Hasty Briefsbeta

Bilingual

Writing a (valid) C program without main()

3 hours ago
  • Most programming languages start execution from a main() function, but C is chosen for this tutorial because it's closest to the operating system without requiring assembly.
  • The C compilation pipeline consists of four stages: preprocessing (cpp), compilation (cc1), assembly (as), and linking (ld/collect2).
  • The preprocessor handles directives like #include and #define, expanding macros and producing larger .i files.
  • The compiler generates assembly code (.s files), which can be optimized using flags like -O0, -O2, or -Os, changing the structure of loops and operations.
  • The assembler turns assembly into object files (.o), while the linker resolves symbols and adds startup code (crt files) to produce the final executable.
  • The real entry point is _start, not main(); by providing a custom _start and skipping startup files with -nostartfiles, you can create a program without main() that directly uses kernel syscalls.
  • Without glibc initialization, functions like printf fail silently; raw syscalls (e.g., sys_write and sys_exit) are needed for low-level operations.