日期:2014-05-16 浏览次数:21000 次
在x86里,循环指令有:
LOOP:ECX不为零时循环 LOOPE/LOOPZ:ECX不为零且标志Z=1时循环 LOOPNE/LOOPNZ:ECX不为零且标志Z=0时循环
但实质上,由于上面指令适用范围太窄,只能用于循环体非常简单的。所以往往是用条件跳转指令来实际循环。用例子来体现一下:
#include <stdio.h>
int loop_for( int n )
{
int sum = 0;
for ( int i = 0; i < n; i++ )
{
sum += i;
}
return sum;
}
int loop_while( int n )
{
int sum = 0;
int i = 0;
while ( i < n )
{
sum += i;
i++;
}
return sum;
}
int loop_do( int n )
{
int sum = 0;
int i = 0;
do
{
sum += i;
i++;
} while ( i < n );
return sum;
}
int main()
{
int n = 0;
scanf( "%d", &n );
return loop_for( n ) + loop_while( n )
+ loop_do( n );
}
看一下loop_do,loop_for, loop_while的汇编:
(gdb) disassemble loop_do Dump of assembler code for function _Z7loop_doi: 0x080485d4 <+0>: push %ebp 0x080485d5 <+1>: mov %esp,%ebp 0x080485d7 <+3>: sub $0x10,%esp 0x080485da <+6>: movl $0x0,-0x4(%ebp) 0x080485e1 <+13>: movl $0x0,-0x8(%ebp) 0x080485e8 <+20>: mov -0x8(%ebp),%eax 0x080485eb <+23>: add %eax,-0x4(%ebp) 0x080485ee <+26>: addl $0x1,-0x8(%ebp) 0x080485f2 <+30>: mov -0x8(%ebp),%eax 0x080485f5 <+33>: cmp 0x8(%ebp),%eax 0x080485f8 <+36>: setl %al 0x080485fb <+39>: test %al,%al 0x080485fd <+41>: jne 0x80485e8 <_Z7loop_doi+20> 0x080485ff <+43>: mov -0x4(%ebp),%eax 0x08048602 <+46>: leave 0x08048603 <+47>: ret End of assembler dump.
(gdb) disassemble loop_for Dump of assembler code for function _Z8loop_fori: 0x08048570 <+0>: push %ebp 0x08048571 <+1>: mov %esp,%ebp 0x08048573 <+3>: sub $0x10,%esp 0x08048576 <+6>: movl $0x0,-0x4(%ebp) 0x0804857d <+13>: movl $0x0,-0x8(%ebp) 0x08048584 <+20>: jmp 0x8048590 <_Z8loop_fori+32> 0x08048586 <+22>: mov -0x8(%ebp),%eax 0x08048589 <+25>: add %eax,-0x4(%ebp) 0x0804858c <+28>: addl $0x1,-0x8(%ebp) 0x08048590 <+32>: mov -0x8(%ebp),%eax 0x08048593 <+35>: cmp 0x8(%ebp),%eax 0x08048596 <+38>: setl %al 0x08048599 <+41>: test %al,%al 0x0804859b <+43>: jne 0x8048586 <_Z8loop_fori+22> 0x0804859d <+45>: mov -0x4(%ebp),%eax 0x080485a0 <+48>: leave 0x080485a1 <+49>: ret End of assembler dump.
(gdb) disassemble loop_while Dump of assembler code for function _Z10loop_whilei: 0x080485a2 <+0>: push %ebp 0x080485a3 <+1>: mov %esp,%ebp 0x080485a5 <+3>: sub $0x10,%esp 0x080485a8 <+6>: movl $0x0,-0x4(%ebp) 0x080485af <+13>: movl $0x0,-0x8(%ebp) 0x080485b6 <+20>: jmp 0x80485c2 <_Z10loop_whilei+32> 0x080485b8 <+22>: mov -0x8(%ebp),%eax 0x080485bb <+25>: add %eax,-0x4(%ebp) 0x080485be <+28>: addl $0x1,-0x8(%ebp) 0x080485c2 <+32>: mov -0x8(%ebp),%eax 0x080485c5 <+35>: cmp 0x8(%ebp),%eax 0x080485c8 <+38>: setl %al 0x080485cb <+41>: test %al,%al 0x080485cd <+43>: jne 0x80485b8 <_Z10loop_whilei+22> 0x080485cf <+45>: mov -0x4(%ebp),%eax 0x080485d2 <+48>: leave 0x080485d3 <+49>: ret End of assembler dump.
由于loop_for,loop_while的代码逻辑一样,连生成的汇编都是一样。loop_do和两者不大一样,所以,汇编不一样。现