关闭

用汇编的眼光看C++(之判断流程)

发表于:2012-5-16 09:43

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:feixiaoxing    来源:51Testing软件测试网采编

  在我们平常的编程当中,用于判断的地方很多,但主要有下面三种方式:if-else;switch;?:。其中最后一种方式在本质上和if-else是一样的。switch和if-else其实也一样,如果我们把switch改成if(...) {} else if(...) {} else {},那么你实现的效果和switch实际差不多,熟悉的朋友都会有这样的体验。或许有的朋友还是不太相信,大家可以自己用写实例比较看一下。

  (1)switch中的break重要吗?

21:       int m = 10;
004017A8   mov         dword ptr [ebp-4],0Ah
22:       switch(m)
23:       {
004017AF   mov         eax,dword ptr [ebp-4]
004017B2   mov         dword ptr [ebp-8],eax
004017B5   cmp         dword ptr [ebp-8],0Ah
004017B9   je          process+33h (004017c3)
004017BB   cmp         dword ptr [ebp-8],0Bh
004017BF   je          process+42h (004017d2)
004017C1   jmp         process+4Fh (004017df)
24:       case 10:
25:           printf("ten!\n");
004017C3   push        offset string "ten!\n" (0046f028)
004017C8   call        printf (004214d0)
004017CD   add         esp,4
26:           break;
004017D0   jmp         process+4Fh (004017df)
27:
28:       case 11:
29:           printf("eleven!\n");
004017D2   push        offset string "eleven!\n" (0046f01c)
004017D7   call        printf (004214d0)
004017DC   add         esp,4
30:           break;
31:
32:       default:
33:           break;
34:       }
35:       return;
36:   }

  上面的汇编代码说明了有break的时候,函数是怎么编译的。我们看到从地址0x4017AF处,CPU开始集中对m进行判断。首先,m的数据被赋值到eax,然后eax拷贝到堆栈【ebp-8】的内存当中。接着开始比较数据10,即16进制0A,如果两者相等,代码跳转到0x4017C3处理;但是如果不相等呢,那么指令会按照原来的排列顺序继续向下走,和11继续比较,如果比较成功,那么就会到地址0x4017d2处执行,如果都不相等,那么只好跳出switch模块,到地址0x4017df处执行了。前面我们说到,如果数据和10或者11比较成功的话,那么就会跳转到相应的case语句处继续执行,可是比较结束后,还会跳转到原来的位置吗?汇编代码告诉我们,他们不会。因为case比较结束后,也要到地址ox4017df处报到。

  如果这里case10后面没有break呢?情况会不会不一样呢?

004017A8   mov         dword ptr [ebp-4],0Ah
22:       switch(m)
23:       {
004017AF   mov         eax,dword ptr [ebp-4]
004017B2   mov         dword ptr [ebp-8],eax
004017B5   cmp         dword ptr [ebp-8],0Ah
004017B9   je          process+33h (004017c3)
004017BB   cmp         dword ptr [ebp-8],0Bh
004017BF   je          process+40h (004017d0)
004017C1   jmp         process+4Dh (004017dd)
24:       case 10:
25:           printf("ten!\n");
004017C3   push        offset string "ten!\n" (0046f028)
004017C8   call        printf (004214d0)
004017CD   add         esp,4
26:
27:       case 11:
28:           printf("eleven!\n");
004017D0   push        offset string "eleven!\n" (0046f01c)
004017D5   call        printf (004214d0)
004017DA   add         esp,4
29:           break;
30:
31:       default:
32:           break;
33:       }
34:       return;
35:   }

  我们在case10后面取消了break语句。和原来的情形稍有不同,我们发现case10在执行了printf函数之后,并没有跳出当前的switch模块,而是继续执行case11的语句。所以在输出结果的时候,你会发现ten和eleven都有打印。看了这样清晰的流程之后,相信你对break的重要性又有了新的认识。在汇编面前,一切都一目了然。

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号