When writing a Win32 application, a WinMain function must be implemented in the source code. But Windows program execution does not start from the WinMain function. The first thing to be executed is the code related to the startup function, which is generated by the compiler. The startup code completes the initialization process, and then calls the WinMain function.
For Visual C++ programs, it calls the C/C++ runtime startup function, which is responsible for initializing the C/C++ runtime library. Visual C++ is equipped with the source code of the C runtime library, the source code of the startup function can be found in the crtsrccrt0.c file (Visual C++ must select the option to install the source code during installation); and the startup code for the console program is stored in crtsrcwincmdln. c file.
All C/C++ runtime startup functions do basically the same thing: retrieve the command line pointer to the new process, retrieve the environment variable pointer to the new process, initialize global variables, initialize the memory stack, etc. When all initialization operations are complete, the startup function calls the application's entry point function. Calling the WinMain function looks like this:
1
2
3
|
<span style
=
"font-size: 13.86px;"
>GetStartupInfo (&StartupInfo);
Int
nMainRetVal
=
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;"
>
00401180
push ebp
00401181
mov ebp, esp
00401183
push FFFFFFFF
00401185
push
004040D0
0040118A
push
00401CB4
0040118F
mov eax, dword ptr fs:[
00000000
]
00401195
push eax
00401196
mov dword ptr fs:[
00000000
], esp
0040119D
sub esp,
00000058
004011A0
push ebx
004011A1
push esi
004011A2
push edi
004011A3
mov dword ptr [ebp
-
18
], esp
004011A6
Call KERNEL32.GetVersion ; 确定Windows系统版本
……
004011F4
Call KERNEL32.GetCommandLineA ; 指向进程的完整命令行的指针
……
0040121E
push eax
0040121F
Call KERNEL32.GetStartupInfoA ; 获取一个进程的启动信息
……
00401241
push esi
00401242
Call KERNEL32.GetModuleHandleA ; 返回进程地址空间执行文件基地址
00401248
push eax
00401249
call
00401000
; 调用用户编写的进入点函数WinMain
; 分析程序时,直接跳到
401000
即可
0040124E
mov dword ptr [ebp
-
60
], eax
00401251
push eax
00401252
call
004012EC
; 退出程序
……
0040126A
ret
<
/
span>
|