用汇编的眼光看C++(之退出流程)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/feixiaoxing/article/details/6766366

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    无论是在判断还是在循环的过程中,通常在遇到合适的条件的时候就会退出相应的模块。跳出模块运行的方式很多,break,continue,return都可以。下面我们就可以分别对他们进行将介绍。

    (1)continue只能用于循环,而break循环、判断都可以应用。两者有什么区别呢?


 
 
  1. 21: for( int m = 10; m < 100; m ++)
  2. 00401638 mov dword ptr [ebp -4], 0Ah
  3. 0040163F jmp process+ 2Ah ( 0040164a)
  4. 00401641 mov eax,dword ptr [ebp -4]
  5. 00401644 add eax, 1
  6. 00401647 mov dword ptr [ebp -4],eax
  7. 0040164A cmp dword ptr [ebp -4], 64h
  8. 0040164E jge process+ 55h ( 00401675)
  9. 22: {
  10. 23: if(m / 20 == 3)
  11. 00401650 mov eax,dword ptr [ebp -4]
  12. 00401653 cdq
  13. 00401654 mov ecx, 14h
  14. 00401659 idiv eax,ecx
  15. 0040165B cmp eax, 3
  16. 0040165E jne process+ 42h ( 00401662)
  17. 24: {
  18. 25: break;
  19. 00401660 jmp process+ 55h ( 00401675)
  20. 26: }
  21. 27:
  22. 28: if(m / 10 == 0)
  23. 00401662 mov eax,dword ptr [ebp -4]
  24. 00401665 cdq
  25. 00401666 mov ecx, 0Ah
  26. 0040166B idiv eax,ecx
  27. 0040166D test eax,eax
  28. 0040166F jne process+ 53h ( 00401673)
  29. 29: {
  30. 30: continue;
  31. 00401671 jmp process+ 21h ( 00401641)
  32. 31: }
  33. 32: }
  34. 00401673 jmp process+ 21h ( 00401641)
    我们在循环模块里面可以看到了代码做了两次判断。一次判断是查看m除以20是否等于3,一次判断是查看m除以10是否可以整除。同样,前面的判断结果是break,后面的结果是continue,那么两者之间的区别是什么呢?我们可以好好看一下。在第一次条件判断的时候,我们发现如果m除以20不等于3,那么下面指令直接跳转到0x00401662,也就是第二条件的入口处。但是如果第一个条件判断成功了,那么程序就会跳转到地址0x00401675,也就是说整个循环模块已经结束了。而continue呢?我们发现不管条件判断是否为真,那么指令都会跳转到0x00401641处执行,也就是循环+1的地方。这说明continue结束的只是本次循环,整个循环的流程还没有结束,而break表示当前已经推出了整个循环模块。如果大家对书本上的概念还有些模糊的话,那么汇编指令在这里已经把细节之处解释得明明白白了。


    (2)goto一般用的情况不多,但是有一种情况例外?


 
 
  1. void process()
  2. {
  3. if( /* get resources one */ == 0)
  4. {
  5. return;
  6. }
  7. if( /* get resource two */ == 0)
  8. {
  9. /* free resource one */
  10. return;
  11. }
  12. if( /* get resource three */ == 0)
  13. {
  14. /* free resource two */
  15. /* free resource one */
  16. return;
  17. }
  18. if( /* get resource four */ == 0)
  19. {
  20. /* free resource three */
  21. /* free resource two */
  22. /* free resource one */
  23. return;
  24. }
  25. /* ... */
  26. }
    通常情况下,我们创建一个对象时,需要各种各样的资源,等到所有资源都分配齐了,我们的代码才能开始工作。但是事实上,也存在很多分配失败的可能性。如果遇到了分配失败,那么我们就要对原来的资源进行释放处理。随着资源的总数越来越多,这个代码块就会显得越来越臃肿。那么有没有什么好的办法解决这一难题呢?goto就是一种好的选择。

 
 
  1. void process()
  2. {
  3. if( /* get resources one */ == 0)
  4. {
  5. return;
  6. }
  7. if( /* get resource two */ == 0)
  8. {
  9. goto fail_one;
  10. }
  11. if( /* get resource three */ == 0)
  12. {
  13. goto fail_two;
  14. }
  15. if( /* get resource four */ == 0)
  16. {
  17. goto fail_three;
  18. }
  19. /* ... */
  20. fail_three:
  21. /* free resource three */
  22. fail_two:
  23. /* free resource two */
  24. fail_one:
  25. /* free resource one */
  26. return;
  27. }

    (3) return也是跳出代码段一个很好的方法。

    它不光可以在函数中使用,也可以灵活运用在循环语句、判断语句中。要是在递归语句中,更是少不了他的身影。比如说,我们现在查看一个字符串是否满足这样一个结构:

    str = ab | a str b;

    那么换成函数代码应该怎么编写呢?大家可以自己先试一试,下面是我的一个方法:


 
 
  1. BOOL process_multi_char( const char* str, int length)
  2. {
  3. if( 2 == length)
  4. return !strncmp(str, "ab", strlen( "ab")) ? TRUE : FALSE;
  5. if(str[ 0] == 'a' && str[length -1] == 'b')
  6. return process_multi_char(str+ 1, length -2);
  7. else
  8. return FALSE;
  9. }
  10. BOOL process( const char str[], int length)
  11. {
  12. if( NULL == str || length < 2 || ( 0 != length % 2))
  13. return FALSE;
  14. return process_multi_char(&str[ 0], length);
  15. }

     这里return的好处就是充分把字符串进行了拆分。我们按照定义,先从基本的问题下手,大事化小,小事化了。当然这里的小事就是字符串这有两个字符的情形,也是最底层函数的出口。要不然函数就会一致不停地处理下去,这是没有意义的。计算过程中一旦发现了不合法的运算,那么整个迭代的过程就会结束,快速回溯,输出结果。所以说要想写好递归或者是用到堆栈结构的代码时,必须考虑代码的入口和出口的把握,而return就是最好的选择,什么时候return,什么时候迭代都要把握时机,否则很容易陷入到死循环当中去。



【预告: 下面的博客是用汇编的眼光看C++之嵌入式汇编】





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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值