用汇编的眼光看C++(之循环流程)

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

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


    循环是我们编程中遇到的另外一项重要技术。通过反复的迭代运算,我们可以获取想要的任何结果。当然这种迭代是有基本条件的,或是以时间为条件的,或是以空间为条件的,或者是某一种外来交互作为条件的。循环的方式有很多种,但是常用的还是:while、for、do-while、goto这几种。很多公司的项目都不喜欢goto,这其中倒不是说goto不好,主要是goto的随意性太大,一旦用的不好,就会降低代码的可读性,反而影响其他人的工作效率。

    (1)do-while为什么先执行,后判断?

    老规矩,我们还是先看代码示例再说:


 
 
  1. 21: int m = 10;
  2. 00401638 mov dword ptr [ebp- 4],0Ah
  3. 22: do {
  4. 23: printf( "%d\n", m);
  5. 0040163F mov eax,dword ptr [ebp- 4]
  6. 00401642 push eax
  7. 00401643 push offset string "%d\n" ( 0046f01c)
  8. 00401648 call printf ( 00420fb 0)
  9. 0040164D add esp, 8
  10. 24: m ++;
  11. 00401650 mov ecx,dword ptr [ebp- 4]
  12. 00401653 add ecx, 1
  13. 00401656 mov dword ptr [ebp- 4],ecx
  14. 25: } while( m < 10);
  15. 00401659 cmp dword ptr [ebp- 4],0Ah
  16. 0040165D jl process+ 1Fh ( 0040163f)
    如果换成while呢?


 
 
  1. 21: int m = 10;
  2. 00401638 mov dword ptr [ebp- 4],0Ah
  3. 22: while( m < 20)
  4. 0040163F cmp dword ptr [ebp- 4], 14h
  5. 00401643 jge process+ 41h ( 00401661)
  6. 23: {
  7. 24: printf( "%d\n", m);
  8. 00401645 mov eax,dword ptr [ebp- 4]
  9. 00401648 push eax
  10. 00401649 push offset string "%d\n" ( 0046f01c)
  11. 0040164E call printf ( 00420fb 0)
  12. 00401653 add esp, 8
  13. 25: m ++;
  14. 00401656 mov ecx,dword ptr [ebp- 4]
  15. 00401659 add ecx, 1
  16. 0040165C mov dword ptr [ebp- 4],ecx
  17. 26: }
  18. 0040165F jmp process+ 1Fh ( 0040163f)
  19. 27: }
    其实,上面的代码表现已经很明显了。do-while的时候,模块上来先进行运算,然后再判断数据范围的大小;while就不一样,上来就进行判断,判断成功就继续运行,否则就退出循环模块,如果是for的情况呢?


 
 
  1. 21: for( int m = 10; m < 20; 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], 14h
  8. 0040164E jge process+ 4Ch ( 0040166c)
  9. 22: {
  10. 23: printf( "%d\n", m);
  11. 00401650 mov ecx,dword ptr [ebp- 4]
  12. 00401653 push ecx
  13. 00401654 push offset string "%d\n" ( 0046f01c)
  14. 00401659 call printf ( 00420fc 0)
  15. 0040165E add esp, 8
  16. 24: m ++;
  17. 00401661 mov edx,dword ptr [ebp- 4]
  18. 00401664 add edx, 1
  19. 00401667 mov dword ptr [ebp- 4],edx
  20. 25: }
  21. 0040166A jmp process+ 21h ( 00401641)
    我们发现,其实for和上面的while,do-while有点小区别。在m第一次赋值的时候,并不进行加1处理,而是直接跳到地址0x40164a处运行,判断m数值和20进行判断。判断成功,则跳入循环模块,否则越过循环模块。那么,在循环处理结束后呢?也就是m++后,循环模块是怎么处理的?我们发现代码又回到了0x00401641处处理。但是这里并不是整个循环模块开始出的代码,而是对m进行自增处理。完成自增后,继续判断,下面的流程和第一次一样,不再赘述。


    (2)多重循环怎么跳出来?

    很多朋友编码的时候都有这样的一个困扰,有的时候希望在多层循环中寻找某一个条件的变量,但是在找到特定变量后,希望赶快退出循环。我们应该怎么做呢,下面是我个人的做法,仅供大家参考。


 
 
  1. int flag = 0;
  2. for( int m = 1; m < 20 && !flag; m++)
  3. {
  4. for( int n = 1; n < 20 && !flag; n++)
  5. {
  6. for( int t = 1; t < 20 && !flag; t++)
  7. {
  8. if( /* special conditions are satisfied */)
  9. flag = 1;
  10. }
  11. }
  12. }


    (3)while(1)是否有其他的表示方法?


 
 
  1. int flag = 0;
  2. for(;;) {
  3. /* code segment */
  4. }
  5. do{
  6. /* code segment */
  7. } while( 1);
  8. loop:
  9. {
  10. /* code segment */
  11. }
  12. if(!flag)
  13. goto loop;

总结:

    其实,循环中还有很多的细节需要处理,你比如说:

    (1)循环的时候请务必填上程序终止的条件

    (2)循环的时候注意8位char和32和int之间的区别,务必不要死循环

    (3)字符的循环务必注意‘\0’

    (4)不要把循环、判断合二为1,给你的同事留条活路,不要以为while(*dst ++  = *src ++);这样写代码很帅

    (5)务必注意自己的返回值是你需要的那个地址,还是前一个地址,还是下一个地址

     (6)不要在for(;;)中添加额外的语句,加的越多,风险越多

    

【预报: 下面主要讨论break、continue、goto的灵活使用,欢迎关注】



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值