在编写Win32应用程序时,都必须在源码里实现一个WinMain函数。但Windows程序执行并不是从WinMain函数开始的,首先被执行的是启动函数相关代码,这段代码是编译器生成的。启动代码完成初始化进程,再调用WinMain函数。
对于Visual C++程序来说,它调用的是C/C++运行时启动函数,该函数负责对C/C++运行库进行初始化。Visual C++配有C运行库的源代码,可以在crtsrccrt0.c文件中找到启动函数的源代码(安装时Visual C++必须选取安装源代码选项);而用于控制台程序的启动代码存放在crtsrcwincmdln.c文件中。
所有的C/C++运行时启动函数的作用基本都是相同的:检索指向新进程的命令行指针,检索指向新进程的环境变量指针,全局变量初始化,内存堆栈初始化等。当所有的初始化操作完毕后,启动函数就调用应用程序的进入点函数。调用WinMain函数如下所示:
| 1 2 3 | <span style="font-size: 13.86px;">GetStartupInfo (&StartupInfo);IntnMainRetVal =WinMain(GetModuleHandle(NULL),NULL,pszCommandLineAnsi,(StartupInfo.dwFlags&STARTF_USESHOWWINDOW)?StartupInfo.wShowWindow:SW__SHOWDEFAULT);</span>
 | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span style="font-size: 13.86px;">00401180push ebp00401181mov ebp, esp00401183push FFFFFFFF00401185push 004040D00040118Apush 00401CB40040118Fmov      eax, dword ptr fs:[00000000]00401195push eax00401196mov  dword ptr fs:[00000000], esp0040119Dsub  esp, 00000058004011A0push ebx004011A1push esi004011A2push edi004011A3mov dword ptr [ebp-18], esp004011A6Call KERNEL32.GetVersion            ; 确定Windows系统版本……  004011F4Call KERNEL32.GetCommandLineA       ; 指向进程的完整命令行的指针…… 0040121Epush eax0040121FCall KERNEL32.GetStartupInfoA   ; 获取一个进程的启动信息……  00401241push esi00401242Call KERNEL32.GetModuleHandleA  ; 返回进程地址空间执行文件基地址00401248push eax00401249call 00401000; 调用用户编写的进入点函数WinMain                                            ; 分析程序时,直接跳到401000即可0040124Emov dword ptr [ebp-60], eax00401251push eax00401252call 004012EC; 退出程序…… 0040126Aret</span>
 | 
原文:https://www.cnblogs.com/blck/p/8970447.html