操作系统调用exec()函数。 实际上,它通常调用诸如_init之类的名为“陌生事物”的事物。C编译器将标准库链接到每个提供此操作系统定义的入口点的应用程序,然后调用main()。
编辑:显然,这对于某些人来说不够详细和正确。
许多Unix OS使用的可执行和可链接格式(ELF)定义了入口点地址。 在操作系统完成其exec()调用之后,程序即开始在该位置运行。 在Linux系统上,这是_init。
从objdump -d:
Disassembly of section .init:
08049f08 <_init>:
8049f08: 55 push %ebp
8049f09: 89 e5 mov %esp,%ebp
8049f0b: 83 ec 08 sub $0x8,%esp
8049f0e: e8 a1 05 00 00 call 804a4b4
8049f13: e8 f8 05 00 00 call 804a510
8049f18: e8 d3 50 00 00 call 804eff0 <__do_global_ctors_aux>
8049f1d: c9 leave
8049f1e: c3 ret
从readelf -d:
0x00000001 (NEEDED) Shared library: [libstdc++.so.6]
0x00000001 (NEEDED) Shared library: [libm.so.6]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8049f08
0x0000000d (FINI) 0x804f018
0x00000004 (HASH) 0x8048168
0x00000005 (STRTAB) 0x8048d8c
0x00000006 (SYMTAB) 0x804867c
0x0000000a (STRSZ) 3313 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8059114
0x00000002 (PLTRELSZ) 688 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8049c58
0x00000011 (REL) 0x8049be0
0x00000012 (RELSZ) 120 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x8049b60
0x6fffffff (VERNEEDNUM) 3
0x6ffffff0 (VERSYM) 0x8049a7e
0x00000000 (NULL) 0x0
您可以看到INIT等于_init的地址。
frame_dummy和__do_global_ctors_aux的代码在一组名为crtbegin.o和crtend.o(以及这些名称的变体)的文件中。 这些是海湾合作委员会的一部分。 该代码执行C程序所需的各种操作,例如设置stdin,stdout,全局和静态变量以及其他操作。
以下文章很好地描述了它在Linux中的功能(从下面的答案中以较少的票数得出):[http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html]
我相信其他人的答案已经描述了Windows的功能。