From "LCC-Win32 Technical Reference", page 41, by Jacob Navia. Writing the startup code When you click in a program icon, or just type the name of a program at the command line, you invoke implicitly a program that is one of the basic pieces of any operating system: the program loader. This program will search and read for an executable file of the name that corresponds to the name you typed in or to the program the icon points to. It will load that program into RAM, fix it, and then pass control to the program’s entry-point. This is NOT the ‘main’ function (or the WinMain) but a piece of code that prepares the execution of the main line, doing some initializations first. The startup of lcc comes in two flavors: the normal startup of an executable, called lcccrt0.obj, and the DLL startup called libcrt0.obj. Both object files reside in the "lib" directory. The task of that piece of code is to perform the initialization of the standard input/output, and call the ‘main’ or ‘WinMain’ function. Actually, the startup will always call the ‘_main’ function. If the program is a windows program, it doesn’t have any "main" function, so the linker will find a "main" function in the "libc.lib" library file, and link it in. That function will call WinMain. This allows the lcc-win32 system to use only one startup for all .exe programs. After the main function returns, the startup code calls the exit function, that returns control to the operating system. Here is the code for the main function of the startup. _mainCRTStartup: movl %fs :0,%eax ; save the contents of the exception list pushl %ebp ; build a stack frame movl %esp,%ebp push $0xffffffff ; build the exception handler structure pushl $_$ExcepData pushl $__except_handler3 push %eax movl %esp,fs :0 ; set this structure at the top of the exception list subl $16,%esp ; space for local variables push %ebx ; save registers push %esi push %edi mov %esp,-24(%ebp) pushl $__environ ;call GetMainArgs to get the command arguments pushl $___argv ;for the ‘main’ function pushl $___argc call __GetMainArgs pushl __environ ; now push those for _main() pushl ___argv pushl ___argc movl %esp,__InitialStack ; save the top of stack in a global call _main addl $24,%esp xor %ecx,%ecx ; invalidate the exception list element above movl %ecx,-4(%ebp) push %eax call _exit ; finish this process ret ; this is in case _exit returns, very surprising!