今天终于有时间来研究一下一个很大很大的工程编译成一个exe和若干dll后,程序是如果执行它的第一条指令的?操作系统以什么规则来找到应该执行的第一条指令(或说如何找到第一个入口函数的)?
我们以前写windows程序时,都是先写个main()函数,然后再写自己的逻辑,然后编译,然后点击exe就能运行我们的程序了;如果我们用VS2005工具生成一个非空工程,工程会为我们提供一个int_tmain(int argc, _TCHAR*argv[])或WinMain()函数的入口,然后我们在里面添加程序等等。我们上学时这是这样做了,但是很多人这时理所当然的,很少人会去问为什么会这样?
我读了MSDN里面的讲解才弄出点眉目了,其实我们以前所写的以main()函数开始的程序都是一个半成品,剩下的也是与系统息息相关的工作由编译器帮我们代劳了。怎么回事呢?编译器是如何帮我们代劳的呢?那么程序被系统加载时,准确的说是被系统中的加载器加载时又是如何知道编译器在我们写的程序上做了手脚呢?难道编译器和加载器之间有什么协定吗?这一些列的问题,做为刚入行的你是否在心里问过自己没有!?
我们以前写的程序在编译器编译成为一个模块(可能是obj文件或其他形式),然后链接器会将一些所需要的库文件和刚才编译器生成的文件进行链接,最终生成一个exe文件,在所链接的库文件中就包含CRT运行时库,这就是我们今天谈论的主角。在运行时库里面有好一个已经定义如下的函数函数:
(1)mainCRTStartup(或wmainCRTStartup) //使用/SUBSYSTEM:CONSOLE 的应用程序
(2)WinMainCRTStartup(或 wWinMainCRTStartup) //使用/SU