这个是源代码:
1 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 ; Sample code for < Win32ASM Programming 2nd Edition> 3 ; by 罗云彬, http://asm.yeah.net 4 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 5 ; FirstWindow.asm 6 ; 窗口程序的模板代码 7 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 8 ; 使用 nmake 或下列命令进行编译和链接: 9 ; ml /c /coff FirstWindow.asm 10 ; Link /subsystem:windows FirstWindow.obj 11 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 12 .386 13 .model flat,stdcall 14 option casemap:none 15 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 16 ; Include 文件定义 17 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 18 include windows.inc 19 include gdi32.inc 20 includelib gdi32.lib 21 include user32.inc 22 includelib user32.lib 23 include kernel32.inc 24 includelib kernel32.lib 25 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 26 ; 数据段 27 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 28 .data? 29 hInstance dd ? 30 hWinMain dd ? 31 32 .const 33 szClassName db 'MyClass',0 34 szCaptionMain db 'My first Window !',0 35 szText db 'Win32 Assembly, Simple and powerful !',0 36 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 37 ; 代码段 38 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 39 .code 40 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 41 ; 窗口过程 42 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 43 _ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam 44 local @stPs:PAINTSTRUCT 45 local @stRect:RECT 46 local @hDc 47 48 mov eax,uMsg 49 ;******************************************************************** 50 .if eax == WM_PAINT 51 invoke BeginPaint,hWnd,addr @stPs 52 mov @hDc,eax 53 54 invoke GetClientRect,hWnd,addr @stRect 55 invoke DrawText,@hDc,addr szText,-1,\ 56 addr @stRect,\ 57 DT_SINGLELINE or DT_CENTER or DT_VCENTER 58 59 invoke EndPaint,hWnd,addr @stPs 60 ;******************************************************************** 61 .elseif eax == WM_CLOSE 62 invoke DestroyWindow,hWinMain 63 invoke PostQuitMessage,NULL 64 ;******************************************************************** 65 .else 66 invoke DefWindowProc,hWnd,uMsg,wParam,lParam 67 ret 68 .endif 69 ;******************************************************************** 70 xor eax,eax 71 ret 72 73 _ProcWinMain endp 74 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 75 _WinMain proc 76 local @stWndClass:WNDCLASSEX 77 local @stMsg:MSG 78 79 invoke GetModuleHandle,NULL 80 mov hInstance,eax 81 invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass 82 ;******************************************************************** 83 ; 注册窗口类 84 ;******************************************************************** 85 invoke LoadCursor,0,IDC_ARROW 86 mov @stWndClass.hCursor,eax 87 push hInstance 88 pop @stWndClass.hInstance 89 mov @stWndClass.cbSize,sizeof WNDCLASSEX 90 mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW 91 mov @stWndClass.lpfnWndProc,offset _ProcWinMain 92 mov @stWndClass.hbrBackground,COLOR_WINDOW + 1 93 mov @stWndClass.lpszClassName,offset szClassName 94 invoke RegisterClassEx,addr @stWndClass 95 ;******************************************************************** 96 ; 建立并显示窗口 97 ;******************************************************************** 98 invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\ 99 WS_OVERLAPPEDWINDOW,\ 100 100,100,600,400,\ 101 NULL,NULL,hInstance,NULL 102 mov hWinMain,eax 103 invoke ShowWindow,hWinMain,SW_SHOWNORMAL 104 invoke UpdateWindow,hWinMain 105 ;******************************************************************** 106 ; 消息循环 107 ;******************************************************************** 108 .while TRUE 109 invoke GetMessage,addr @stMsg,NULL,0,0 110 .break .if eax == 0 111 invoke TranslateMessage,addr @stMsg 112 invoke DispatchMessage,addr @stMsg 113 .endw 114 ret 115 116 _WinMain endp 117 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 118 start: 119 call _WinMain 120 invoke ExitProcess,NULL 121 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 122 end start
我在66行的位置处对invoke DefWindowProc,hWnd,uMsg,wParam,lParam没有进行换行处理,一直报错。(我先自己照着书写代码)
error A2008: syntax error : invoke
===============================================
===============================================
start: call _WinMain invoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> end start
对应的反汇编代码:
1 00401163 >/$ E8 21FFFFFF call 00401089 ; call _WinMain 2 00401168 |. 6A 00 push 0 ; /ExitCode = 0 3 0040116A \. E8 5B000000 call <jmp.&kernel32.ExitProcess> ; \ExitProcess
现在进入_WinMain,汇编代码为:
1 _WinMain proc 2 local @stWndClass:WNDCLASSEX 3 local @stMsg:MSG 4 5 invoke GetModuleHandle,NULL 6 mov hInstance,eax 7 invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass 8 ;******************************************************************** 9 ; 注册窗口类 10 ;******************************************************************** 11 invoke LoadCursor,0,IDC_ARROW 12 mov @stWndClass.hCursor,eax 13 push hInstance 14 pop @stWndClass.hInstance 15 mov @stWndClass.cbSize,sizeof WNDCLASSEX 16 mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW 17 mov @stWndClass.lpfnWndProc,offset _ProcWinMain 18 mov @stWndClass.hbrBackground,COLOR_WINDOW + 1 19 mov @stWndClass.lpszClassName,offset szClassName 20 invoke RegisterClassEx,addr @stWndClass 21 ;******************************************************************** 22 ; 建立并显示窗口 23 ;******************************************************************** 24 invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\ 25 WS_OVERLAPPEDWINDOW,\ 26 100,100,600,400,\ 27 NULL,NULL,hInstance,NULL 28 mov hWinMain,eax 29 invoke ShowWindow,hWinMain,SW_SHOWNORMAL 30 invoke UpdateWindow,hWinMain 31 ;******************************************************************** 32 ; 消息循环 33 ;******************************************************************** 34 .while TRUE 35 invoke GetMessage,addr @stMsg,NULL,0,0 36 .break .if eax == 0 37 invoke TranslateMessage,addr @stMsg 38 invoke DispatchMessage,addr @stMsg 39 .endw 40 ret 41 42 _WinMain endp
首先是填充WNDCLASSEX结构,然后是注册窗口类,显示窗口,更新窗口。
1 00401089 /$ 55 push ebp 2 0040108A |. 8BEC mov ebp, esp 3 0040108C |. 83C4 B4 add esp, -4C 4 0040108F |. 6A 00 push 0 ; /pModule = NULL 5 00401091 |. E8 3A010000 call <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA 6 00401096 |. A3 00304000 mov dword ptr [403000], eax 7 0040109B |. 6A 30 push 30 ; /Length = 30 (48.) 8 0040109D |. 8D45 D0 lea eax, dword ptr [ebp-30] ; | 9 004010A0 |. 50 push eax ; |Destination 10 004010A1 |. E8 30010000 call <jmp.&kernel32.RtlZeroMemory> ; \RtlZeroMemory 11 004010A6 |. 68 007F0000 push 7F00 ; /RsrcName = IDC_ARROW 12 004010AB |. 6A 00 push 0 ; |hInst = NULL 13 004010AD |. E8 F4000000 call <jmp.&user32.LoadCursorA> ; \LoadCursorA 14 004010B2 |. 8945 EC mov dword ptr [ebp-14], eax 15 004010B5 |. FF35 00304000 push dword ptr [403000] ; OtherDia.00400000 16 004010BB |. 8F45 E4 pop dword ptr [ebp-1C] 17 004010BE |. C745 D0 30000>mov dword ptr [ebp-30], 30 18 004010C5 |. C745 D4 03000>mov dword ptr [ebp-2C], 3 19 004010CC |. C745 D8 00104>mov dword ptr [ebp-28], 00401000 20 004010D3 |. C745 F0 06000>mov dword ptr [ebp-10], 6 21 004010DA |. C745 F8 50204>mov dword ptr [ebp-8], 00402050 ; ASCII "MyClass" 22 004010E1 |. 8D45 D0 lea eax, dword ptr [ebp-30] 23 004010E4 |. 50 push eax ; /pWndClassEx 24 004010E5 |. E8 C8000000 call <jmp.&user32.RegisterClassExA> ; \RegisterClassExA 25 004010EA |. 6A 00 push 0 ; /lParam = NULL 26 004010EC |. FF35 00304000 push dword ptr [403000] ; |hInst = 00400000 27 004010F2 |. 6A 00 push 0 ; |hMenu = NULL 28 004010F4 |. 6A 00 push 0 ; |hParent = NULL 29 004010F6 |. 68 90010000 push 190 ; |Height = 190 (400.) 30 004010FB |. 68 58020000 push 258 ; |Width = 258 (600.) 31 00401100 |. 6A 64 push 64 ; |Y = 64 (100.) 32 00401102 |. 6A 64 push 64 ; |X = 64 (100.) 33 00401104 |. 68 0000CF00 push 0CF0000 ; |Style = WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|
; WS_SYSMENU|WS_THICKFRAME|WS_CAPTION 34 00401109 |. 68 58204000 push 00402058 ; |WindowName = "My first Window !" 35 0040110E |. 68 50204000 push 00402050 ; |Class = "MyClass" 36 00401113 |. 68 00020000 push 200 ; |ExtStyle = WS_EX_CLIENTEDGE 37 00401118 |. E8 59000000 call <jmp.&user32.CreateWindowExA> ; \CreateWindowExA 38 0040111D |. A3 04304000 mov dword ptr [403004], eax 39 00401122 |. 6A 01 push 1 ; /ShowState = SW_SHOWNORMAL 40 00401124 |. FF35 04304000 push dword ptr [403004] ; |hWnd = NULL 41 0040112A |. E8 89000000 call <jmp.&user32.ShowWindow> ; \ShowWindow 42 0040112F |. FF35 04304000 push dword ptr [403004] ; /hWnd = NULL 43 00401135 |. E8 8A000000 call <jmp.&user32.UpdateWindow> ; \UpdateWindow 44 0040113A |> 6A 00 /push 0 ; /MsgFilterMax = 0 45 0040113C |. 6A 00 |push 0 ; |MsgFilterMin = 0 46 0040113E |. 6A 00 |push 0 ; |hWnd = NULL 47 00401140 |. 8D45 B4 |lea eax, dword ptr [ebp-4C] ; | 48 00401143 |. 50 |push eax ; |pMsg 49 00401144 |. E8 57000000 |call <jmp.&user32.GetMessageA> ; \GetMessageA 50 00401149 |. 0BC0 |or eax, eax 51 0040114B |. 74 14 |je short 00401161 52 0040114D |. 8D45 B4 |lea eax, dword ptr [ebp-4C] 53 00401150 |. 50 |push eax ; /pMsg 54 00401151 |. E8 68000000 |call <jmp.&user32.TranslateMessage> ; \TranslateMessage 55 00401156 |. 8D45 B4 |lea eax, dword ptr [ebp-4C] 56 00401159 |. 50 |push eax ; /pMsg 57 0040115A |. E8 29000000 |call <jmp.&user32.DispatchMessageA> ; \DispatchMessageA 58 0040115F |.^ EB D9 \jmp short 0040113A 59 00401161 |> C9 leave 60 00401162 \. C3 retn
我们看看这个窗口的窗口处理函数在哪个位置。
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
对应的反汇编代码为
004010CC |. C745 D8 00104>mov dword ptr [ebp-28], 00401000 ; mov @stWndClass.lpfnWndProc,offset _ProcWinMain
我们找到对应的地址并跳转过去看看
1 00401000 /. 55 push ebp 2 00401001 |. 8BEC mov ebp, esp 3 00401003 |. 83C4 AC add esp, -54 4 00401006 |. 53 push ebx 5 00401007 |. 57 push edi 6 00401008 |. 56 push esi 7 00401009 |. 8B45 0C mov eax, dword ptr [ebp+C] 8 0040100C |. 83F8 0F cmp eax, 0F 9 0040100F |. 75 3E jnz short 0040104F 10 00401011 |. 8D45 C0 lea eax, dword ptr [ebp-40] 11 00401014 |. 50 push eax ; /pPaintstruct 12 00401015 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 13 00401018 |. E8 53010000 call <jmp.&user32.BeginPaint> ; \BeginPaint 14 0040101D |. 8945 AC mov dword ptr [ebp-54], eax 15 00401020 |. 8D45 B0 lea eax, dword ptr [ebp-50] 16 00401023 |. 50 push eax ; /pRect 17 00401024 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 18 00401027 |. E8 6E010000 call <jmp.&user32.GetClientRect> ; \GetClientRect 19 0040102C |. 6A 25 push 25 ; /Flags = DT_CENTER|DT_VCENTER|DT_SINGLELINE 20 0040102E |. 8D45 B0 lea eax, dword ptr [ebp-50] ; | 21 00401031 |. 50 push eax ; |pRect 22 00401032 |. 6A FF push -1 ; |Count = FFFFFFFF (-1.) 23 00401034 |. 68 6A204000 push 0040206A ; |Text = "Win32 Assembly, Simple and powerful !" 24 00401039 |. FF75 AC push dword ptr [ebp-54] ; |hDC 25 0040103C |. E8 4D010000 call <jmp.&user32.DrawTextA> ; \DrawTextA 26 00401041 |. 8D45 C0 lea eax, dword ptr [ebp-40] 27 00401044 |. 50 push eax ; /pPaintstruct 28 00401045 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 29 00401048 |. E8 47010000 call <jmp.&user32.EndPaint> ; \EndPaint 30 0040104D |. EB 31 jmp short 00401080 31 0040104F |> 83F8 10 cmp eax, 10 32 00401052 |. 75 14 jnz short 00401068 33 00401054 |. FF35 04304000 push dword ptr [403004] ; /hWnd = 001107D4 ('My first Window !',class='MyClass') 34 0040105A |. E8 23010000 call <jmp.&user32.DestroyWindow> ; \DestroyWindow 35 0040105F |. 6A 00 push 0 ; /ExitCode = 0 36 00401061 |. E8 46010000 call <jmp.&user32.PostQuitMessage> ; \PostQuitMessage 37 00401066 |. EB 18 jmp short 00401080 38 00401068 |> FF75 14 push dword ptr [ebp+14] ; /lParam 39 0040106B |. FF75 10 push dword ptr [ebp+10] ; |wParam 40 0040106E |. FF75 0C push dword ptr [ebp+C] ; |Message 41 00401071 |. FF75 08 push dword ptr [ebp+8] ; |hWnd 42 00401074 |. E8 03010000 call <jmp.&user32.DefWindowProcA> ; \DefWindowProcA 43 00401079 |. 5E pop esi 44 0040107A |. 5F pop edi 45 0040107B |. 5B pop ebx 46 0040107C |. C9 leave 47 0040107D |. C2 1000 retn 10 48 00401080 |> 33C0 xor eax, eax 49 00401082 |. 5E pop esi 50 00401083 |. 5F pop edi 51 00401084 |. 5B pop ebx 52 00401085 |. C9 leave 53 00401086 \. C2 1000 retn 10
再来看看对应的源代码:
1 _ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam 2 local @stPs:PAINTSTRUCT 3 local @stRect:RECT 4 local @hDc 5 6 mov eax,uMsg 7 ;******************************************************************** 8 .if eax == WM_PAINT 9 invoke BeginPaint,hWnd,addr @stPs 10 mov @hDc,eax 11 12 invoke GetClientRect,hWnd,addr @stRect 13 invoke DrawText,@hDc,addr szText,-1,\ 14 addr @stRect,\ 15 DT_SINGLELINE or DT_CENTER or DT_VCENTER 16 17 invoke EndPaint,hWnd,addr @stPs 18 ;******************************************************************** 19 .elseif eax == WM_CLOSE 20 invoke DestroyWindow,hWinMain 21 invoke PostQuitMessage,NULL 22 ;******************************************************************** 23 .else 24 invoke DefWindowProc,hWnd,uMsg,wParam,lParam 25 ret 26 .endif 27 ;******************************************************************** 28 xor eax,eax 29 ret 30 31 _ProcWinMain endp
对应起来差距不是很大,这样看代码会觉得清晰很多,如果我们写的代码和反汇编的代码基本一样,就说明技术过关了。