设为首页 加入收藏

TOP

5.7 do/while/for的比较(2)
2013-10-07 14:29:46 来源: 作者: 【 】 浏览:68
Tags:5.7 do/while/for 比较

5.7 do/while/for的比较(2)

如果遇到以上代码块,即可判定它为一个do循环结构,只有do循环结构无需先检查,直接执行循环语句块。根据条件跳转指令所跳转到的地址,可以得到循环语句块的首地址,jxx指令的地址为循环语句块的结尾地址。在还原while比较时,应该注意,它与if不同,while的比较数并不是相反,而是相同的。依此分析即可还原do循环结构的原型。

(2)while循环

while循环和do循环正好相反,在执行循环语句块之前,必须要进行条件判断,根据比较结果再选择是否执行循环语句块,如代码清单5-23所示。

代码清单5-23 while循环—Debug版

  1. // C++(www.cppentry.com)源码说明:while循环完成整数累加和  
  2. int LoopWhile(int nCount){  
  3.             int nSum = 0;  
  4.             int nIndex = 0;  
  5.             // 先执行条件比较,再进入循环体  
  6.             while (nIndex <= nCount){  
  7.                 nSum += nIndex;  
  8.                 nIndex++;  
  9.             }  
  10.             return nSum;  
  11. }  
  12.  
  13. // C++(www.cppentry.com)源码于对应汇编代码讲解  
  14. int nSum = 0;  
  15. 0040B7C8   mov         dword ptr [ebp-4],0  
  16. int nIndex = 0;  
  17. 0040B7CF   mov         dword ptr [ebp-8],0  
  18. // C++(www.cppentry.com)源码对比,判断循环条件  
  19. while (nIndex <= nCount)  
  20. 0040B7D6   mov         eax,dword ptr [ebp-8]  
  21. 0040B7D9   cmp         eax,dword ptr [ebp+8]  
  22. ; 条件判断比较,使用JG指令,大于则跳转到地址0x0040B7F2处,和if语句一样  
  23. ; 地址0x0040B7F2为while循环结束地址  
  24. 0040B7DC   jg          LoopWhile+42h (0040b7f2)  
  25. {  
  26.     // 循环语句块  
  27. nSum += nIndex;  
  28. 0040B7DE   mov         ecx,dword ptr [ebp-4]  
  29. 0040B7E1   add         ecx,dword ptr [ebp-8]  
  30. 0040B7E4   mov         dword ptr [ebp-4],ecx  
  31. nIndex++;  
  32. 0040B7E7   mov         edx,dword ptr [ebp-8]  
  33. 0040B7EA   add         edx,1  
  34. 0040B7ED   mov         dword ptr [ebp-8],edx  
  35. }  
  36. ; 执行跳转指令JMP,跳转到地址0x0040B7D6处  
  37. 0040B7F0   jmp         LoopWhile+26h (0040b7d6)  
  38. return nSum;  
  39. 0040B7F2   mov         eax,dword ptr [ebp-4] 

在代码清单5-23中,转换后的while比较和if语句一样,也是比较相反,向下跳转。如何区分代码中是分支结果还是循环结构呢?查看条件指令跳转地址0x0040B7F2,如果这个地址上有一句JMP指令,并且此指令跳转到的地址小于当前代码地址,那么很明显是一个向上跳转。要完成语句循环,就需要修改程序流程,回到循环语句处,因此向上跳转就成了循环结构的明显特征。根据这些特性可知while循环结构的特征,在条件跳转到的地址附近会有JMP指令修改程序流程,向上跳转,回到条件比较指令处。

while循环结构中使用了两次跳转指令完成循环,由于多使用了一次跳转指令,因此while循环要比do循环效率低一些。

总结:

  1. WHILE_BEGIN:  
  2. ; 影响标记位的指令  
  3. jxx     WHILE_END           ; 条件成立跳转到循环语句块结尾处  
  4. ……                  ; 循环语句块  
  5. jmp     WHILE_BEGIN         ; 跳转到取出条件比较数据处  
  6. WHILE_END: 

