Most programmers think main() is where execution starts. It isn't. By the time your code runs, the OS has already loaded your ELF binary, set up the stack, initialized the heap, resolved dynamic library symbols, and run _start — a function you never wrote.
Digging into this changes how you think about programs. Your program isn't a standalone thing — it's a guest in the OS's house. The runtime environment is pre-loaded. Signals are configured. File descriptors 0, 1, and 2 are already open, pointing at stdin, stdout, and stderr.
The ELF Binary
When you compile a C program, the output isn't raw machine code. It's an ELF (Executable and Linkable Format) binary — a structured file with sections: .text for code, .data for initialized globals, .bss for zero-initialized globals, and metadata describing how to load everything into memory.
The OS reads this format. It maps sections to virtual addresses. It resolves PLT and GOT entries for shared libraries. Then it jumps to _start, not main.
; Simplified _start in x86-64 assembly
_start:
xor rbp, rbp ; mark the outermost stack frame
pop rdi ; argc
mov rsi, rsp ; argv
call main
mov edi, eax ; return value → exit code
call exit
The Bootloader Perspective
Writing a bootloader made all of this visceral. When you're in the bootloader, none of the comforts exist. There's no stack — you set one up yourself. There's no heap. File descriptors don't exist. The screen is memory-mapped I/O.
You configure the Global Descriptor Table. You switch from real mode to protected mode. Then, slowly, you build the world that every program running on your system takes completely for granted.
Why This Matters
Understanding the execution environment before main() makes you a better systems programmer. It explains why global constructors in C++ run before your code. It explains why atexit() handlers run after main returns. It explains why linking order matters.
Most importantly, it dissolves the magic. Programs aren't magic. They're guests in a very carefully prepared house, and understanding how that house is built is one of the most useful things a programmer can do.