windows程序设计(2)

 

继续上反汇编

源代码

程序2-1  SCRNSIZE
        
SCRNSIZE.C
        
/*---------------------------------------------------------------------------
        
    SCRNSIZE.C -- Displays screen size in a message box
        
                 (c) Charles Petzold, 1998
        
----------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include <tchar.h>   
        
#include <stdio.h>   
        
int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
        
{
        
    TCHAR   szBuffer [1024] ;
        
    va_list pArgList ;
        

    // The va_start macro (defined in STDARG.H) is usually equivalent to:
        
    // pArgList = (char *) &szFormat + sizeof (szFormat) ;
        

    va_start (pArgList, szFormat) ;
        

    // The last argument to wvsprintf points to the arguments
        

    _vsntprintf ( szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
        
                   szFormat, pArgList) ;
        

    // The va_end macro just zeroes out pArgList for no good reason
        
    va_end (pArgList) ;
        
    return MessageBox (NULL, szBuffer, szCaption, 0) ;
        
}
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                   PSTR szCmdLine, int iCmdShow)
        
{
        
    int cxScreen, cyScreen ;
        
    cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
        
    cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
        

    MessageBoxPrintf (    TEXT ("ScrnSize"),
        
                   TEXT ("The screen is %i pixels wide by %i pixels high."),
        
                   cxScreen, cyScreen) ;
        
    return 0 ;
        
}


 

49:
50:   int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
51:
52:                      PSTR szCmdLine, int iCmdShow) 53:  // windows 程序 入口函数 WINAPI 宏定义 #define WINAPI __stdcall 遵从标准函数调  由子程序平衡堆栈 参数从右向左压栈
54:   {
004010D0   push        ebp                                              //ebp压栈
004010D1   mov         ebp,esp                              //ebp作为esp的副本。
004010D3   sub         esp,48h                            //堆栈开辟48h的空间
004010D6   push        ebx                                      
004010D7   push        esi
004010D8   push        edi                                //保存现场
004010D9   lea         edi,[ebp-48h]                //12h的字节写入0cccccccch  防止堆栈溢出 同时可作为局部变量缓冲区
004010DC   mov         ecx,12h                       
004010E1   mov         eax,0CCCCCCCCh
004010E6   rep stos    dword ptr [edi]
55:
56:       int cxScreen, cyScreen ;
57:
58:       cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
004010E8   mov         esi,esp                                              
004010EA   push        0                                                         //0作为参数压栈 代表获取x值  
004010EC   call        dword ptr [__imp__GetSystemMetrics@4 (0042a2b0)]           //调用win32api GetSystemMetrics() 返回值eax

004010F2   cmp         esi,esp                                                                                               //GetSystemMetrics是一个能用来获得Windows中不同对象的尺寸信息的函数
004010F4   call        __chkesp (00401270)                               //检测修复堆栈平衡
004010F9   mov         dword ptr [ebp-4],eax                                //ebp-4处  局部变量cxScreen 地址 保存在那里
59:
60:       cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
004010FC   mov         esi,esp
004010FE   push        1                                             //1作为参数压栈  代表获取y值
00401100   call        dword ptr [__imp__GetSystemMetrics@4 (0042a2b0)]
00401106   cmp         esi,esp
00401108   call        __chkesp (00401270)
0040110D   mov         dword ptr [ebp-8],eax   //ebp-8处为局部变量cxScreen地址
61:
62:
63:       MessageBoxPrintf (    TEXT ("ScrnSize"),
64:
65:                      TEXT ("The screen is %i pixels wide by %i pixels high."),
66:
67:                      cxScreen, cyScreen) ;
00401110   mov         eax,dword ptr [ebp-8]          //   取cyScreen
00401113   push        eax                    
00401114   mov         ecx,dword ptr [ ebp-4]              // 取 cxScreen
00401117   push        ecx
00401118   push        offset string "The screen is %i pixels wide by "... (00422028)  //取格式字符串
0040111D   push        offset string "ScrnSize" (0042201c)   // 取对话框标题参数
00401122   call        @ILT+0(_MessageBoxPrintf) (00401005)         //调用 _MessageBoxPrintf子函数

             跟入 子程序  来到 00401005处  
           
            00401005   jmp         MessageBoxPrintf (00401020) //一条跳转指令  这种调用形式是由于 输入地址表iat造成的 编译器无法识别普通函数调用和输入函数调用。所以统一格式,子程序调用。
             
跟入 来到子程序处                                                                                                                                    11:   #include <windows.h>
12:
13:   #include <tchar.h>
14:
15:   #include <stdio.h>
16:
17:   int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
18:
19:   {
00401020   push        ebp               
00401021   mov         ebp,esp
00401023   sub         esp,444h
00401029   push        ebx
0040102A   push        esi
0040102B   push        edi
0040102C   lea         edi,[ebp-444h]
00401032   mov         ecx,111h
00401037   mov         eax,0CCCCCCCCh            //分许同上
0040103C   rep stos    dword ptr [edi]
20:
21:       TCHAR   szBuffer [1024] ;
22:
23:       va_list pArgList ;
24:
25:
26:       // The va_start macro (defined in STDARG.H) is usually equivalent to:
27:
28:       // pArgList = (char *) &szFormat + sizeof (szFormat) ;
29:
30:
31:       va_start (pArgList, szFormat) ;
0040103E   lea         eax,[ebp+10h]               //ebp+10h处开始,是传入的参数 ,这里将参数地址传给eax                       33:                                                                                                                                 00401041   mov         dword ptr [ebp-404h],eax   //将参数保存在局部变量内,即pArgList
34:       // The last argument to wvsprintf points to the arguments
35:
36:
37:       _vsntprintf ( szBuffer, sizeof (szBuffer) / sizeof (TCHAR),
38:
39:                      szFormat, pArgList) ;
00401047   mov         ecx,dword ptr [ebp-404h]  //取pArgList 入栈
0040104D   push        ecx              
0040104E   mov         edx,dword ptr [ebp+0Ch]       //取倒数第三个参数入栈,即格式字符串地址
00401051   push        edx
00401052   push        400h                       //  大小
00401057   lea         eax,[ebp-400h]            //缓冲区
0040105D   push        eax
0040105E   call        _vsnprintf (00401170)    //调用_vsnprintf
00401063   add         esp,10h                  //_vsnprintf为 _cdel 规则调用   由调用者平衡堆栈 eax返回值为 格式化显示后的字符串长度
40:
41:
42:       // The va_end macro just zeroes out pArgList for no good reason
43:
44:       va_end (pArgList) ;
00401066   mov         dword ptr [ebp-404h],0  //将 pArgList置清0
45:
46:       return MessageBox (NULL, szBuffer, szCaption, 0);
00401070   mov         esi,esp
00401072   push        0
00401074   mov         ecx,dword ptr [ebp+8]
00401077   push        ecx
00401078   lea         edx,[ebp-400h]
0040107E   push        edx
0040107F   push        0
00401081   call        dword ptr [__imp__MessageBoxA@16 (0042a2b4)]
00401087   cmp         esi,esp
00401089   call        __chkesp (00401270)
47:
48:   }
0040108E   pop         edi
0040108F   pop         esi
00401090   pop         ebx
00401091   add         esp,444h       //int CDECL MessageBoxPrintf  是_cdecl调用  由调用者平衡堆栈 ,这里调用者是编译器?windows?
00401097   cmp         ebp,esp
00401099   call        __chkesp (00401270)
0040109E   mov         esp,ebp
004010A0   pop         ebp
004010A1   ret                                                                                                                     至此 返回 主程序 winmain中
00401127   add         esp,10h
68:
69:       return 0 ;
0040112A   xor         eax,eax             //eax返回0
70:
71:   }
0040112C   pop         edi
0040112D   pop         esi
0040112E   pop         ebx
0040112F   add         esp,48h
00401132   cmp         ebp,esp
00401134   call        __chkesp (00401270)
00401139   mov         esp,ebp
0040113B   pop         ebp
0040113C   ret         10h


 

由反汇编总结  va_start(pArgList,szFormat)宏的具体作用是取szFormat的地址保存在pArgList里,而va_list pArgList只是告诉编译器应该分配多大的指针空间。

va_end(pArgList)则是将pArgList所用空间清零。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值