我正在寻找一个更技术性的解释然后操作系统调用该功能。 任何人都可以帮助我或指向我的网站或书籍吗?
答案 0 :(得分:25)
.exe文件(或其他平台上的等效文件)包含“入口点”地址。对于第一个近似值,OS将.EXE文件的相关部分加载到ram中,然后跳转到入口点。
正如其他人所说,这个入口点不是'main',而是成为运行时库的一部分 - 它将执行诸如初始化静态对象,设置argc / argv参数,设置stdin /之类的操作stdout / stderr等等。完成所有这些后,它将调用你的main()函数。当主要退出时,运行时会经历一个将返回代码传递回环境,调用静态析构函数,调用_atexit例程等的类似过程。
如果您有MS工具(可能不是免费赠送的工具),那么您拥有所有运行时源,并且一种简单的方法来查看它是在main()方法的右括号上放置一个断点,并且单个退回到运行时。
答案 1 :(得分:8)
main()
是C库的一部分,不是系统函数。我不知道OS X或Linux,但Windows通常使用WinMainCRTStartup()
启动程序。此符号初始化您的进程,提取命令行参数和环境(argc, argv, end
)并调用main()
。它还负责调用应在main()
之后运行的任何代码,例如atexit()
。
通过查看Visual Studio文件,您应该能够找到WinMainCRTStartup
的默认实现,以查看它的作用。
您还可以定义自己的函数以在启动时调用,这可以通过更改链接器选项中的“入口点”来完成。这通常是一个不带参数的函数,并返回一个void。
答案 2 :(得分:5)
就Windows而言,入口点功能是:
void __cdecl mainCRTStartup( void ) {}
void __stdcall WinMainCRTStartup( void ) {}
BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}
在普通的main / WinMain / DllMain上使用这些的唯一原因是你想使用自己的运行时库(如果你想要更小的文件大小或自定义功能)
对于自定义运行时实现和其他获取较小PE文件的技巧,请参阅:
答案 3 :(得分:1)
Expert C++/CLI(请参阅第279页)有关于本机,混合和纯CLR程序集的不同引导方案的非常具体的细节。
答案 4 :(得分:1)
这取决于操作系统。 在OS X中,mach头中有一个包含EIP(指令指针)寄存器起始地址的帧。
加载二进制文件后,操作系统将从此地址启动执行:
cristi:test diciu$ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD cmd LC_UNIXTHREAD cmdsize 80 flavor i386_THREAD_STATE count i386_THREAD_STATE_COUNT [..] ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000 [..]
地址是二进制文件中“start”函数的地址:
cristi:test diciu$ nm ./a.out 0000200c D _NXArgc 00002008 D _NXArgv 00002000 D ___progname 00001fe0 t __dyld_func_lookup 00001000 A __mh_execute_header [..] 00001f8c T start
在Mac OS X中,它是首先调用的“start”函数,甚至在“main”函数之前:
(gdb) b start Breakpoint 1 at 0x1f90 (gdb) b main Breakpoint 2 at 0x1ff4 (gdb) r Starting program: /Users/diciu/Programming/test/a.out Reading symbols for shared libraries ++. done Breakpoint 1, 0x00001f90 in start ()
答案 5 :(得分:0)
您可以查看以下链接:
答案 6 :(得分:0)
如果您对与Windows和Win32 API相关的书感兴趣,请尝试
Jeffrey Richter编写的“Microsoft Windows编程应用程序”。