1.for循环
循环语句的代码是:
int sum(int x)
{
int i;
int res=0;
for(i=0;i<=x;i++)
res+=i;
return res;
}
产生的汇编代码为:
00000000<sum>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
d: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
14: eb 0a jmp 20 <sum+0x20>
16: 8b 45 f8 mov -0x8(%ebp),%eax
19: 01 45 fc add %eax,-0x4(%ebp)
1c: 83 45 f8 01 addl $0x1,-0x8(%ebp)
20: 8b 45 f8 mov -0x8(%ebp),%eax
23: 3b 45 08 cmp 0x8(%ebp),%eax
26: 7e ee jle 16 <sum+0x16>
28: 8b 45 fc mov -0x4(%ebp),%eax
2b: c9 leave
2c: c3 ret
编译器为函数分配了16字节的堆栈,变量存放在ebp偏移4字节处,而变量res存放在ebp偏移8字节处。上面的C代码可以写成以下伪代码:
int sum(int x)
{
int i=0;
int res=0;
jmp comp;
loop:
res+=x;
i++;
comp:
if(i<=x)
jmp loop;
}
这样,这段伪代码与上面的汇编代码就可以对应起来。
2.while循环
代码如下:
int sum(int x)
2{
int i;
int res=0;
while(i<=x)
{
res+=i;
i++;
}
return res;
}
产生的汇编代码如下:
00000000<sum>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
d: eb 0a jmp 19 <sum+0x19>
f: 8b 45 f8 mov -0x8(%ebp),%eax
12: 01 45 fc add %eax,-0x4(%ebp)
15: 83 45 f8 01 addl $0x1,-0x8(%ebp)
19: 8b 45 f8 mov -0x8(%ebp),%eax
1c: 3b 45 08 cmp 0x8(%ebp),%eax
1f: 7e ee jle f <sum+0xf>
21: 8b 45 fc mov -0x4(%ebp),%eax
24: c9 leave
25: c3 ret
从上面的汇编代码看出,变量i存放在寄存器ebp偏移8字节处,res存放在寄存器ebp偏移4字节处,返回值在寄存器eax中。
上面的C代码可以写成如下伪代码的形式:
int sum(int x)
{
int i=0;
int res=0;
jmp comp;
loop:
res+=i;
i++;
comp:
if(i<=x)
goto loop;
}
3.do...while循环
写C程序如下:
int sum(int x)
{
int i=0;
int res=0;
do{
res+=i;
i++;
}while(i<=x);
return res;
}
产生的汇编代码如下:
00000000<sum>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 10 sub $0x10,%esp
6: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
d: c745 fc 00 00 00 00 movl $0x0,-0x4(%ebp)
14: 8b 45 f8 mov -0x8(%ebp),%eax
17: 01 45 fc add %eax,-0x4(%ebp)
1a: 83 45 f8 01 addl $0x1,-0x8(%ebp)
1e: 8b 45 f8 mov -0x8(%ebp),%eax
21: 3b 45 08 cmp 0x8(%ebp),%eax
24: 7e ee jle 14 <sum+0x14>
26: 8b 45 fc mov -0x4(%ebp),%eax
29: c9 leave
2a: c3 ret
变量i存放在寄存器ebp偏移8字节处,变量res存放在寄存器偏移4字节处。
do...while循环产生的汇编代码与while循环稍有不同,因为do...while循环至少执行一次。
上面的C代码转为伪代码为:
int sum(int x)
{
int i=0;
int res=0;
loop:
res+=i;
i++;
if(i<=x)
goto loop;
}
编译器产生的汇编代码在不同的环境,gcc版本和优化级别情形下,可能有所不同,以上的汇编代码是在ubuntu中,使用gcc 4.7.2,在默认优化级别下产生的。