SDK程序员经常写出的一段低效率代码

来源:互联网 发布:淘宝买鞋子注意事项 编辑:程序博客网 时间:2024/05/01 17:08

SDK程序员经常写出的一段低效率代码[代码优化][]



由于新版本的 MafaLSHelper v1.0 Standard 在编写当中需要涉及到一些更加复杂的操作,将导致以前用MASM32所编写的Utils.dll函数库供不应求,所以目前需要新增一批函数!如下列表:


------------------------------------------------------------------------------------------------------

1)       MStrFindAANSI)、MStrFindWUNICODE);攻能:查找字符串,并返回结果串,失败为0

2)       MStrCmpAANSI)、MStrCmpWUNICODE);攻能:比较字符串,和strcmp一样。

3)       MStrCmpiAANSI)、MStrCmpiWUNICODE);攻能:比较字符串,和strcmpi一样。

4)       MStrNCmpAANSI)、MStrNCmpWUNICODE);攻能:比较指定的N个字符串,和strcmpN一样。

5)       MGetAbsolutePathAANSI)、MGetAbsolutePathWUNICODE);攻能:从相对路径中获取绝对路径。

6)       MGetRelativePathAANSI)、MGetRelativePathWUNICODE);攻能:从绝对路径获取相对路径。

------------------------------------------------------------------------------------------------------

 

第一个函数即刻可从MStrRepA/W简化过来的。但是,众所周知社会在发展,人也一样,所以编程思想也在不断地进步,显然,代码质量也就相应的有所提高了…… 所以不是再那么简单地从MStrRepA/W简化过来了,事情变的更加地复杂,我不得不重新大规模地修改至少80%处左右的代码……

因此,为了能在编写的过程中可以更加快速的查看寄存器的变化,于是我在DLL内新增加了一个能显示当前寄存器的MessageBox。该函数前提地需要不能影响当前的所有寄存器及标志寄存器内的值。代码如下:

-----------------------------------------------------------------------------

MASM32 code:

MsgInfo PROC C pszFormat:DWORD, args:VARARG

   LOCAL szBuffer[6400]:BYTE

   PUSHAD
   PUSHFD
  
   LEA EAX, szBuffer
   MOV BYTE PTR [EAX], 00H
  
   LEA EAX, pszFormat
   ADD EAX, 4
  
   INVOKE wvsprintf, ADDR szBuffer, pszFormat, EAX
   INVOKE MessageBox, 0, /
                      ADDR szBuffer, /
                      ctext("Test"), /
                      MB_OK OR MB_ICONINFORMATION
   POPFD
   POPAD
  
   RET
MsgInfo ENDP

 

为了更大程度的优化代码,于是,我便用OllyDbg进行了如下反汇编DLL,结果MsgInfo函数出来的代码如下:

 

OllyDbg Code:

10001000    55              push    ebp
10001001    8BEC            mov     ebp, esp                             ;
上面那条和这条可用这一条代替:enter
10001003    81C4 00E7FFFF   add     esp, -1900
10001009    60              pushad
1000100A    9C              pushfd
1000100B    8D85 00E7FFFF   lea     eax, dword ptr ss:[ebp-1900]
10001011    C600 00         mov     byte ptr ds:[eax], 0
10001014    8D45 08         lea     eax, dword ptr ss:[ebp+8]
10001017    83C0 04         add     eax, 4
1000101A    50              push    eax
1000101B    FF75 08         push    dword ptr ss:[ebp+8]
1000101E    8D85 00E7FFFF   lea     eax, dword ptr ss:[ebp-1900]
10001024    50              push    eax
10001025    E8 960F0000     call    <jmp.&user32.wvsprintfA>
1000102A    6A 40           push    40
1000102C    68 10200010     push    Utils.10002010                   ; ASCII "Test"
10001031    8D85 00E7FFFF   lea     eax, dword ptr ss:[ebp-1900]
10001037    50              push    eax
10001038    6A 00           push    0
1000103A    E8 7B0F0000     call    <jmp.&user32.MessageBoxA>
1000103F    9D              popfd
10001040    61              popad
10001041    C9              leave                                      ;
代替这两条指令:mov esp, ebp
pop ebp
10001042    C3              retn

 

大家可以看出,MASM32写的代码,几乎和反汇编出来的结果一样!很惊奇吧?J

-----------------------------------------------------------------------------

 

说了那么多的废话,几乎都完全脱离主题了……汗一个先,不过总得让大家知道,我是因为什么才会拿出牛刀OllyDbg来调试我的C程序的……

 

现在我们来看一段SDK的代码:

 

///////////////////////////////////////////////////////////////////////////////////////////

 

//; MStrFindA MASM32 原型

//MStrFindA       proto pszExpression:DWORD, pszFind:DWORD, nStart:DWORD, nCount:DWORD

 

// C声明原型

EXPORT LPSTR MStrFindA( LPSTR pszExpression, LPCSTR pszFind, int nStart, int nCount );

 

#ifndef _UNICODE

#define MStrFindEx                  MStrFindA

#else

    #define MStrFindEx                  MStrFindW

#endif

 

#define MStrFind(pszExpression,pszFind)  /

MStrFindEx(pszExpression,pszFind,-1,-1);

 

///////////////////////////////////////////////////////////////////////////////////////////

 

int main(int argc, char** argv)

