[32位汇编系列]002 - 创建标准的windows窗口(3)
2009-07-13 23:54
543 查看
接着上面一篇文章
, 下面是反汇编代码的对照讲解:
现在我们来看一看反汇编的代码:
00401000
/.
55
push ebp
00401001 |.
8BEC
mov ebp, esp
00401003 |. 83C4 AC
add esp, -54
00401006 |. 8B45 0C
mov eax, dword ptr [ebp+C]
00401009 |. 83F8
0F
cmp eax, 0F
0040100C |. 75
55
jnz short 00401063
0040100E |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401011 |.
50
push
eax
; /pPaintstruct
00401012 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
00401015 |. E8 B0010000 call
<jmp.&user32.BeginPaint>
; /BeginPaint
0040101A |. 8945
AC
mov dword ptr [ebp-54], eax
0040101D |. 68 00FF0000 push
0FF00
; /Color = <LIGHTGREEN>
00401022 |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
00401025 |. E8 24020000 call
<jmp.&gdi32.SetTextColor> ;
/SetTextColor
0040102A |. 6A
00
push
0
; /Color = <BLACK>
0040102C |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
0040102F |. E8 14020000 call
<jmp.&gdi32.SetBkColor>
; /SetBkColor
00401034 |. 8D45
B0
lea eax, dword ptr [ebp-50]
00401037 |.
50
push
eax
; /pRect
00401038 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040103B |. E8 B4010000 call
<jmp.&user32.GetClientRect> ;
/GetClientRect
00401040 |. 6A
25
push
25
; /Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE
00401042 |. 8D45 B0
lea eax, dword ptr
[ebp-50] ; |
00401045 |.
50
push
eax
; |pRect
00401046 |. 6A
FF
push
-1
; |Count = FFFFFFFF (-1.)
00401048 |. 68 75204000 push
00402075
; |Text = "things have changed from now"
0040104D |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
00401050 |. E8 93010000 call
<jmp.&user32.DrawTextA>
; /DrawTextA
00401055 |. 8D45
C0
lea eax, dword ptr [ebp-40]
00401058 |.
50
push
eax
; /pPaintstruct
00401059 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
0040105C |. E8 8D010000 call
<jmp.&user32.EndPaint>
; /EndPaint
00401061 |. EB
2E
jmp short 00401091
00401063 |> 83F8 10
cmp eax, 10
00401066 |. 75
14
jnz short 0040107C
00401068 |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
0040106E |. E8 69010000 call
<jmp.&user32.DestroyWindow> ;
/DestroyWindow
00401073 |. 6A
00
push
0
; /ExitCode = 0
00401075 |. E8 98010000 call
<jmp.&user32.PostQuitMessage> ; /PostQuitMessage
0040107A |. EB
15
jmp short 00401091
0040107C |> FF75
14 push dword
ptr
[ebp+14]
; /lParam
0040107F |. FF75 10
push dword ptr
[ebp+10]
; |wParam
00401082 |. FF75 0C
push dword ptr
[ebp+C]
; |Message
00401085 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
00401088 |. E8 49010000 call
<jmp.&user32.DefWindowProcA> ;
/DefWindowProcA
0040108D |.
C9
leave
0040108E |. C2 1000
retn 10
00401091 |> 33C0
xor eax, eax
00401093 |.
C9
leave
00401094 /. C2
1000
retn 10
00401097 /$
55
push ebp
00401098 |.
8BEC
mov ebp, esp
0040109A |. 83C4
B4
add esp, -4C
0040109D |. 6A 00
push
0
; /pModule = NULL
0040109F |. E8 92010000 call
<jmp.&kernel32.GetModuleHandleA> ; /GetModuleHandleA
004010A4 |. A3 00304000 mov
dword ptr [403000], eax
004010A9 |. 6A 30
push
30
; /Length = 30 (48.)
004010AB |. 8D45 D0
lea eax, dword ptr
[ebp-30] ; |
004010AE |.
50
push
eax
; |Destination
004010AF |. E8 88010000 call
<jmp.&kernel32.RtlZeroMemory> ; /RtlZeroMemory
004010B4 |. C745 D0 30000>mov dword ptr
[ebp-30], 30
004010BB |. C745 D4 03000>mov dword ptr
[ebp-2C], 3
004010C2 |. C745 D8 00104>mov dword ptr
[ebp-28], 00401000
004010C9 |. FF35 00304000 push dword ptr [403000]
004010CF |. 8F45
E4
pop dword ptr [ebp-1C]
004010D2 |. 68 007F0000
push
7F00
; /RsrcName = IDI_APPLICATION
004010D7 |. 6A
00
push
0
; |hInst = NULL
004010D9 |. E8 28010000 call
<jmp.&user32.LoadIconA>
; /LoadIconA
004010DE |. 8945
E8
mov dword ptr [ebp-18], eax
004010E1 |. 8945
FC
mov dword ptr [ebp-4], eax
004010E4 |. 68 007F0000 push
7F00
; /RsrcName = IDC_ARROW
004010E9 |. 6A
00
push
0
; |hInst = NULL
004010EB |. E8 10010000 call
<jmp.&user32.LoadCursorA> ;
/LoadCursorA
004010F0 |. 8945
EC
mov dword ptr [ebp-14], eax
004010F3 |. 6A 04
push
4
; /ObjType = BLACK_BRUSH
004010F5 |. E8 48010000 call
<jmp.&gdi32.GetStockObject> ;
/GetStockObject
004010FA |. 8945
F0
mov dword ptr [ebp-10], eax
004010FD |. C745 F8 68204>mov dword ptr
[ebp-8], 00402068 ; ASCII
"NormalWindow"
00401104 |. 8D45
D0
lea eax, dword ptr [ebp-30]
00401107 |.
50
push
eax
; /pWndClassEx
00401108 |. E8 0B010000 call
<jmp.&user32.RegisterClassExA> ; /RegisterClassExA
0040110D |.
0BC0
or eax, eax
0040110F |. 75
15
jnz short 00401126
00401111 |. 6A
10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401113 |. 68 92204000 push
00402092
; |Title = "Error"
00401118 |. 68 98204000 push
00402098
; |Text = "This program requires NT !"
0040111D |. 6A
00
push
0
; |hOwner = NULL
0040111F |. E8 E8000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401124 |.
C9
leave
00401125 |.
C3
retn
00401126 |> 6A 00
push
0
; /lParam = NULL
00401128 |. FF35 00304000 push dword ptr
[403000]
; |hInst = NULL
0040112E |. 6A
00
push
0
; |hMenu = NULL
00401130 |. 6A
00
push
0
; |hParent = NULL
00401132 |. 68 00000080 push
80000000
; |Height = 80000000 (-2147483648.)
00401137 |. 68 00000080 push
80000000
; |Width = 80000000 (-2147483648.)
0040113C |. 68 00000080 push
80000000
; |Y = 80000000 (-2147483648.)
00401141 |. 68 00000080 push
80000000
; |X = 80000000 (-2147483648.)
00401146 |. 68 0000CF00 push
0CF0000
; |Style = WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION
0040114B |. 68 68204000 push
00402068
; |WindowName = "NormalWindow"
00401150 |. 68 68204000 push
00402068
; |Class = "NormalWindow"
00401155 |. 68 00020000 push
200
; |ExtStyle = WS_EX_CLIENTEDGE
0040115A |. E8 71000000 call
<jmp.&user32.CreateWindowExA> ; /CreateWindowExA
0040115F |.
0BC0
or eax, eax
00401161 |. 75
15
jnz short 00401178
00401163 |. 6A 10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401165 |. 68 92204000 push
00402092
; |Title = "Error"
0040116A |. 68 B3204000 push
004020B3
; |Text = "CreateWindow Error."
0040116F |. 6A
00
push
0
; |hOwner = NULL
00401171 |. E8 96000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401176 |.
C9
leave
00401177 |.
C3
retn
00401178 |> A3 04304000 mov
dword ptr [403004], eax
0040117D |. 6A 01
push
1
; /ShowState = SW_SHOWNORMAL
0040117F |. FF35 04304000 push dword ptr
[403004]
; |hWnd = NULL
00401185 |. E8 94000000 call
<jmp.&user32.ShowWindow>
; /ShowWindow
0040118A |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
00401190 |. E8 95000000 call
<jmp.&user32.UpdateWindow> ;
/UpdateWindow
00401195 |> 6A
00 /
push
0
; /MsgFilterMax = 0
00401197 |. 6A 00
| push
0
; |MsgFilterMin = 0
00401199 |. 6A 00
| push
0
; |hWnd = NULL
0040119B |. 8D45 B4
| lea eax, dword ptr
[ebp-4C] ; |
0040119E |.
50
| push
eax
; |pMsg
0040119F |. E8 56000000 |call
<jmp.&user32.GetMessageA> ;
/GetMessageA
004011A4 |.
0BC0
| or eax, eax
004011A6 |. 74 14
| je short 004011BC
004011A8 |. 8D45 B4
| lea eax, dword ptr [ebp-4C]
004011AB |.
50
| push
eax
; /pMsg
004011AC |. E8 73000000 |call
<jmp.&user32.TranslateMessage> ; /TranslateMessage
004011B1 |. 8D45 B4
| lea eax, dword ptr [ebp-4C]
004011B4 |.
50
| push
eax
; /pMsg
004011B5 |. E8 28000000 |call
<jmp.&user32.DispatchMessageA> ; /DispatchMessageA
004011BA |.^ EB D9
/ jmp short 00401195
004011BC |>
C9
leave
004011BD /.
C3
retn
004011BE >/$ E8 D4FEFFFF call 00401097
004011C3 |. 6A
00
push
0
; /ExitCode = 0
004011C5 /. E8 66000000 call
<jmp.&kernel32.ExitProcess> ;
/ExitProcess
004011CA $- FF25 60204000 jmp dword ptr
[<&user32.BeginPaint>] ; user32.BeginPaint
004011D0 $- FF25 58204000 jmp dword ptr
[<&user32.CreateWindow>; user32.CreateWindowExA
004011D6 $- FF25 54204000 jmp dword ptr
[<&user32.DefWindowPro>; user32.DefWindowProcA
004011DC $- FF25 4C204000 jmp dword ptr
[<&user32.DestroyWindo>; user32.DestroyWindow
004011E2 $- FF25 50204000 jmp dword ptr
[<&user32.DispatchMess>; user32.DispatchMessageA
004011E8 $- FF25 48204000 jmp dword ptr
[<&user32.DrawTextA>] ; user32.DrawTextA
004011EE $- FF25 44204000 jmp dword ptr
[<&user32.EndPaint>] ; user32.EndPaint
004011F4 $- FF25 30204000 jmp dword ptr
[<&user32.GetClientRec>; user32.GetClientRect
004011FA $- FF25 20204000 jmp dword ptr
[<&user32.GetMessageA>>; user32.GetMessageA
00401200 $- FF25 24204000 jmp dword ptr
[<&user32.LoadCursorA>>; user32.LoadCursorA
00401206 $- FF25 28204000 jmp dword ptr
[<&user32.LoadIconA>] ; user32.LoadIconA
0040120C $- FF25 2C204000 jmp dword ptr
[<&user32.MessageBoxA>>; user32.MessageBoxA
00401212 $- FF25 5C204000 jmp dword ptr
[<&user32.PostQuitMess>; user32.PostQuitMessage
00401218 $- FF25 34204000 jmp dword ptr
[<&user32.RegisterClas>; user32.RegisterClassExA
0040121E $- FF25 38204000 jmp dword ptr
[<&user32.ShowWindow>] ; user32.ShowWindow
00401224 $- FF25 3C204000 jmp dword ptr
[<&user32.TranslateMes>; user32.TranslateMessage
0040122A $- FF25 40204000 jmp dword ptr
[<&user32.UpdateWindow>; user32.UpdateWindow
00401230 .- FF25 14204000 jmp dword ptr
[<&kernel32.ExitProces>; kernel32.ExitProcess
00401236 $- FF25 10204000 jmp dword ptr
[<&kernel32.GetModuleH>; kernel32.GetModuleHandleA
0040123C $- FF25 18204000 jmp dword ptr
[<&kernel32.RtlZeroMem>; ntdll.RtlZeroMemory
00401242 $- FF25 04204000 jmp dword ptr
[<&gdi32.GetStockObjec>; GDI32.GetStockObject
00401248 $- FF25 00204000 jmp dword ptr
[<&gdi32.SetBkColor>] ; GDI32.SetBkColor
0040124E $- FF25 08204000 jmp dword ptr
[<&gdi32.SetTextColor>>; GDI32.SetTextColor
经过反汇编后的代码,
看起来是不是有些郁闷?
跟源程序比,
显得有些乱七八糟的,
其实好好分析一下,
也不难理解:
对于
004011CA $- FF25
60204000 jmp dword ptr [<&user32.BeginPaint>]
; user32.BeginPaint
以及后面的部分,我们就不需要去看了,
很显然,
是程序中用到的一些导入函数
004011BE
>/$ E8 D4FEFFFF call 00401097
004011C3 |. 6A 00
push
0
; /ExitCode = 0
004011C5 /. E8 66000000 call
<jmp.&kernel32.ExitProcess> ;
/ExitProcess
这个便是标签
start 和
end start 之间的内容
call 00401097 显然是调用主过程
_WinMain,
00401097是
_WinMain的地址
push 0
call <jmp.&kernel32.ExitProcess>
这
2句调用
ExitProcess函数,
传入的退出代码为
0
现在看看主过程
_WinMain对应的反汇编代码:
00401097
/$ 55
push ebp
00401098 |.
8BEC
mov ebp, esp
0040109A |. 83C4 B4
add esp, -4C
这
3
句代码首先保存
ebp
的值,
然后将当前栈指针赋值给
ebp
,好在后面
通过
ebp
来访问各个参数
add esp, -4C
为局部变量
local
@stWC:WNDCLASSEX
local @stMsg:MSG
分配临时栈空间
, sizeof @stWC
和
sizeof @stMsg
加起来正好
4CH
个字节
0040109D |. 6A 00
push
0
; /pModule = NULL
0040109F |. E8 92010000 call
<jmp.&kernel32.GetModuleHandleA> ; /GetModuleHandleA
004010A4 |. A3 00304000 mov
dword ptr [403000], eax
调用
kernel32.dll
模块中的
GetModuleHandleA
函数,得到当前的实例句柄,
并且保存在全局变量
hInstance
中,
全局变量
hInstance
的地址为
403000
004010A9
|. 6A 30
push
30
; /Length = 30 (48.)
004010AB |. 8D45 D0
lea eax, dword ptr
[ebp-30] ; |
004010AE |.
50
push
eax
; |Destination
004010AF |. E8 88010000 call
<jmp.&kernel32.RtlZeroMemory> ; /RtlZeroMemory
调用
Kernel32
模块中的
RtlZeroMemory
函数,
将局部变量
@stWC
结构填充为
0
其中
@stWC
结构的大小为
30H
个字节,
地址是
ebp-30
004010B4 |. C745 D0 30000>mov dword ptr
[ebp-30], 30
相当于
mov @stWC.cbSize, sizeof WNDCLASSEX
004010BB |. C745 D4 03000>mov dword ptr
[ebp-2C], 3
相当于
mov
@stWC.style, CS_HREDRAW or CS_VREDRAW
004010C2
|. C745 D8 00104>mov dword ptr [ebp-28],
00401000
相当于
mov
@stWC.lpfnWndProc, offset _WinProc
004010C9
|. FF35 00304000 push dword ptr [403000]
相当于
push
hInstance
004010CF
|. 8F45 E4
pop dword ptr [ebp-1C]
相当于
pop
@stWC.hInstance
004010D2
|. 68 007F0000 push
7F00
; /RsrcName = IDI_APPLICATION
004010D7
|. 6A 00
push
0
; |hInst = NULL
004010D9 |. E8 28010000 call
<jmp.&user32.LoadIconA>
; /LoadIconA
004010DE |. 8945 E8
mov dword ptr [ebp-18], eax
004010E1 |. 8945 FC
mov dword ptr [ebp-4], eax
调用
user32.dll
模块中的
LoadIcon
函数,得到默认图标,分别填充
@stWC
结构的
@stWC.hIcon
和
@stWC.hIconSm
域
004010E4
|. 68 007F0000 push
7F00
; /RsrcName = IDC_ARROW
004010E9 |. 6A 00
push
0
; |hInst = NULL
004010EB |. E8 10010000 call
<jmp.&user32.LoadCursorA> ;
/LoadCursorA
004010F0 |. 8945 EC
mov dword ptr [ebp-14], eax
调用
user32
模块中的
LoadCursor
函数,
得到默认光标,填充
@stWC
结构的
@stWC.hCursor
域
004010F3
|. 6A 04
push
4
; /ObjType = BLACK_BRUSH
004010F5 |. E8 48010000 call
<jmp.&gdi32.GetStockObject> ;
/GetStockObject
004010FA |. 8945 F0
mov dword ptr [ebp-10], eax
调用
gdi32
模块中的
GetStockObject
填充
@stWC
结构的
@stWC.hbrBackground
域
004010FD
|. C745 F8 68204>mov dword ptr [ebp-8],
00402068 ; ASCII "NormalWindow"
用字符串
'NormalWindow'
填充结构
@stWC
的
@stWC.lpszClassName
域
00401104
|. 8D45 D0
lea eax, dword ptr [ebp-30]
将局部变量
@stWC
的地址放入
eax
中
00401107
|. 50
push
eax
; /pWndClassEx
00401108 |. E8 0B010000 call
<jmp.&user32.RegisterClassExA> ; /RegisterClassExA
调用
user32
模块中的
RegisterClassExA
注册窗口类
0040110D
|. 0BC0
or eax, eax
看
RegisterClassExA
的返回值
ea
是否为
0
,如果为
0
,
则调用
MessageBoxA
对话框,显示错误讯息,并且执行
leave
retn
指令退出程序
否则,执行
jnz short 00401126
跳转到窗口创建部分
0040110F |. 75
15 jnz
short 00401126
00401111 |. 6A 10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401113 |. 68 92204000 push
00402092
; |Title = "Error"
00401118 |. 68 98204000 push
00402098
; |Text = "This program requires NT !"
0040111D |. 6A 00
push
0
; |hOwner = NULL
0040111F |. E8 E8000000 call <jmp.&user32.MessageBoxA>
; /MessageBoxA
00401124 |.
C9 leave
00401125 |.
C3 retn
leave
和
retn
两条指令用于恢复寄存器
ebp
的值以及平衡堆栈,
也就是将寄存器
ebp
和
esp
恢复到调用该过程前的值
下面是创建窗口的代码,
从右到左,
依次传入
CreateWindowExA
的各个参数
00401126
|> 6A 00 push
0
; /lParam = NULL
00401128 |. FF35 00304000 push dword ptr
[403000]
; |hInst = NULL
0040112E |. 6A 00
push
0
; |hMenu = NULL
00401130 |. 6A 00
push
0
; |hParent = NULL
00401132 |. 68 00000080 push
80000000
; |Height = 80000000 (-2147483648.)
00401137 |. 68 00000080 push
80000000
; |Width = 80000000 (-2147483648.)
0040113C |. 68 00000080 push
80000000
; |Y = 80000000 (-2147483648.)
00401141 |. 68 00000080 push
80000000
; |X = 80000000 (-2147483648.)
00401146 |. 68 0000CF00 push
0CF0000
; |Style =
WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION
0040114B |. 68 68204000 push
00402068
; |WindowName = "NormalWindow"
00401150 |. 68 68204000 push 00402068
; |Class = "NormalWindow"
00401155 |. 68 00020000 push
200
; |ExtStyle = WS_EX_CLIENTEDGE
0040115A |. E8 71000000 call
<jmp.&user32.CreateWindowExA> ; /CreateWindowExA
CreateWindowExA
返回,
看看返回值
eax
的值是否为
0
,
如果为
0
,
则显示错误对话框,
调用
leave, retn
平衡堆栈,
并且退出该过程,
否则,
跳转到
ShowWindow
函数部分
0040115F
|. 0BC0
or eax, eax
00401161 |. 75 15
jnz short
00401178 ;
跳转到
ShowWindow
的处理部分
00401163 |. 6A 10
push 10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401165 |. 68 92204000 push
00402092
; |Title = "Error"
0040116A |. 68 B3204000 push
004020B3
; |Text = "CreateWindow Error."
0040116F |. 6A 00
push
0
; |hOwner = NULL
00401171 |. E8 96000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401176 |.
C9 leave
00401177 |.
C3 retn
ShowWindow
处理部分,
首先将
CreateWindowExA
的返回值即窗口句柄
eax
存入全局变量
hWinMain
地址是
403004
,
然后调用
ShowWindow
和
UpdateWindow
显示窗口
00401178
|> A3 04304000 mov dword ptr
[403004], eax
0040117D |. 6A 01
push
1
; /ShowState = SW_SHOWNORMAL
0040117F |. FF35 04304000 push dword ptr
[403004]
; |hWnd = NULL
00401185 |. E8 94000000 call
<jmp.&user32.ShowWindow>
; /ShowWindow
0040118A |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
00401190 |. E8 95000000 call
<jmp.&user32.UpdateWindow> ;
/UpdateWindow
剩下的代码就是消息循环了,
通过
je short 004011BC
跳出消息循环
通过
jmp
short 00401195
执行
while
循环
00401195
|> 6A 00
/push
0
; /MsgFilterMax = 0
00401197 |. 6A 00
|push
0
; |MsgFilterMin = 0
00401199 |. 6A 00
|push
0
; |hWnd = NULL
0040119B |. 8D45 B4
|lea eax, dword ptr
[ebp-4C] ; |
0040119E |.
50
|push
eax
; |pMsg
0040119F |. E8 56000000 |call
<jmp.&user32.GetMessageA> ;
/GetMessageA
004011A4 |.
0BC0
|or eax, eax
004011A6 |. 74 14
|je short 004011BC
004011A8 |. 8D45 B4
|lea eax, dword ptr [ebp-4C]
004011AB |.
50
|push
eax
; /pMsg
004011AC |. E8 73000000 |call
<jmp.&user32.TranslateMessage> ; /TranslateMessage
004011B1 |. 8D45 B4
|lea eax, dword ptr [ebp-4C]
004011B4 |.
50
|push
eax
; /pMsg
004011B5 |. E8 28000000 |call
<jmp.&user32.DispatchMessageA> ; /DispatchMessageA
004011BA |.^ EB D9
/jmp short 00401195
004011BC |>
C9 leave
004011BD /.
C3 retn
下面来看看窗口过程
_WinProc的反汇编代码:
00401000
/. 55
push ebp
00401001 |.
8BEC
mov ebp, esp
00401003 |. 83C4 AC
add esp, -54
跟
_WinMain
开头一样,保存
ebp,
为局部变量分配栈空间
00401006
|. 8B45 0C
mov eax, dword ptr [ebp+C]
相当于
mov eax, uMsg
ebp + C
就是
uMsg
所在的栈位置
00401009
|. 83F8 0F
cmp eax, 0F
看看
uMsg
是不是
WM_PAINT
如果不是,则转入
WM_CLOSE
判断,否则,处理
WM_PAINT
消息,然后通过
jmp
short 00401091
退出过程
0040100C
|. 75 55
jnz short 00401063
0040100E |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401011 |.
50
push
eax
; /pPaintstruct
00401012 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
00401015 |. E8 B0010000 call
<jmp.&user32.BeginPaint>
; /BeginPaint
0040101A |. 8945 AC
mov dword ptr [ebp-54], eax
0040101D |. 68 00FF0000 push
0FF00
; /Color = <LIGHTGREEN>
00401022 |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
00401025 |. E8 24020000 call
<jmp.&gdi32.SetTextColor> ;
/SetTextColor
0040102A |. 6A 00
push
0
; /Color = <BLACK>
0040102C |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
0040102F |. E8 14020000 call
<jmp.&gdi32.SetBkColor>
; /SetBkColor
00401034 |. 8D45 B0
lea eax, dword ptr [ebp-50]
00401037 |.
50
push
eax
; /pRect
00401038 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040103B |. E8 B4010000 call
<jmp.&user32.GetClientRect> ;
/GetClientRect
00401040 |. 6A 25
push
25
; /Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE
00401042 |. 8D45 B0
lea eax, dword ptr
[ebp-50] ; |
00401045 |.
50
push
eax
; |pRect
00401046 |. 6A FF
push
-1
; |Count = FFFFFFFF (-1.)
00401048 |. 68 75204000 push
00402075
; |Text = "things have changed from now"
0040104D |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
00401050 |. E8 93010000 call
<jmp.&user32.DrawTextA>
; /DrawTextA
00401055 |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401058 |.
50
push
eax
; /pPaintstruct
00401059 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040105C |. E8 8D010000 call
<jmp.&user32.EndPaint>
; /EndPaint
00401061 |. EB 2E
jmp short 00401091
00401063
|> 83F8 10
cmp eax, 10
看看
uMsg
是不是
WM_CLOSE
如果不是的,则转入
DefWindowProc
处理,否则,处理
WM_CLOSE
消息,然后通过
jmp
short 00401091
退出过程
00401066
|. 75 14
jnz short 0040107C
00401068 |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
0040106E |. E8 69010000 call
<jmp.&user32.DestroyWindow> ;
/DestroyWindow
00401073 |. 6A 00
push
0
; /ExitCode = 0
00401075 |. E8 98010000 call
<jmp.&user32.PostQuitMessage> ; /PostQuitMessage
0040107A |. EB 15
jmp short 00401091
0040107C
|> FF75 14 push
dword ptr [ebp+14]
; /lParam
0040107F |. FF75 10
push dword ptr
[ebp+10]
; |wParam
00401082 |. FF75 0C
push dword ptr
[ebp+C]
; |Message
00401085 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
00401088 |. E8 49010000 call
<jmp.&user32.DefWindowProcA> ;
/DefWindowProcA
0040108D |.
C9 leave
0040108E |. C2 1000
retn 10
00401091
|> 33C0
xor eax, eax
00401093 |.
C9 leave
00401094 /. C2 1000
retn 10
这部分相对比较简单,
主要
cmp进行比较各个消息,如果不是则跳转到下一个消息的比较入口,如果都不是则跳转到默认消息处理,
如果是要处理的消息,
则处理完毕之后,
通过
jmp
short 00401091
跳到过程的出口,
平衡堆栈后返回到调用过程
OK
,
对于本程序的分析到此为止,有源程序对照,
理解这些反汇编代码还是比较容易的。
, 下面是反汇编代码的对照讲解:
现在我们来看一看反汇编的代码:
00401000
/.
55
push ebp
00401001 |.
8BEC
mov ebp, esp
00401003 |. 83C4 AC
add esp, -54
00401006 |. 8B45 0C
mov eax, dword ptr [ebp+C]
00401009 |. 83F8
0F
cmp eax, 0F
0040100C |. 75
55
jnz short 00401063
0040100E |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401011 |.
50
push
eax
; /pPaintstruct
00401012 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
00401015 |. E8 B0010000 call
<jmp.&user32.BeginPaint>
; /BeginPaint
0040101A |. 8945
AC
mov dword ptr [ebp-54], eax
0040101D |. 68 00FF0000 push
0FF00
; /Color = <LIGHTGREEN>
00401022 |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
00401025 |. E8 24020000 call
<jmp.&gdi32.SetTextColor> ;
/SetTextColor
0040102A |. 6A
00
push
0
; /Color = <BLACK>
0040102C |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
0040102F |. E8 14020000 call
<jmp.&gdi32.SetBkColor>
; /SetBkColor
00401034 |. 8D45
B0
lea eax, dword ptr [ebp-50]
00401037 |.
50
push
eax
; /pRect
00401038 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040103B |. E8 B4010000 call
<jmp.&user32.GetClientRect> ;
/GetClientRect
00401040 |. 6A
25
push
25
; /Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE
00401042 |. 8D45 B0
lea eax, dword ptr
[ebp-50] ; |
00401045 |.
50
push
eax
; |pRect
00401046 |. 6A
FF
push
-1
; |Count = FFFFFFFF (-1.)
00401048 |. 68 75204000 push
00402075
; |Text = "things have changed from now"
0040104D |. FF75
AC
push dword ptr
[ebp-54]
; |hDC
00401050 |. E8 93010000 call
<jmp.&user32.DrawTextA>
; /DrawTextA
00401055 |. 8D45
C0
lea eax, dword ptr [ebp-40]
00401058 |.
50
push
eax
; /pPaintstruct
00401059 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
0040105C |. E8 8D010000 call
<jmp.&user32.EndPaint>
; /EndPaint
00401061 |. EB
2E
jmp short 00401091
00401063 |> 83F8 10
cmp eax, 10
00401066 |. 75
14
jnz short 0040107C
00401068 |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
0040106E |. E8 69010000 call
<jmp.&user32.DestroyWindow> ;
/DestroyWindow
00401073 |. 6A
00
push
0
; /ExitCode = 0
00401075 |. E8 98010000 call
<jmp.&user32.PostQuitMessage> ; /PostQuitMessage
0040107A |. EB
15
jmp short 00401091
0040107C |> FF75
14 push dword
ptr
[ebp+14]
; /lParam
0040107F |. FF75 10
push dword ptr
[ebp+10]
; |wParam
00401082 |. FF75 0C
push dword ptr
[ebp+C]
; |Message
00401085 |. FF75
08
push dword ptr
[ebp+8]
; |hWnd
00401088 |. E8 49010000 call
<jmp.&user32.DefWindowProcA> ;
/DefWindowProcA
0040108D |.
C9
leave
0040108E |. C2 1000
retn 10
00401091 |> 33C0
xor eax, eax
00401093 |.
C9
leave
00401094 /. C2
1000
retn 10
00401097 /$
55
push ebp
00401098 |.
8BEC
mov ebp, esp
0040109A |. 83C4
B4
add esp, -4C
0040109D |. 6A 00
push
0
; /pModule = NULL
0040109F |. E8 92010000 call
<jmp.&kernel32.GetModuleHandleA> ; /GetModuleHandleA
004010A4 |. A3 00304000 mov
dword ptr [403000], eax
004010A9 |. 6A 30
push
30
; /Length = 30 (48.)
004010AB |. 8D45 D0
lea eax, dword ptr
[ebp-30] ; |
004010AE |.
50
push
eax
; |Destination
004010AF |. E8 88010000 call
<jmp.&kernel32.RtlZeroMemory> ; /RtlZeroMemory
004010B4 |. C745 D0 30000>mov dword ptr
[ebp-30], 30
004010BB |. C745 D4 03000>mov dword ptr
[ebp-2C], 3
004010C2 |. C745 D8 00104>mov dword ptr
[ebp-28], 00401000
004010C9 |. FF35 00304000 push dword ptr [403000]
004010CF |. 8F45
E4
pop dword ptr [ebp-1C]
004010D2 |. 68 007F0000
push
7F00
; /RsrcName = IDI_APPLICATION
004010D7 |. 6A
00
push
0
; |hInst = NULL
004010D9 |. E8 28010000 call
<jmp.&user32.LoadIconA>
; /LoadIconA
004010DE |. 8945
E8
mov dword ptr [ebp-18], eax
004010E1 |. 8945
FC
mov dword ptr [ebp-4], eax
004010E4 |. 68 007F0000 push
7F00
; /RsrcName = IDC_ARROW
004010E9 |. 6A
00
push
0
; |hInst = NULL
004010EB |. E8 10010000 call
<jmp.&user32.LoadCursorA> ;
/LoadCursorA
004010F0 |. 8945
EC
mov dword ptr [ebp-14], eax
004010F3 |. 6A 04
push
4
; /ObjType = BLACK_BRUSH
004010F5 |. E8 48010000 call
<jmp.&gdi32.GetStockObject> ;
/GetStockObject
004010FA |. 8945
F0
mov dword ptr [ebp-10], eax
004010FD |. C745 F8 68204>mov dword ptr
[ebp-8], 00402068 ; ASCII
"NormalWindow"
00401104 |. 8D45
D0
lea eax, dword ptr [ebp-30]
00401107 |.
50
push
eax
; /pWndClassEx
00401108 |. E8 0B010000 call
<jmp.&user32.RegisterClassExA> ; /RegisterClassExA
0040110D |.
0BC0
or eax, eax
0040110F |. 75
15
jnz short 00401126
00401111 |. 6A
10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401113 |. 68 92204000 push
00402092
; |Title = "Error"
00401118 |. 68 98204000 push
00402098
; |Text = "This program requires NT !"
0040111D |. 6A
00
push
0
; |hOwner = NULL
0040111F |. E8 E8000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401124 |.
C9
leave
00401125 |.
C3
retn
00401126 |> 6A 00
push
0
; /lParam = NULL
00401128 |. FF35 00304000 push dword ptr
[403000]
; |hInst = NULL
0040112E |. 6A
00
push
0
; |hMenu = NULL
00401130 |. 6A
00
push
0
; |hParent = NULL
00401132 |. 68 00000080 push
80000000
; |Height = 80000000 (-2147483648.)
00401137 |. 68 00000080 push
80000000
; |Width = 80000000 (-2147483648.)
0040113C |. 68 00000080 push
80000000
; |Y = 80000000 (-2147483648.)
00401141 |. 68 00000080 push
80000000
; |X = 80000000 (-2147483648.)
00401146 |. 68 0000CF00 push
0CF0000
; |Style = WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION
0040114B |. 68 68204000 push
00402068
; |WindowName = "NormalWindow"
00401150 |. 68 68204000 push
00402068
; |Class = "NormalWindow"
00401155 |. 68 00020000 push
200
; |ExtStyle = WS_EX_CLIENTEDGE
0040115A |. E8 71000000 call
<jmp.&user32.CreateWindowExA> ; /CreateWindowExA
0040115F |.
0BC0
or eax, eax
00401161 |. 75
15
jnz short 00401178
00401163 |. 6A 10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401165 |. 68 92204000 push
00402092
; |Title = "Error"
0040116A |. 68 B3204000 push
004020B3
; |Text = "CreateWindow Error."
0040116F |. 6A
00
push
0
; |hOwner = NULL
00401171 |. E8 96000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401176 |.
C9
leave
00401177 |.
C3
retn
00401178 |> A3 04304000 mov
dword ptr [403004], eax
0040117D |. 6A 01
push
1
; /ShowState = SW_SHOWNORMAL
0040117F |. FF35 04304000 push dword ptr
[403004]
; |hWnd = NULL
00401185 |. E8 94000000 call
<jmp.&user32.ShowWindow>
; /ShowWindow
0040118A |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
00401190 |. E8 95000000 call
<jmp.&user32.UpdateWindow> ;
/UpdateWindow
00401195 |> 6A
00 /
push
0
; /MsgFilterMax = 0
00401197 |. 6A 00
| push
0
; |MsgFilterMin = 0
00401199 |. 6A 00
| push
0
; |hWnd = NULL
0040119B |. 8D45 B4
| lea eax, dword ptr
[ebp-4C] ; |
0040119E |.
50
| push
eax
; |pMsg
0040119F |. E8 56000000 |call
<jmp.&user32.GetMessageA> ;
/GetMessageA
004011A4 |.
0BC0
| or eax, eax
004011A6 |. 74 14
| je short 004011BC
004011A8 |. 8D45 B4
| lea eax, dword ptr [ebp-4C]
004011AB |.
50
| push
eax
; /pMsg
004011AC |. E8 73000000 |call
<jmp.&user32.TranslateMessage> ; /TranslateMessage
004011B1 |. 8D45 B4
| lea eax, dword ptr [ebp-4C]
004011B4 |.
50
| push
eax
; /pMsg
004011B5 |. E8 28000000 |call
<jmp.&user32.DispatchMessageA> ; /DispatchMessageA
004011BA |.^ EB D9
/ jmp short 00401195
004011BC |>
C9
leave
004011BD /.
C3
retn
004011BE >/$ E8 D4FEFFFF call 00401097
004011C3 |. 6A
00
push
0
; /ExitCode = 0
004011C5 /. E8 66000000 call
<jmp.&kernel32.ExitProcess> ;
/ExitProcess
004011CA $- FF25 60204000 jmp dword ptr
[<&user32.BeginPaint>] ; user32.BeginPaint
004011D0 $- FF25 58204000 jmp dword ptr
[<&user32.CreateWindow>; user32.CreateWindowExA
004011D6 $- FF25 54204000 jmp dword ptr
[<&user32.DefWindowPro>; user32.DefWindowProcA
004011DC $- FF25 4C204000 jmp dword ptr
[<&user32.DestroyWindo>; user32.DestroyWindow
004011E2 $- FF25 50204000 jmp dword ptr
[<&user32.DispatchMess>; user32.DispatchMessageA
004011E8 $- FF25 48204000 jmp dword ptr
[<&user32.DrawTextA>] ; user32.DrawTextA
004011EE $- FF25 44204000 jmp dword ptr
[<&user32.EndPaint>] ; user32.EndPaint
004011F4 $- FF25 30204000 jmp dword ptr
[<&user32.GetClientRec>; user32.GetClientRect
004011FA $- FF25 20204000 jmp dword ptr
[<&user32.GetMessageA>>; user32.GetMessageA
00401200 $- FF25 24204000 jmp dword ptr
[<&user32.LoadCursorA>>; user32.LoadCursorA
00401206 $- FF25 28204000 jmp dword ptr
[<&user32.LoadIconA>] ; user32.LoadIconA
0040120C $- FF25 2C204000 jmp dword ptr
[<&user32.MessageBoxA>>; user32.MessageBoxA
00401212 $- FF25 5C204000 jmp dword ptr
[<&user32.PostQuitMess>; user32.PostQuitMessage
00401218 $- FF25 34204000 jmp dword ptr
[<&user32.RegisterClas>; user32.RegisterClassExA
0040121E $- FF25 38204000 jmp dword ptr
[<&user32.ShowWindow>] ; user32.ShowWindow
00401224 $- FF25 3C204000 jmp dword ptr
[<&user32.TranslateMes>; user32.TranslateMessage
0040122A $- FF25 40204000 jmp dword ptr
[<&user32.UpdateWindow>; user32.UpdateWindow
00401230 .- FF25 14204000 jmp dword ptr
[<&kernel32.ExitProces>; kernel32.ExitProcess
00401236 $- FF25 10204000 jmp dword ptr
[<&kernel32.GetModuleH>; kernel32.GetModuleHandleA
0040123C $- FF25 18204000 jmp dword ptr
[<&kernel32.RtlZeroMem>; ntdll.RtlZeroMemory
00401242 $- FF25 04204000 jmp dword ptr
[<&gdi32.GetStockObjec>; GDI32.GetStockObject
00401248 $- FF25 00204000 jmp dword ptr
[<&gdi32.SetBkColor>] ; GDI32.SetBkColor
0040124E $- FF25 08204000 jmp dword ptr
[<&gdi32.SetTextColor>>; GDI32.SetTextColor
经过反汇编后的代码,
看起来是不是有些郁闷?
跟源程序比,
显得有些乱七八糟的,
其实好好分析一下,
也不难理解:
对于
004011CA $- FF25
60204000 jmp dword ptr [<&user32.BeginPaint>]
; user32.BeginPaint
以及后面的部分,我们就不需要去看了,
很显然,
是程序中用到的一些导入函数
004011BE
>/$ E8 D4FEFFFF call 00401097
004011C3 |. 6A 00
push
0
; /ExitCode = 0
004011C5 /. E8 66000000 call
<jmp.&kernel32.ExitProcess> ;
/ExitProcess
这个便是标签
start 和
end start 之间的内容
call 00401097 显然是调用主过程
_WinMain,
00401097是
_WinMain的地址
push 0
call <jmp.&kernel32.ExitProcess>
这
2句调用
ExitProcess函数,
传入的退出代码为
0
现在看看主过程
_WinMain对应的反汇编代码:
00401097
/$ 55
push ebp
00401098 |.
8BEC
mov ebp, esp
0040109A |. 83C4 B4
add esp, -4C
这
3
句代码首先保存
ebp
的值,
然后将当前栈指针赋值给
ebp
,好在后面
通过
ebp
来访问各个参数
add esp, -4C
为局部变量
local
@stWC:WNDCLASSEX
local @stMsg:MSG
分配临时栈空间
, sizeof @stWC
和
sizeof @stMsg
加起来正好
4CH
个字节
0040109D |. 6A 00
push
0
; /pModule = NULL
0040109F |. E8 92010000 call
<jmp.&kernel32.GetModuleHandleA> ; /GetModuleHandleA
004010A4 |. A3 00304000 mov
dword ptr [403000], eax
调用
kernel32.dll
模块中的
GetModuleHandleA
函数,得到当前的实例句柄,
并且保存在全局变量
hInstance
中,
全局变量
hInstance
的地址为
403000
004010A9
|. 6A 30
push
30
; /Length = 30 (48.)
004010AB |. 8D45 D0
lea eax, dword ptr
[ebp-30] ; |
004010AE |.
50
push
eax
; |Destination
004010AF |. E8 88010000 call
<jmp.&kernel32.RtlZeroMemory> ; /RtlZeroMemory
调用
Kernel32
模块中的
RtlZeroMemory
函数,
将局部变量
@stWC
结构填充为
0
其中
@stWC
结构的大小为
30H
个字节,
地址是
ebp-30
004010B4 |. C745 D0 30000>mov dword ptr
[ebp-30], 30
相当于
mov @stWC.cbSize, sizeof WNDCLASSEX
004010BB |. C745 D4 03000>mov dword ptr
[ebp-2C], 3
相当于
mov
@stWC.style, CS_HREDRAW or CS_VREDRAW
004010C2
|. C745 D8 00104>mov dword ptr [ebp-28],
00401000
相当于
mov
@stWC.lpfnWndProc, offset _WinProc
004010C9
|. FF35 00304000 push dword ptr [403000]
相当于
push
hInstance
004010CF
|. 8F45 E4
pop dword ptr [ebp-1C]
相当于
pop
@stWC.hInstance
004010D2
|. 68 007F0000 push
7F00
; /RsrcName = IDI_APPLICATION
004010D7
|. 6A 00
push
0
; |hInst = NULL
004010D9 |. E8 28010000 call
<jmp.&user32.LoadIconA>
; /LoadIconA
004010DE |. 8945 E8
mov dword ptr [ebp-18], eax
004010E1 |. 8945 FC
mov dword ptr [ebp-4], eax
调用
user32.dll
模块中的
LoadIcon
函数,得到默认图标,分别填充
@stWC
结构的
@stWC.hIcon
和
@stWC.hIconSm
域
004010E4
|. 68 007F0000 push
7F00
; /RsrcName = IDC_ARROW
004010E9 |. 6A 00
push
0
; |hInst = NULL
004010EB |. E8 10010000 call
<jmp.&user32.LoadCursorA> ;
/LoadCursorA
004010F0 |. 8945 EC
mov dword ptr [ebp-14], eax
调用
user32
模块中的
LoadCursor
函数,
得到默认光标,填充
@stWC
结构的
@stWC.hCursor
域
004010F3
|. 6A 04
push
4
; /ObjType = BLACK_BRUSH
004010F5 |. E8 48010000 call
<jmp.&gdi32.GetStockObject> ;
/GetStockObject
004010FA |. 8945 F0
mov dword ptr [ebp-10], eax
调用
gdi32
模块中的
GetStockObject
填充
@stWC
结构的
@stWC.hbrBackground
域
004010FD
|. C745 F8 68204>mov dword ptr [ebp-8],
00402068 ; ASCII "NormalWindow"
用字符串
'NormalWindow'
填充结构
@stWC
的
@stWC.lpszClassName
域
00401104
|. 8D45 D0
lea eax, dword ptr [ebp-30]
将局部变量
@stWC
的地址放入
eax
中
00401107
|. 50
push
eax
; /pWndClassEx
00401108 |. E8 0B010000 call
<jmp.&user32.RegisterClassExA> ; /RegisterClassExA
调用
user32
模块中的
RegisterClassExA
注册窗口类
0040110D
|. 0BC0
or eax, eax
看
RegisterClassExA
的返回值
ea
是否为
0
,如果为
0
,
则调用
MessageBoxA
对话框,显示错误讯息,并且执行
leave
retn
指令退出程序
否则,执行
jnz short 00401126
跳转到窗口创建部分
0040110F |. 75
15 jnz
short 00401126
00401111 |. 6A 10
push
10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401113 |. 68 92204000 push
00402092
; |Title = "Error"
00401118 |. 68 98204000 push
00402098
; |Text = "This program requires NT !"
0040111D |. 6A 00
push
0
; |hOwner = NULL
0040111F |. E8 E8000000 call <jmp.&user32.MessageBoxA>
; /MessageBoxA
00401124 |.
C9 leave
00401125 |.
C3 retn
leave
和
retn
两条指令用于恢复寄存器
ebp
的值以及平衡堆栈,
也就是将寄存器
ebp
和
esp
恢复到调用该过程前的值
下面是创建窗口的代码,
从右到左,
依次传入
CreateWindowExA
的各个参数
00401126
|> 6A 00 push
0
; /lParam = NULL
00401128 |. FF35 00304000 push dword ptr
[403000]
; |hInst = NULL
0040112E |. 6A 00
push
0
; |hMenu = NULL
00401130 |. 6A 00
push
0
; |hParent = NULL
00401132 |. 68 00000080 push
80000000
; |Height = 80000000 (-2147483648.)
00401137 |. 68 00000080 push
80000000
; |Width = 80000000 (-2147483648.)
0040113C |. 68 00000080 push
80000000
; |Y = 80000000 (-2147483648.)
00401141 |. 68 00000080 push
80000000
; |X = 80000000 (-2147483648.)
00401146 |. 68 0000CF00 push
0CF0000
; |Style =
WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION
0040114B |. 68 68204000 push
00402068
; |WindowName = "NormalWindow"
00401150 |. 68 68204000 push 00402068
; |Class = "NormalWindow"
00401155 |. 68 00020000 push
200
; |ExtStyle = WS_EX_CLIENTEDGE
0040115A |. E8 71000000 call
<jmp.&user32.CreateWindowExA> ; /CreateWindowExA
CreateWindowExA
返回,
看看返回值
eax
的值是否为
0
,
如果为
0
,
则显示错误对话框,
调用
leave, retn
平衡堆栈,
并且退出该过程,
否则,
跳转到
ShowWindow
函数部分
0040115F
|. 0BC0
or eax, eax
00401161 |. 75 15
jnz short
00401178 ;
跳转到
ShowWindow
的处理部分
00401163 |. 6A 10
push 10
; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401165 |. 68 92204000 push
00402092
; |Title = "Error"
0040116A |. 68 B3204000 push
004020B3
; |Text = "CreateWindow Error."
0040116F |. 6A 00
push
0
; |hOwner = NULL
00401171 |. E8 96000000 call
<jmp.&user32.MessageBoxA> ;
/MessageBoxA
00401176 |.
C9 leave
00401177 |.
C3 retn
ShowWindow
处理部分,
首先将
CreateWindowExA
的返回值即窗口句柄
eax
存入全局变量
hWinMain
地址是
403004
,
然后调用
ShowWindow
和
UpdateWindow
显示窗口
00401178
|> A3 04304000 mov dword ptr
[403004], eax
0040117D |. 6A 01
push
1
; /ShowState = SW_SHOWNORMAL
0040117F |. FF35 04304000 push dword ptr
[403004]
; |hWnd = NULL
00401185 |. E8 94000000 call
<jmp.&user32.ShowWindow>
; /ShowWindow
0040118A |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
00401190 |. E8 95000000 call
<jmp.&user32.UpdateWindow> ;
/UpdateWindow
剩下的代码就是消息循环了,
通过
je short 004011BC
跳出消息循环
通过
jmp
short 00401195
执行
while
循环
00401195
|> 6A 00
/push
0
; /MsgFilterMax = 0
00401197 |. 6A 00
|push
0
; |MsgFilterMin = 0
00401199 |. 6A 00
|push
0
; |hWnd = NULL
0040119B |. 8D45 B4
|lea eax, dword ptr
[ebp-4C] ; |
0040119E |.
50
|push
eax
; |pMsg
0040119F |. E8 56000000 |call
<jmp.&user32.GetMessageA> ;
/GetMessageA
004011A4 |.
0BC0
|or eax, eax
004011A6 |. 74 14
|je short 004011BC
004011A8 |. 8D45 B4
|lea eax, dword ptr [ebp-4C]
004011AB |.
50
|push
eax
; /pMsg
004011AC |. E8 73000000 |call
<jmp.&user32.TranslateMessage> ; /TranslateMessage
004011B1 |. 8D45 B4
|lea eax, dword ptr [ebp-4C]
004011B4 |.
50
|push
eax
; /pMsg
004011B5 |. E8 28000000 |call
<jmp.&user32.DispatchMessageA> ; /DispatchMessageA
004011BA |.^ EB D9
/jmp short 00401195
004011BC |>
C9 leave
004011BD /.
C3 retn
下面来看看窗口过程
_WinProc的反汇编代码:
00401000
/. 55
push ebp
00401001 |.
8BEC
mov ebp, esp
00401003 |. 83C4 AC
add esp, -54
跟
_WinMain
开头一样,保存
ebp,
为局部变量分配栈空间
00401006
|. 8B45 0C
mov eax, dword ptr [ebp+C]
相当于
mov eax, uMsg
ebp + C
就是
uMsg
所在的栈位置
00401009
|. 83F8 0F
cmp eax, 0F
看看
uMsg
是不是
WM_PAINT
如果不是,则转入
WM_CLOSE
判断,否则,处理
WM_PAINT
消息,然后通过
jmp
short 00401091
退出过程
0040100C
|. 75 55
jnz short 00401063
0040100E |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401011 |.
50
push
eax
; /pPaintstruct
00401012 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
00401015 |. E8 B0010000 call
<jmp.&user32.BeginPaint>
; /BeginPaint
0040101A |. 8945 AC
mov dword ptr [ebp-54], eax
0040101D |. 68 00FF0000 push
0FF00
; /Color = <LIGHTGREEN>
00401022 |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
00401025 |. E8 24020000 call
<jmp.&gdi32.SetTextColor> ;
/SetTextColor
0040102A |. 6A 00
push
0
; /Color = <BLACK>
0040102C |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
0040102F |. E8 14020000 call
<jmp.&gdi32.SetBkColor>
; /SetBkColor
00401034 |. 8D45 B0
lea eax, dword ptr [ebp-50]
00401037 |.
50
push
eax
; /pRect
00401038 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040103B |. E8 B4010000 call
<jmp.&user32.GetClientRect> ;
/GetClientRect
00401040 |. 6A 25
push
25
; /Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE
00401042 |. 8D45 B0
lea eax, dword ptr
[ebp-50] ; |
00401045 |.
50
push
eax
; |pRect
00401046 |. 6A FF
push
-1
; |Count = FFFFFFFF (-1.)
00401048 |. 68 75204000 push
00402075
; |Text = "things have changed from now"
0040104D |. FF75 AC
push dword ptr
[ebp-54]
; |hDC
00401050 |. E8 93010000 call
<jmp.&user32.DrawTextA>
; /DrawTextA
00401055 |. 8D45 C0
lea eax, dword ptr [ebp-40]
00401058 |.
50
push
eax
; /pPaintstruct
00401059 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
0040105C |. E8 8D010000 call
<jmp.&user32.EndPaint>
; /EndPaint
00401061 |. EB 2E
jmp short 00401091
00401063
|> 83F8 10
cmp eax, 10
看看
uMsg
是不是
WM_CLOSE
如果不是的,则转入
DefWindowProc
处理,否则,处理
WM_CLOSE
消息,然后通过
jmp
short 00401091
退出过程
00401066
|. 75 14
jnz short 0040107C
00401068 |. FF35 04304000 push dword ptr
[403004]
; /hWnd = NULL
0040106E |. E8 69010000 call
<jmp.&user32.DestroyWindow> ;
/DestroyWindow
00401073 |. 6A 00
push
0
; /ExitCode = 0
00401075 |. E8 98010000 call
<jmp.&user32.PostQuitMessage> ; /PostQuitMessage
0040107A |. EB 15
jmp short 00401091
0040107C
|> FF75 14 push
dword ptr [ebp+14]
; /lParam
0040107F |. FF75 10
push dword ptr
[ebp+10]
; |wParam
00401082 |. FF75 0C
push dword ptr
[ebp+C]
; |Message
00401085 |. FF75 08
push dword ptr
[ebp+8]
; |hWnd
00401088 |. E8 49010000 call
<jmp.&user32.DefWindowProcA> ;
/DefWindowProcA
0040108D |.
C9 leave
0040108E |. C2 1000
retn 10
00401091
|> 33C0
xor eax, eax
00401093 |.
C9 leave
00401094 /. C2 1000
retn 10
这部分相对比较简单,
主要
cmp进行比较各个消息,如果不是则跳转到下一个消息的比较入口,如果都不是则跳转到默认消息处理,
如果是要处理的消息,
则处理完毕之后,
通过
jmp
short 00401091
跳到过程的出口,
平衡堆栈后返回到调用过程
OK
,
对于本程序的分析到此为止,有源程序对照,
理解这些反汇编代码还是比较容易的。
相关文章推荐
- [32位汇编系列]002 - 创建标准的windows窗口(1)
- [32位汇编系列]002 - 创建标准的windows窗口(2)
- windows下32位汇编语言学习笔记 第四章 第一个窗口程序 1 (消息的使用和入口代码)
- 微机原理课程设计32位汇编学习之二(创建简单的窗口)
- windows下32位汇编语言学习笔记 第四章 第一个窗口程序 (windows的消息机制)
- Windows窗口程序从创建到关闭产生的消息
- Windows窗口创建
- Windows 7的预备知识系列之二:认识Windows 7中的窗口
- Windows 8 动手实验系列教程 实验1:创建Windows应用商店应用
- OpenGL_002创建窗口
- windows下创建控制台窗口
- 简单的windows窗口创建实例
- Windows环境下32位汇编程序设计C版code--第五章(二)
- 游戏编程之DirectX的修炼:二(创建属于自己的windows窗口程序:下)
- Qt在Windows下如何创建无CMD窗口控制台程序
- Windows环境下32位汇编程序设计C版code--第五章(三)
- 记录我的Windows编程(一)创建窗口
- 谈谈windows窗口注册和创建
- Delphi使用Windows API 创建最基本的窗口程序Hello,Windows演示
- 【Windows编程】系列第二篇:Windows SDK创建基本控件