0:08Set the stage for the chat
0:08Set the stage for the chat
0:08Set the stage for the chat
1:45Read Nacre314's email regarding typedef'ing of functions
1:45Read Nacre314's email regarding typedef'ing of functions
1:45Read Nacre314's email regarding typedef'ing of functions
6:59A few words on C never having reached maturity on the relationship between code and data
6:59A few words on C never having reached maturity on the relationship between code and data
6:59A few words on C never having reached maturity on the relationship between code and data
9:29On departing from batch files
9:29On departing from batch files
9:29On departing from batch files
12:50Create nacre314 directory and main.cpp
12:50Create nacre314 directory and main.cpp
12:50Create nacre314 directory and main.cpp
15:39Compilation vs Linking
15:39Compilation vs Linking
15:39Compilation vs Linking
17:52The compiler as an auto-detecting stream processor
17:52The compiler as an auto-detecting stream processor
17:52The compiler as an auto-detecting stream processor
21:14Create main2.c, and #include it in main.cpp as a way to make the compiler aware of this file
21:14Create main2.c, and #include it in main.cpp as a way to make the compiler aware of this file
21:14Create main2.c, and #include it in main.cpp as a way to make the compiler aware of this file
26:16Translation units, as evinced by passing individual files to the compiler, versus using the #include approach
26:16Translation units, as evinced by passing individual files to the compiler, versus using the #include approach
26:16Translation units, as evinced by passing individual files to the compiler, versus using the #include approach
32:42C, as opposed to C++, can assume which arguments a function takes without having seen its declaration
32:42C, as opposed to C++, can assume which arguments a function takes without having seen its declaration
32:42C, as opposed to C++, can assume which arguments a function takes without having seen its declaration
45:33Looking at our linker output and our compiled .obj files
45:33Looking at our linker output and our compiled .obj files
45:33Looking at our linker output and our compiled .obj files
48:44"I don't know how to use cars"α
48:44"I don't know how to use cars"α
48:44"I don't know how to use cars"α
48:55Use dumpbin to inspect main.obj, and note that Bar() is without a known address
48:55Use dumpbin to inspect main.obj, and note that Bar() is without a known address
48:55Use dumpbin to inspect main.obj, and note that Bar() is without a known address
56:09Inspect main3.obj, with its corresponding indicator for Bar()
56:09Inspect main3.obj, with its corresponding indicator for Bar()
56:09Inspect main3.obj, with its corresponding indicator for Bar()
58:59The linker prepares an executable that conforms to the OS standard
58:59The linker prepares an executable that conforms to the OS standard
58:59The linker prepares an executable that conforms to the OS standard
1:00:47Call main() in main.cpp and successfully link
1:00:47Call main() in main.cpp and successfully link
1:00:47Call main() in main.cpp and successfully link
1:03:12C runtime standard library, as implicitly included by Windows
1:03:12C runtime standard library, as implicitly included by Windows
1:03:12C runtime standard library, as implicitly included by Windows
1:08:42Set LIB to nothing and note that linking now fails
1:08:42Set LIB to nothing and note that linking now fails
1:08:42Set LIB to nothing and note that linking now fails
1:12:04Create build.bat to control each step in the compilation / linking process
1:12:04Create build.bat to control each step in the compilation / linking process
1:12:04Create build.bat to control each step in the compilation / linking process
1:17:16Entry point, mainCRTStartup()
1:17:16Entry point, mainCRTStartup()
1:17:16Entry point, mainCRTStartup()
1:26:44Use extern "C" to make the compiler comply with the C rules
1:26:44Use extern "C" to make the compiler comply with the C rules
1:26:44Use extern "C" to make the compiler comply with the C rules
1:29:33Specifying the SUBSYSTEM to enable the linker to recognise this as the entry point on Windows
1:29:33Specifying the SUBSYSTEM to enable the linker to recognise this as the entry point on Windows
1:29:33Specifying the SUBSYSTEM to enable the linker to recognise this as the entry point on Windows
1:35:01Inspect the .exe output of the linker
1:35:01Inspect the .exe output of the linker
1:35:01Inspect the .exe output of the linker
1:42:48main.cpp: Introduce void *FunctionPointer = Foo() and inspect the .obj file
1:42:48main.cpp: Introduce void *FunctionPointer = Foo() and inspect the .obj file
1:42:48main.cpp: Introduce void *FunctionPointer = Foo() and inspect the .obj file
1:47:30Dereferencing a function pointer
1:47:30Dereferencing a function pointer
1:47:30Dereferencing a function pointer
1:49:32Relative addressing and Address Space Layout Randomization (ASLR)
1:49:32Relative addressing and Address Space Layout Randomization (ASLR)
1:49:32Relative addressing and Address Space Layout Randomization (ASLR)
1:53:48Manually deference the function pointer pointing to Foo()
1:53:48Manually deference the function pointer pointing to Foo()
1:53:48Manually deference the function pointer pointing to Foo()
1:57:34main.cpp: Introduce Five() and watch it operate in the debugger
1:57:34main.cpp: Introduce Five() and watch it operate in the debugger
1:57:34main.cpp: Introduce Five() and watch it operate in the debugger
2:03:18How C calls a function1
2:03:18How C calls a function1
2:03:18How C calls a function1
2:07:47Using typedef on the function signature in order to enable the compiler to generate the preamble to a call instruction
2:07:47Using typedef on the function signature in order to enable the compiler to generate the preamble to a call instruction
2:07:47Using typedef on the function signature in order to enable the compiler to generate the preamble to a call instruction
2:14:11main.cpp: Introduce CodeForFive[] to contain the code for Five() as an array of characters
2:14:11main.cpp: Introduce CodeForFive[] to contain the code for Five() as an array of characters
2:14:11main.cpp: Introduce CodeForFive[] to contain the code for Five() as an array of characters
2:16:58Inspect the .data section in our COFF .obj file
2:16:58Inspect the .data section in our COFF .obj file
2:16:58Inspect the .data section in our COFF .obj file
2:24:08Step through our call to CodeForFive[] and hit the access violation for the attempt to execute code not marked as executable
2:24:08Step through our call to CodeForFive[] and hit the access violation for the attempt to execute code not marked as executable
2:24:08Step through our call to CodeForFive[] and hit the access violation for the attempt to execute code not marked as executable
2:26:43VirtualAlloc()2 and Memory Protection Constants3
2:26:43VirtualAlloc()2 and Memory Protection Constants3
2:26:43VirtualAlloc()2 and Memory Protection Constants3
2:35:13Step through our call to VirtualAlloc() and on to CodeForFive[]
2:35:13Step through our call to VirtualAlloc() and on to CodeForFive[]
2:35:13Step through our call to VirtualAlloc() and on to CodeForFive[]
2:38:58main.cpp: Enable CodeForFive[] to return any 4-byte value
2:38:58main.cpp: Enable CodeForFive[] to return any 4-byte value
2:38:58main.cpp: Enable CodeForFive[] to return any 4-byte value
2:42:49Relative calls, using address offsets and function sizes
2:42:49Relative calls, using address offsets and function sizes
2:42:49Relative calls, using address offsets and function sizes
2:55:23main.cpp: Rename CodeForFive[] to Code[] and enable it to perform a relative call to Five()
2:55:23main.cpp: Rename CodeForFive[] to Code[] and enable it to perform a relative call to Five()
2:55:23main.cpp: Rename CodeForFive[] to Code[] and enable it to perform a relative call to Five()
3:01:39Step through our generated relative call to Five()
3:01:39Step through our generated relative call to Five()
3:01:39Step through our generated relative call to Five()
3:04:16The code that the compiler generates is just bytes
3:04:16The code that the compiler generates is just bytes
3:04:16The code that the compiler generates is just bytes
3:05:48Multiple separate executable pieces
3:05:48Multiple separate executable pieces
3:05:48Multiple separate executable pieces
3:07:57How programs were executed historically, before multitasking operating systems
3:07:57How programs were executed historically, before multitasking operating systems
3:07:57How programs were executed historically, before multitasking operating systems
3:10:53Secondary link phase that happens upon loading an executable
3:10:53Secondary link phase that happens upon loading an executable
3:10:53Secondary link phase that happens upon loading an executable
3:12:48Import libraries, kernel32.lib as a dynamically linked library (dll), and what Windows' dynamic linker does
3:12:48Import libraries, kernel32.lib as a dynamically linked library (dll), and what Windows' dynamic linker does
3:12:48Import libraries, kernel32.lib as a dynamically linked library (dll), and what Windows' dynamic linker does
3:22:38Compare the hex dump of main.exe with the running code after being dynamically linked
3:22:38Compare the hex dump of main.exe with the running code after being dynamically linked
3:22:38Compare the hex dump of main.exe with the running code after being dynamically linked
3:35:46The linker links with an expectation of what the base address probably would be
3:35:46The linker links with an expectation of what the base address probably would be
3:35:46The linker links with an expectation of what the base address probably would be
3:37:05Continue to compare the raw data before and after dynamic linking
3:37:05Continue to compare the raw data before and after dynamic linking
3:37:05Continue to compare the raw data before and after dynamic linking
3:41:38How Handmade Hero uses Windows' mechanism for dynamic linking in order to perform hot reloading
3:41:38How Handmade Hero uses Windows' mechanism for dynamic linking in order to perform hot reloading
3:41:38How Handmade Hero uses Windows' mechanism for dynamic linking in order to perform hot reloading
3:44:31Inspect the dumpbin imports and exports for win32_handmade.exe and handmade.dll
3:44:31Inspect the dumpbin imports and exports for win32_handmade.exe and handmade.dll
3:44:31Inspect the dumpbin imports and exports for win32_handmade.exe and handmade.dll
3:48:17Portable Executable4
3:48:17Portable Executable4
3:48:17Portable Executable4
3:50:01The CPU is executing code somewhere, indicated by the contents of the RIP register
3:50:01The CPU is executing code somewhere, indicated by the contents of the RIP register
3:50:01The CPU is executing code somewhere, indicated by the contents of the RIP register
3:54:13The stack location is referenced off the RSP register
3:54:13The stack location is referenced off the RSP register
3:54:13The stack location is referenced off the RSP register
3:56:24pseudonym73 Worth a plug
5🗪
3:56:24pseudonym73 Worth a plug
5🗪
3:56:24pseudonym73 Worth a plug
5🗪
3:57:20butwhynot1 Technically, you need to call FlushInstructionCache when you generate code
🗪
3:57:20butwhynot1 Technically, you need to call FlushInstructionCache when you generate code
🗪
3:57:20butwhynot1 Technically, you need to call FlushInstructionCache when you generate code
🗪
3:59:26FlushInstructionCache6
3:59:26FlushInstructionCache6
3:59:26FlushInstructionCache6
4:01:36main.cpp: Demo usage of FlushInstructionCache()
4:01:36main.cpp: Demo usage of FlushInstructionCache()
4:01:36main.cpp: Demo usage of FlushInstructionCache()
4:08:35insofaras I think something like /SECTION:.data,RWE and /NXCOMPAT:NO to link.exe might work for the non-VirtualProtect code in array thing
🗪
4:08:35insofaras I think something like /SECTION:.data,RWE and /NXCOMPAT:NO to link.exe might work for the non-VirtualProtect code in array thing
🗪
4:08:35insofaras I think something like /SECTION:.data,RWE and /NXCOMPAT:NO to link.exe might work for the non-VirtualProtect code in array thing
🗪
4:09:30nacre314 Maybe this episode belongs in the Intro to C week as episode 6?
🗪
4:09:30nacre314 Maybe this episode belongs in the Intro to C week as episode 6?
🗪
4:09:30nacre314 Maybe this episode belongs in the Intro to C week as episode 6?
🗪
4:09:39user549 Maybe the smallest crt ever
7🗪
4:09:39user549 Maybe the smallest crt ever
7🗪
4:09:39user549 Maybe the smallest crt ever
7🗪
4:10:02filiadelski Is there a low-level reason you don't like virtual functions? My understanding of them is that they're basically just function pointers in a table that is dereferenced
🗪
4:10:02filiadelski Is there a low-level reason you don't like virtual functions? My understanding of them is that they're basically just function pointers in a table that is dereferenced
🗪
4:10:02filiadelski Is there a low-level reason you don't like virtual functions? My understanding of them is that they're basically just function pointers in a table that is dereferenced
🗪
4:11:45ingenero First of all, thank you so much for this stream! At the beginning you mentioned you hadn't done some of these things for a while. My question is, in what context did you originally learn and apply all this information? It seems like spending time at work exploring this may be considered time taken away from actually being "productive". Is it just something you have to learn on your own time?
🗪
4:11:45ingenero First of all, thank you so much for this stream! At the beginning you mentioned you hadn't done some of these things for a while. My question is, in what context did you originally learn and apply all this information? It seems like spending time at work exploring this may be considered time taken away from actually being "productive". Is it just something you have to learn on your own time?
🗪
4:11:45ingenero First of all, thank you so much for this stream! At the beginning you mentioned you hadn't done some of these things for a while. My question is, in what context did you originally learn and apply all this information? It seems like spending time at work exploring this may be considered time taken away from actually being "productive". Is it just something you have to learn on your own time?
🗪