遇到以上代码块,即可判定它为一个while循环结构。根据条件跳转指令,可以还原相反的while循环判断。循环语句块的结尾地址即为条件跳转指令的目标地址,在这个地址之前会有一条jmp跳转指令,指令的目标地址为while循环的起始地址。需要注意的是,while循环结构很可能会被优化成do循环结构,被转换后的while结构由于需要检查是否可以被成功执行一次,通常会被嵌套在if单分支结构中,其还原的高级代码如下所示:
  1. if(xxx)  
  2. {  
  3.     do  
  4.     {  
  5.         // ……  
  6. }while(xxx)  

(3)for循环

for循环是三种循环结构中最复杂的一种。for循环由赋初值、设置循环条件、设置循环步长这三条语句组成。由于for循环更符合人类的思维方式,在循环结构中被使用的频率也最高。根据for语句组成特性分析代码清单5-24。

代码清单5-24 for循环结构—Debug版

  1. // C++(www.cppentry.com)源码说明:for循环完成整数累加和  
  2. int LoopFor(int nCount){  
  3.     int nSum = 0;  
  4.     // 初始计数器变量、设置循环条件、设置循环步长  
  5.     for (int nIndex = 0; nIndex <= nCount; nIndex++){  
  6.         nSum += nIndex;  
  7.     }  
  8.     return nSum;  
  9. }  
  10.  
  11. // C++(www.cppentry.com)源码于对应汇编代码讲解  
  12. int nSum = 0;  
  13. 0040B818   mov         dword ptr [ebp-4],0  
  14. // C++(www.cppentry.com)源码对比,for语句  
  15. for (int nIndex = 0; nIndex <= nCount; nIndex++)  
  16. ;=====================================================  
  17. ; 初始化计数器变量—nIndex                   1.赋初值部分  
  18. 0040B81F   mov         dword ptr [ebp-8],0  
  19. ; 跳转到地址0x0040B831处,跳过步长操作  
  20. 0040B826   jmp         LoopFor+31h (0040b831)  
  21. ;=====================================================  
  22. ; 取出计数器变量,用于循环步长                    2.步长计算部分  
  23. 0040B828   mov         eax,dword ptr [ebp-8]  
  24. ; 对计数器变量执行加1操作,步长值为1  
  25. 0040B82B   add         eax,1  
  26. ; 将加1后的步长值放回计数器变量—nIndex  
  27. 0040B82E   mov         dword ptr [ebp-8],eax  
  28. ;=====================================================  
  29. ; 取出计数器变量nIndex放入ecx                    3.条件比较部分  
  30. 0040B831   mov         ecx,dword ptr [ebp-8]  
  31. ; ebp+8地址处存放数据为参数nCount,见C++(www.cppentry.com)源码说明  
  32. 0040B834   cmp         ecx,dword ptr [ebp+8]  
  33. ; 比较nIndex与nCount,大于则跳转到地址0x0040B844处,结束循环  
  34. 0040B837   jg          LoopFor+44h (0040b844)  
  35. ;=====================================================  
  36. {  
  37.     // for循环内执行语句块  
  38. nSum += nIndex;  
  39. mov         edx,dword ptr [ebp-4]                ; 4.循环体代码  
  40. 0040B83C   add         edx,dword ptr [ebp-8]  
  41. 0040B83F   mov         dword ptr [ebp-4],edx  
  42. }  
  43. ; 跳转到地址0x0040B828处,这是一个向上跳  
  44. 0040B842   jmp         LoopFor+28h (0040b828)  
  45. return nSum;  
  46. // 设置返回值eax为ebp-4,即nSum  
  47. 0040B844   mov         eax,dword ptr [ebp-4] 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇5.7 do/while/for的比较(3) 下一篇12.1 识别类和类之间的关系(1)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: