[32位汇编系列]004 - 对话框资源的使用(2)

这一节, 我们主要分析上一节 中的反汇编代码,通过汇编代码的分析, 让你更加的清楚汇编程序的处理逻辑
也让你了解我们写出的汇编源码和反汇编代码之间的差别和对应关系

程序分为2个部分, 一个是程序的入口, 通过DialogBoxParam函数启动一个对话框
另一个就是对话框的处理过程, 这个是关键, 下面是反汇编代码的分析:

_ProcDlgMain处理过程:

窗口处理过程只处理了三个消息WM_COMMAND, WM_INITDIALOG, WM_CLOSE

00401000   .  55            push    ebp
00401001   .  8BEC          mov     ebp, esp

00401003   .  8B45 0C       mov     eax, dword ptr [ebp+C]

mov eax, uMsg 将消息值送入eax

00401006   .  3D 11010000   cmp     eax, 111                         ;  Switch (cases 10..111)
比较消息值是否WM_COMMAND消息

0040100B   .  75 6D         jnz     short 0040107A
不是, 转入下一个消息的判断

下面是WM_COMMAND消息的处理
WM_COMMAND消息的
wParam 参数的高16为是通知码, 低16位是控件ID
lParam 参数为控件的句柄

0040100D   .  8B45 10       mov     eax, dword ptr [ebp+10]          ;  Case 111 (WM_COMMAND) of switch 00401006
mov eax, wParam   得到wParam参数

00401010   .  66:83F8 01    cmp     ax, 1
比较控件ID是不是IDOK

00401014   .  75 52         jnz     short 00401068
不是IDOK则转入下一个判断

00401016   .  6A 00         push    0                                ; /IsSigned = FALSE
00401018   .  6A 00         push    0                                ; |pSuccess = NULL
0040101A   .  68 E8030000   push    3E8                              ; |ControlID = 3E8 (1000.)
0040101F   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401022   .  E8 D7000000   call    <jmp.&user32.GetDlgItemInt>      ; /GetDlgItemInt

用GetDlgItemInt函数得到被除数

00401027   .  50            push    eax
保存被除数

00401028   .  6A 00         push    0                                ; /IsSigned = FALSE
0040102A   .  6A 00         push    0                                ; |pSuccess = NULL
0040102C   .  68 E9030000   push    3E9                              ; |ControlID = 3E9 (1001.)
00401031   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401034   .  E8 C5000000   call    <jmp.&user32.GetDlgItemInt>      ; /GetDlgItemInt

得到除数

00401039   .  8BC8          mov     ecx, eax
将除数送入ecx

0040103B   .  33D2          xor     edx, edx
被除数高32位清0

0040103D   .  58            pop     eax
得到被除数低32位

0040103E   .  0BC9          or      ecx, ecx
看看除数是否为0

00401040   .  74 77         je      short 004010B9
如果为0, 则不做处理,直接退出

00401042   .  F7F1          div     ecx
被除数不为0, 则进行32位无符号除法运算
对于32位无符号除法运算, 被除数是64位的, 用寄存器edx保存高32位, 用eax保存低32位
除数是32位的, 运算的结果, 商放在eax中, 余数放在edx中

00401044   .  50            push    eax
保存商

00401045   .  6A 00         push    0                                ; /IsSigned = FALSE
00401047   .  52            push    edx                              ; |Value
00401048   .  68 EB030000   push    3EB                              ; |ControlID = 3EB (1003.)
0040104D   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401050   .  E8 AF000000   call    <jmp.&user32.SetDlgItemInt>      ; /SetDlgItemInt

调用SetDlgItemInt将余数edx显示在对应的文本框中


00401055   .  58            pop     eax
得到商

00401056   .  6A 00         push    0                                ; /IsSigned = FALSE
00401058   .  50            push    eax                              ; |Value
00401059   .  68 EA030000   push    3EA                              ; |ControlID = 3EA (1002.)
0040105E   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401061   .  E8 9E000000   call    <jmp.&user32.SetDlgItemInt>      ; /SetDlgItemInt

用SetDlgItemInt将商eax显示在对应的文本框中

00401066   .  EB 51         jmp     short 004010B9
处理完毕, 退出


00401068   >  66:83F8 02    cmp     ax, 2
比较控件ID是不是IDCANCEL

0040106C   .  75 4B         jnz     short 004010B9
不是, 则退出

0040106E   .  6A 00         push    0                                ; /Result = 0
00401070   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401073   .  E8 7A000000   call    <jmp.&user32.EndDialog>          ; /EndDialog

调用EndDialog关闭对话框

00401078   .  EB 3F         jmp     short 004010B9

处理完毕,退出


0040107A   >  3D 10010000   cmp     eax, 110
看看是不是WM_INITDIALOG

0040107F   .  75 1E         jnz     short 0040109F
不是, 则转入下一个消息判断

00401081   .  68 E8030000   push    3E8                              ; /ControlID = 3E8 (1000.); Case 110 (WM_INITDIALOG) of switch 00401006
00401086   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401089   .  E8 6A000000   call    <jmp.&user32.GetDlgItem>         ; /GetDlgItem
0040108E   .  50            push    eax                              ; /hWnd
0040108F   .  E8 76000000   call    <jmp.&user32.SetFocus>           ; /SetFocus
00401094   .  B8 00000000   mov     eax, 0
00401099   .  C9            leave
0040109A   .  C2 1000       retn    10
0040109D   .  EB 1A         jmp     short 004010B9

处理WM_INITDIALOG消息, 用GetDlgItem得到被除数文本框的句柄, 并用SetFocus设置焦点
注意, 在WM_INITDIALOG中设置控件焦点后, 必须返回FALSE,即0, 否则焦点设置无效


0040109F   >  83F8 10       cmp     eax, 10
看看是不是WM_CLOSE

004010A2   .  75 0C         jnz     short 004010B0
不是,则转入默认处理

004010A4   .  6A 00         push    0                                ; /Result = 0; Case 10 (WM_CLOSE) of switch 00401006
004010A6   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004010A9   .  E8 44000000   call    <jmp.&user32.EndDialog>          ; /EndDialog
004010AE   .  EB 09         jmp     short 004010B9

处理WM_CLOSE消息, 结束对话框, 退出程序

004010B0   >  B8 00000000   mov     eax, 0                           ;  Default case of switch 00401006
004010B5   .  C9            leave
004010B6   .  C2 1000       retn    10

对话框默认处理, 如果eax的值是0, 则表示消息未处理,交给对话框的默认处理过程处理


004010B9   >  B8 01000000   mov     eax, 1
004010BE   .  C9            leave
004010BF   .  C2 1000       retn    10

如果eax的值是1, 则表示消息已经处理过


程序入口点:
004010C2 >/$  6A 00         push    0                                ; /pModule = NULL
004010C4  |.  E8 4D000000   call    <jmp.&kernel32.GetModuleHandleA> ; /GetModuleHandleA

用GetModuleHandleA获取模块句柄, 就是实例句柄

004010C9  |.  A3 00304000   mov     dword ptr [403000], eax
将获取的实例句柄存入全局变量hInstance中

004010CE  |.  6A 00         push    0                                ; /lParam = NULL
004010D0  |.  68 00104000   push    00401000                         ; |DlgProc = Dialog.00401000
004010D5  |.  6A 00         push    0                                ; |hOwner = NULL
004010D7  |.  6A 65         push    65                               ; |pTemplate = 65
004010D9  |.  FF35 00304000 push    dword ptr [403000]               ; |hInst = NULL
004010DF  |.  E8 08000000   call    <jmp.&user32.DialogBoxParamA>    ; /DialogBoxParamA

调用DialogBoxParamA,产生一个对话框,该函数原型如下:
INT_PTR DialogBoxParam(
  HINSTANCE hInstance,     // handle to module
  LPCTSTR lpTemplateName,  // dialog box template
  HWND hWndParent,         // handle to owner window
  DLGPROC lpDialogFunc,    // dialog box procedure
  LPARAM dwInitParam       // initialization value
);


hInstance        实例句柄
lpTemplateName        对话框资源名称,这里可填入资源ID
hWndParent        父窗口
lpDialogFunc        对话框窗口过程, 这里可以处理我们感兴趣的消息
dwInitParam        对话框创库过程的lParam参数

只有当你点击关闭按钮的时候, 这个函数才结束,也就是说,这个函数内部有一个消息循环
不断的处理对话框的各种消息

004010E4  |.  6A 00         push    0                                ; /ExitCode = 0
004010E6  /.  E8 25000000   call    <jmp.&kernel32.ExitProcess>      ; /ExitProcess

调用ExitProcess退出程序

 

这个程序需要注意的是, 用div ecx进行运算后, edx和eax分别保存着32位无符号除法的余数和商

如果要用SetDlgItemInt函数把它们显示在文本框中, 则至少先要保存其中的一个, 因为SetDlgItemInt

会修改eax, ecx, edx寄存器, 如果不保存的话, 则会破坏运算的结果

 

对于整个程序的分析到此为止, 可以看出用了资源之后, 我们可以把更多的精力放在任务处理上
而不必花费时间自己去创建界面。 对于用sdk写windows应用程序的朋友来说, 可以用汇编很容易
的写出用c写出的程序, 然而用汇编写的程序, 不仅程序体积小, 而且效率也更高。
所以,用masm32的宏和VC资源编辑器, 写出功能强大而且效率高的复杂程序不再是一个难题。

<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值