SDK程序员经常写出的一段低效率代码[代码优化][原]
2007-06-07 01:23
459 查看
SDK程序员经常写出的一段低效率代码[代码优化][原] 由于新版本的 MafaLSHelper v1.0 Standard 在编写当中需要涉及到一些更加复杂的操作,将导致以前用MASM32所编写的Utils.dll函数库供不应求,所以目前需要新增一批函数!如下列表: ------------------------------------------------------------------------------------------------------ 1) MStrFindA(ANSI)、MStrFindW(UNICODE);攻能:查找字符串,并返回结果串,失败为0。 2) MStrCmpA(ANSI)、MStrCmpW(UNICODE);攻能:比较字符串,和strcmp一样。 3) MStrCmpiA(ANSI)、MStrCmpiW(UNICODE);攻能:比较字符串,和strcmpi一样。 4) MStrNCmpA(ANSI)、MStrNCmpW(UNICODE);攻能:比较指定的N个字符串,和strcmpN一样。 5) MGetAbsolutePathA(ANSI)、MGetAbsolutePathW(UNICODE);攻能:从相对路径中获取绝对路径。 6) MGetRelativePathA(ANSI)、MGetRelativePathW(UNICODE);攻能:从绝对路径获取相对路径。 ------------------------------------------------------------------------------------------------------ 第一个函数即刻可从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]剩下的253的4字节对齐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]剩下的258的4字节对齐256字节进行清零 00401054 |. >lea ecx, dword ptr ss:[esp+10C] ; szFind[0] 0040105B |. >push -1 ; MStrFindA参数3:int 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 0的0值 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 |
相关文章推荐
- SDK程序员经常写出的一段低效率代码
- 一段阻塞队列代码的纠错与优化
- java也能写出点点算法-像C++一样去优化核心并发的代码例子1
- C#程序员经常用到的10个实用代码片段
- 月薪上万做好这一步:程序员职场中必须掌握的的Java代码性能优化技巧
- 开发代码性能优化,程序员你们知道哪些?
- 面试题---请写出一段Python代码实现删除一个list里面的重复元素
- 程序员有什么借口可以让自己写出低质量的代码
- 由一段代码谈前端js优化和编码规范(一) 分类: JavaScript 2015-03-21 12:43 668人阅读 评论(1) 收藏
- 用冒泡的方式对数组进行排序, 并写出对应的优化后的代码实现。(重点写思路、原理)
- 是什么导致优秀的程序员写出如此垃圾的代码?
- 后端程序员网上经常搜索的代码及命令
- 就是这个美女程序员,写出了让阿波罗成功登陆月球的代码!
- CSS优化,如何写出高效整洁的CSS代码
- 开发代码性能优化(下),程序员你们还知道哪些?
- 程序员如何写出更好的代码
- 由一段代码谈前端js优化和编码规范(一)
- 用选择的方式对数组进行排序,并写出对应的优化后的代码实现。(重点写思路、原理)
- SSE图像算法优化系列一:一段BGR2Y的SIMD代码解析。