{

    TCHAR szDst[260] = TEXT("abcdef");

    TCHAR szFind[260] = TEXT("f");

    PTSTR pFound = NULL;

    

    pFound = MStrFind( szDst, szFind );

   

    _tprintf( TEXT("result of found:[%s]/n"), pFound  );

   

    return 0;

}

 

现在再来看看main函数的反汇编结果:

 

; 当前进程栈向下伸长208H个字节:260D + 260D = 520D

00401000  /$ >sub     esp, 208

 

; 获取堆中的常量串: TEXT("abcdef")
00401006  |. >mov     eax, dword ptr ds:[40704C]    ;  61 62 63 64  ----> abcd
0040100B  |. >mov     cx, word ptr ds:[407050]      ;  65 66  ----> ef
00401012  |. >mov     dl, byte ptr ds:[407052]      ;  00 ----> /0

 

;备份edi
00401018  |. >push    edi

 

; 完成 TCHAR szDst[260] = TEXT("abcdef"); 的赋值...
00401019  |. >mov     dword ptr ss:[esp+4], eax     ; 
填入 abcd 到第一个局部变量 szDst [1~4字节
]
0040101D  |. >mov     word ptr ss:[esp+8], cx       ; 
填入 ef 到第一个局部变量 szDst [5~6字节
]
00401022  |. >mov     ecx, 3F                       ;  252/4=63
00401027  |. >xor     eax, eax                      ; 
清零

00401029  |. >lea     edi, dword ptr ss:[esp+B]     ; 
串:abcdef/0 之后的地址. szDst [8字节]
0040102D  |. >mov     byte ptr ss:[esp+A], dl       ; 
/0 szDst [7字节
]
00401031  |. >rep     stosd                         ;  4*63=252, szDst[260]
剩下的2534字节对齐252字节进行清零

00401033  |. >stosb                                 ; 
最后一个字节253的清零

 

; 获取堆中的常量串:TEXT("f")
00401034  |. >mov     ax, word ptr ds:[407048]      ;  66 00 ----> f/0

 

; 1、完成 TCHAR szFind[260] = TEXT("f"); 的赋值;2、完成MStrFindA函数的参数压栈。
0040103A  |. >mov     ecx, 40                       ;  256/4=64
0040103F  |. >mov     word ptr ss:[esp+108], ax     ; 
填入 f/0 到第二个局部变量 szFind [1~2字节]
00401047  |. >xor     eax, eax                        
清零

00401049  |. >lea     edi, dword ptr ss:[esp+10A]   ; 
串:f/0之后的地址. szDst [3字节]
00401050  |. >push    -1                            ;  MStrFindA
参数4
int count =-1;
00401052  |. >rep     stosd                         ;  4*64=256, szFind[260]
剩下的2584字节对齐256字节进行清零

00401054  |. >lea     ecx, dword ptr ss:[esp+10C]   ;  szFind[0]
0040105B  |. >push    -1                            ;  MStrFindA
参数3int start=-1;
0040105D  |. >lea     edx, dword ptr ss:[esp+C]     ;  szDst[0]
00401061  |. >push    ecx                           ;  MStrFindA
参数2
PCSTR pszFind
00401062  |. >push    edx                           ;  MStrFindA
参数1
PCSTR pszExpression
00401063  |. >stosw                                 ;  szFind
最后一个WORD的清零


00401065  |. >call    <jmp.&Utils.MStrFindA>         ;  CALL MStrFindA
函数

 

; 调用_tprintf显示结果
0040106A  |. >push    eax                           ; 
查看返回值
0040106B  |. >push    test.00407030                 ;  result of found:[%s]/n
00401070  |. >call    test.00401096                 ;  _tprintf
00401075  |. >add     esp, 8                        ; 
恢复_tprintf的参数栈

; 确定return 00

00401078  |. >xor     eax, eax                      ;  return 0;

 

; 恢复 edi
0040107A  |. >pop     edi

; 恢复局部变量占用栈

0040107B  |. >add     esp, 208


00401081  /. >retn

 

///////////////////////////////////////////////////////////////////////////////////////////

 

经过上面的反汇编结果,我想SDK程序员应该都非常地清楚的在定义一个序列串时,如果初始化一个值给它,会有怎么样的结果!

汗不汗你?应该是满头了吧?这样还好点,最恐怖的就是出现如下面这样的代码:

 

TCHAR szFind[260] = TEXT("/0");

 

strcpy( szFind, TEXT("abc") );

 

我可以很直接地告诉你,第一条声明和赋值语句,会和上面反汇编的代码一样地处理(虽然它仅仅就是一个NULL),然后再进行CALL strcpy进行拷贝abc/0,怎么样?冒冷汗了吧你?所以大家以后写代码千万要小心了!在定义一个局部串时,如果真想要给他一个NULL,可以这样用:

 

TCHAR szFind[260];

*szFind = TEXT('/0');

 

你应该也猜到了吧,这行代码将转换成如下形式:

mov     byte ptr ss:[esp+N个偏移], 0

 

嘿嘿!不会再那么傻呼呼地原原版版地进行260个字节逐个进行一一地串门了吧。

 

                    By dreamerate at home written in 2007-6-7 01:13

                      dreamerate@gmail.com


From: http://blog.csdn.net/baofeng/archive/2007/06/07/1641565.aspx

原创粉丝点击