C++反汇编学习笔记2——循环语句
2013-12-17 18:23
417 查看
两年前写的,欢迎大家吐槽!
转载请注明出处。
1.1 do循环
首先来看一段goto语句(什么?不知道goto语句,C语言老师太水了吧,这都不教。其实就和无条件跳转指令JMP差不多,但是最好不要用,因为会破坏结构化)的例子:int GoToDo(intnCount)
{
int nSum =0;
int nIndex =0;
GOTO_DO:
nSum += nIndex;
nIndex++;
if (nIndex<= nCount)
{
gotoGOTO_DO;
}
return nSum;
}
没错,这个和do…while循环语句实现的功能相同,是一个循环,并且至少执行一遍。下面再来看主题:
23: int nSum = 0;
004272AE mov dword ptr [nSum],0
24: int nIndex = 0;
004272B5 mov dword ptr [nIndex],0
25: do
26: {
27: nSum += nIndex;
004272BC mov eax,dword ptr [nSum]
004272BF add eax,dword ptr [nIndex]
004272C2 mov dword ptr [nSum],eax
28: nIndex++;
004272C5 mov eax,dword ptr [nIndex]
004272C8 add eax,1
004272CB mov dword ptr [nIndex],eax
//先执行加操作
29: } while(nIndex <= nCount);
004272CE mov eax,dword ptr [nIndex]
004272D1 cmp eax,dword ptr [nCount]
004272D4 jle LoopDO+2Ch (4272BCh)
//跳转至do处
可以看到两段代码非常相似,但是仔细可以看出,if判定的条件和while判定的条件是相反的(这里指的是汇编代码的判定条件而不是C语言的代码),这样就很容易区分if语句与do…while之间的区别了。
1.2 while循环
由于循环结构的比较简单,所以就直接看例子,下面的也是。36: while (nIndex <= nCount)
0042730C mov eax,dword ptr [nIndex]
0042730F cmp eax,dword ptr [nCount]
00427312 jg LoopWhile+48h (427328h)
//先进行判断
37: {
38: nSum += nIndex;
00427314 mov eax,dword ptr [nSum]
00427317 add eax,dword ptr [nIndex]
0042731A mov dword ptr [nSum],eax
39: nIndex++;
0042731D mov eax,dword ptr [nIndex]
00427320 add eax,1
00427323 mov dword ptr [nIndex],eax
40: }
00427326 jmp LoopWhile+2Ch (42730Ch)
//无条件跳转至while循环开始处
可以看到while循环需要进行两次跳转,如此一来效率必然比不上do…while循环。但是可以将其优化成如下模式:
If(xxx)
{
do
{
}while(xxx);
}
1.3 for循环
for循环是最常用的循环语句,同时也较为复杂。例子:47: for (int nIndex = 0; nIndex <= nCount; ++nIndex)
00427365 mov dword ptr [nIndex],0
0042736C jmp LoopFor+37h (427377h)
//以上是赋初值部分,即nIndex = 0
0042736E mov eax,dword ptr [nIndex]
00427371 add eax,1
00427374 mov dword ptr [nIndex],eax
//步长计算部分,即++nIndex
00427377 mov eax,dword ptr [nIndex]
0042737A cmp eax,dword ptr [nCount]
0042737D jg LoopFor+4Ah (42738Ah)
//判断及跳转部分
48: {
49: nSum += nIndex;
0042737F mov eax,dword ptr [nSum]
00427382 add eax,dword ptr [nIndex]
00427385 mov dword ptr [nSum],eax
50: }
00427388 jmp LoopFor+2Eh (42736Eh)
//无条件跳转至步长计算部分
这里可以看到,for循环与while循环一样,都是先判断后执行,但是for循环共有3次跳转,是循环语句中效率最低的,但是如果把赋初值部分移动到循环之外即可转化为while循环然后再转化为do…while循环。
以上代码均为Debug版本的反汇编代码,Release版本的会按照后面讲解的优化方案进行优化,此处不再赘述。
1.4 循环结构优化——代码外提
例子:IDA Pro反汇编的Release版本源代码:
// 代码外提
int CodePick(intnCount)
{
int nSum =0;
int nIndex =0;
do
{
nSum += nIndex;
nIndex++;
} while(nIndex< nCount - 1);
return nSum;
}
反汇编代码:
.text:00401000 arg_0 = dword ptr 8
.text:00401000
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 mov edx, [ebp+arg_0]
.text:00401006 xor eax, eax
.text:00401008 xor ecx, ecx
.text:0040100A dec edx
.text:0040100B jmp short loc_401010
.text:0040100B ;---------------------------------------------------------------------------
.text:0040100D align 10h
.text:00401010
.text:00401010 loc_401010: ; CODE XREF:sub_401000+Bj
.text:00401010 ;sub_401000+15j
.text:00401010 add eax, ecx
.text:00401012 inc ecx
.text:00401013 cmp ecx,edx
.text:00401015 jl short loc_401010
可以很明显的看到.text:0040100A dec edx这条语句不在循环中,这就是代码外提。把不需要重复的计算都放到循环之外,这样可以减少计算量,提高计算效率。
1.5 强度降低
源代码:// 强度降低
void DoRate(int argc)
{
int t = 0;
int i = 0;
while (t <argc)
{
t = i * 99;
i++;
}
printf("%d",t);
}
这里只列出循环的反汇编代码:
.text:00401030 loc_401030: ; CODE XREF: sub_401020+17j
.text:00401030 mov eax, ecx
.text:00401032 add ecx, 63h
.text:00401035 cmp eax, edx
.text:00401037 jl short loc_401030
这里把乘法转化成了加法从而大大减少了运算量,提高了程序的执行效率。
相关文章推荐
- C++反汇编学习笔记1——选择判断语句
- C++学习笔记——第二章习题(四)-用循环语句打印图案
- 【C++学习笔记】for循环中的复合语句(语句块)
- shell脚本编程之循环语句学习笔记
- C++学习笔记 4th —— 万能流程控制if语句
- c++反汇编学习笔记-------------篇外1、if和switch效率的实测
- Java基础学习笔记(一)环境变量配置,数据类型,运算符,控制语句,循环语句
- Verilog学习笔记基本语法篇(六)········ 循环语句
- PHP学习笔记——循环结构for语句应用
- C++学习笔记-条件操作符&&开关语句
- 《C++ Primer Plus》第5章 循环和关系表达式 学习笔记
- C++学习笔记之三(C++语句基础之表达式与语句)
- Python学习笔记(五)——Python 判断循环语句
- 【菜鸟C++学习笔记】8.if语句
- FreeBASIC学习笔记——4.2 循环语句
- Java学习笔记---4.Java的分支循环语句
- 《python基础教程(第二版)》学习笔记 语句/循环/条件(第5章)
- 【菜鸟C++学习笔记】13.while语句
- C++反汇编学习笔记6——变量在内存中的位置和访问方式
- Python学习笔记(五)条件,循环和其他语句(上)