循环是我们编程中遇到的另外一项重要技术。通过反复的迭代运算,我们可以获取想要的任何结果。当然这种迭代是有基本条件的,或是以时间为条件的,或是以空间为条件的,或者是某一种外来交互作为条件的。循环的方式有很多种,但是常用的还是:while、for、do-while、goto这几种。很多公司的项目都不喜欢goto,这其中倒不是说goto不好,主要是goto的随意性太大,一旦用的不好,就会降低代码的可读性,反而影响其他人的工作效率。
(1)do-while为什么先执行,后判断?
老规矩,我们还是先看代码示例再说:
21: int m = 10; 00401638 mov dword ptr [ebp-4],0Ah 22: do { 23: printf("%d\n", m); 0040163F mov eax,dword ptr [ebp-4] 00401642 push eax 00401643 push offset string "%d\n" (0046f01c) 00401648 call printf (00420fb0) 0040164D add esp,8 24: m ++; 00401650 mov ecx,dword ptr [ebp-4] 00401653 add ecx,1 00401656 mov dword ptr [ebp-4],ecx 25: }while(m < 10); 00401659 cmp dword ptr [ebp-4],0Ah 0040165D jl process+1Fh (0040163f) |
如果换成while呢?
21: int m = 10; 00401638 mov dword ptr [ebp-4],0Ah 22: while(m < 20) 0040163F cmp dword ptr [ebp-4],14h 00401643 jge process+41h (00401661) 23: { 24: printf("%d\n", m); 00401645 mov eax,dword ptr [ebp-4] 00401648 push eax 00401649 push offset string "%d\n" (0046f01c) 0040164E call printf (00420fb0) 00401653 add esp,8 25: m ++; 00401656 mov ecx,dword ptr [ebp-4] 00401659 add ecx,1 0040165C mov dword ptr [ebp-4],ecx 26: } 0040165F jmp process+1Fh (0040163f) 27: } |
其实,上面的代码表现已经很明显了。do-while的时候,模块上来先进行运算,然后再判断数据范围的大小;while就不一样,上来就进行判断,判断成功就继续运行,否则就退出循环模块,如果是for的情况呢?
21: for(int m = 10; m < 20; m++) 00401638 mov dword ptr [ebp-4],0Ah 0040163F jmp process+2Ah (0040164a) 00401641 mov eax,dword ptr [ebp-4] 00401644 add eax,1 00401647 mov dword ptr [ebp-4],eax 0040164A cmp dword ptr [ebp-4],14h 0040164E jge process+4Ch (0040166c) 22: { 23: printf("%d\n", m); 00401650 mov ecx,dword ptr [ebp-4] 00401653 push ecx 00401654 push offset string "%d\n" (0046f01c) 00401659 call printf (00420fc0) 0040165E add esp,8 24: m ++; 00401661 mov edx,dword ptr [ebp-4] 00401664 add edx,1 00401667 mov dword ptr [ebp-4],edx 25: } 0040166A jmp process+21h (00401641) |
我们发现,其实for和上面的while,do-while有点小区别。在m第一次赋值的时候,并不进行加1处理,而是直接跳到地址0x40164a处运行,判断m数值和20进行判断。判断成功,则跳入循环模块,否则越过循环模块。那么,在循环处理结束后呢?也就是m++后,循环模块是怎么处理的?我们发现代码又回到了0x00401641处处理。但是这里并不是整个循环模块开始出的代码,而是对m进行自增处理。完成自增后,继续判断,下面的流程和第一次一样,不再赘述。