在C语言中循环会用到for和while结构,现在对比一下。
先看看for循环。C语言代码:
#include <stdio.h> int main() { int x = 0; for (int i = 1;i <= 100;i++) x = x + i; return 0; }
这段代码用来计算1到100累计相加的结果,编译后使用IDA进行分析,看反汇编代码:
.text:00401000 push ebp .text:00401001 mov ebp, esp .text:00401003 sub esp, 8 .text:00401006 mov [ebp+x], 0 .text:0040100D mov [ebp+i], 1
这里定义了两个int型的变量x和i,分别给它们赋值0和1
.text:00401014 jmp short loc_40101F .text:00401016 mov eax, [ebp+i] .text:00401019 add eax, 1 .text:0040101C mov [ebp+i], eax .text:0040101F cmp [ebp+i], 64h .text:00401023 jg short loc_401030 .text:00401025 mov ecx, [ebp+x] .text:00401028 add ecx, [ebp+i] .text:0040102B mov [ebp+x], ecx .text:0040102E jmp short loc_401016
这里是循环体的代码。在对变量x和i初始化以后直接跳到0x0040101F处把循环变量和0x64进行比较,0x64就是十进制的100,当循环变量i大于0x64时则跳出循环体,如果循环变量i不大于0x64时,把变量x和变量i相加,结果存回变量x,然后跳回循环头部,使循环变量i自增1,然后再次和0x64进行比较,直到循环变量i大于0x64才退出循环。
.text:00401030 xor eax, eax .text:00401032 mov esp, ebp .text:00401034 pop ebp .text:00401035 retn
再来看一看while循环的方式:
#include <stdio.h> int main() { int x = 0; int i = 101; while (i--) x = x + i; return 0; }
同样是一段计算1到100累计相加的结果的代码,编译后使用IDA进行分析,看反汇编代码:
.text:00401000 push ebp .text:00401001 mov ebp, esp .text:00401003 sub esp, 8 .text:00401006 mov [ebp+x], 0 .text:0040100D mov [ebp+i], 65h
这里定义了两个int型的变量x和i,分别给它们赋值0和0x65,0x65即十进制的101
.text:00401014 mov eax, [ebp+i] .text:00401017 mov ecx, [ebp+i] .text:0040101A sub ecx, 1 .text:0040101D mov [ebp+i], ecx .text:00401020 test eax, eax .text:00401022 jz short loc_40102F .text:00401024 mov edx, [ebp+x] .text:00401027 add edx, [ebp+i] .text:0040102A mov [ebp+x], edx .text:0040102D jmp short loc_401014
这一部分是循环体的代码,取出变量i的值,放入寄存器eax和ecx中,使ecx减1,然后存回变量i中,接下来使用test指令测试eax是不是0,eax是还没有减1前的变量i的值,如果eax等于0则跳出循环体部分,否则不执行跳转,把变量x和变量i相加,结果存回变量x,最后跳回循环头部重新计算。
.text:0040102F xor eax, eax .text:00401031 mov esp, ebp .text:00401033 pop ebp .text:00401034 retn
while循环还有一种形式为do-while结构:
#include <stdio.h> int main() { int x = 0; int i = 100; do{ x = x + i; } while (--i); return 0; }
依然一段计算1到100累计相加的结果的代码,编译后使用IDA进行分析,看反汇编代码:
.text:00401000 push ebp .text:00401001 mov ebp, esp .text:00401003 sub esp, 8 .text:00401006 mov [ebp+x], 0 .text:0040100D mov [ebp+i], 64h
这里定义了两个int型的变量x和i,分别给它们赋值0和0x64,0x64即十进制的100。
.text:00401014 mov eax, [ebp+x] .text:00401017 add eax, [ebp+i] .text:0040101A mov [ebp+x], eax .text:0040101D mov ecx, [ebp+i] .text:00401020 sub ecx, 1 .text:00401023 mov [ebp+i], ecx .text:00401026 jnz short loc_401014
这一段是循环体的代码。把变量x和变量i相加,然后把结果存回变量x中,然后取变量i的值,减1后把结果存回变量i中,最后跳到循环头部重新计算。
.text:00401028 xor eax, eax .text:0040102A mov esp, ebp .text:0040102C pop ebp .text:0040102D retn