C 语言的3种循环分析
---forward
C 语言中一共有三种类型的循环语句while 语句、语句、do
do 语句和for 语句,同样都是循环语句但是从汇编的角度来看他们有着不同的循环流程,做了次简单的逆向分析如下
(1)while 循环
While 在进入循环前会先进行判断,根据比较的结果来决定是否进行循环在进入循环前会先进行判断,根据比较的结果来决定是否进行循环,
,如下面代码(到时候我会打包一起上传)
int a,b;
scanf("%d",&b);/*此处省略N 多行反汇编代码*/
a=0;
00401039mov dword ptr [ebp-4],0
while(a<b){/*根据值得比较判断是否进入循环*/
00401040mov ecx,dword ptr [ebp-4]
00401043cmp ecx,dword ptr [ebp-8]
00401046jge main+54h (00401064)
printf("%d\n",a);
00401048mov edx,dword ptr [ebp-4]
0040104B push edx
0040104C push offset string "%d\n"(0042501c)
00401051call printf (00401090)
00401056add esp,8
a++;
00401059mov eax,dword ptr [ebp-4]
0040105C add eax,1
0040105F mov dword ptr [ebp-4],eax
}/*jmp 指令直接跳到起始处,重新开始*/
00401062jmp main+30h (00401040)
15:return 0;
00401064xor eax,eax
在这里要区分if 和while while,经过反汇编后的,经过反汇编后的while(a<b)while(a<b)与
与if 条件判断的结构非常相似。都是比较相反,比较完之后都往下跳。光从这一点来看它们是一样
的,无法直观的的分辨无法直观的的分辨。
看看jge 的目标地址00401064上面有一个jmp 指令并且是指向循环起始处的,很明显这个是个循环语句。可以根据这一个特性来辨
别if 判断和while 判断。判断。利用利用IDA 的流程图分析更为直观如图
(2)(2)do
do 循环Do 语句是先进行循环再判断成立则继续循环,这一点正好和while 循环相反
int a,b;/*a,b;/*初始化变量初始化变量初始化变量*/
*/a=0;
00401028mov dword ptr [ebp-4],0
scanf("%d",&b);/*/*将变量
将变量b 的值存于ebp-4处*/0040102F lea eax,[ebp-8]
00401032push eax
00401033push offset string "%d"(0042212c)
00401038call scanf (0040f900)
0040103D add esp,8
do{/*do{/*未进行判断直接进入循环体未进行判断直接进入循环体未进行判断直接进入循环体*/
*/printf("%d\n",a);/*/*水平有限解释不了水平有限解释不了水平有限解释不了*/
*/00401040mov ecx,dword ptr [ebp-4]
00401043push ecx
00401044push offset string "%d\n"(0042201c)
00401049call printf (00401080)
0040104E add esp,8
a++;
00401051mov edx,dword ptr [ebp-4]
00401054add edx,1
00401057mov dword ptr [ebp-4],edx
}while(a<b);/*/*判断是否退出循环,判断是否退出循环,判断是否退出循环,JL JL 指令是小于则跳转指令是小于则跳转*/
*/0040105A mov eax,dword ptr [ebp-4]
0040105D cmp eax,dword ptr [ebp-8]
00401060jl main+30h (00401040)
return 0;
00401062xor eax,eax
在上面代码中判断语句while while((a>b a>b))的反汇编代码与if 的结构相似的结构相似,
,相对于之前的比较容易区分。前的比较容易区分。If If 比较的是相反,并且是往下跳的。而do 循环的判断循环的判断句
句while while((a<b a<b)是网上面跳的。有了这个特点区别
)是网上面跳的。有了这个特点区别if 和do 语句就相对容易了。你或许发现do 至始至终只有一个跳转
指令至始至终只有一个跳转指令,,而while 有两个跳转指令有两个跳转指令,,这里就提高了效率。这也就是do 循环要比while 循环效率高的原因了。
在我平常分析有while 发布版程序中发现
While While(条件)(条件)(条件){
{部分代码
}
往往被优化成
if if(条件)(条件)(条件){
{Do{
代码
}while }while(条件)
(条件)}
如图,逆向的是while 的发布版本
(3)for 循环
For 循环是最复杂的,由初始值,循环条件以及步长组成。效率也是最低的。但是for 循环用起来更为自然,所以他在程序被使用的频率挺高的。如下代码所示。
int a,b;
scanf("%d",&b);
00401028lea eax,[ebp-8]
0040102B push eax
0040102C push offset string"%d"(00425020)
00401031call scanf(00401120)
00401036add esp,8
for(a=0;a<b;a++)
00401039mov dword ptr[ebp-4],0;设置初始值
代码00401040jmp main+3Bh(0040104b);跳过步长a++
a++代码00401042mov ecx,dword ptr[ebp-4]
00401045add ecx,1
00401048mov dword ptr[ebp-4],ecx
0040104B mov edx,dword ptr[ebp-4]
0040104E cmp edx,dword ptr[ebp-8];比较条件
00401051jge main+56h(00401066);用于跳出循环
printf("%d\n",a);
00401053mov eax,dword ptr[ebp-4]
00401056push eax
00401057push offset string"%d\n"(0042501c)
0040105C call printf(004010a0)
00401061add esp,8
00401064jmp main+32h(00401042);跳回循环起始处
return0;while循环语句的程序流程图
00401066xor eax,eax
在给初始值赋值之后,直接用jmp指令跳过第一次步长计算指令,跳到cmp处判断是否进入循环。往下,执行完循环块时又出现一个jmp指令,并且指向步长计算的代码。
遇上这样的循环代码块时,可以直接判断为for循环。
通过对发布版的反汇编会发现被优化的惨不忍睹,和while的优化思想一样同样被优化成先if然后do循环
的嵌套语句块,从而减少跳转的次数达到优化的目的。所以一般情况下很难分辨是for循环与while循环,还原成等价的代码即可。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。