gcc会把do-while循环转换成如下形式的代码,再生成汇编代码:
loop:
表达式
…
t = 循环条件
if(t)
goto loop
示例1:
int dw_loop(int x, int y, int n)
{
do{
x+= n;
y*= n;
n--;
}while ((n > 0) & (y < n)); /* Note use of bitwise '&' */
return x;
}
gcc -O1 -S -m32 dw.c
dw_loop:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax //eax = x
movl 12(%ebp), %ecx //ecx = y
movl 16(%ebp), %edx //edx = n
.L3:
addl %edx, %eax // eax = x +n =x
imull %edx, %ecx //ecx = y*n = y
subl $1, %edx //edx = n-1 = n
testl %edx, %edx //测试n是正数、负数或0
jle .L5 //如果n小于等于0,跳转到L5,跳出循环
cmpl %edx, %ecx //否则,说明n>0,这时比较y和n
jl .L3 //如果y<n,跳转到L3,继续循环。
.L5:
popl %ebp
ret
示例2:
int fib_dw(int n)
{
int i = 0;
int val = 0;
int nval = 1;
do {
intt = val + nval;
val= nval;
nval= t;
i++;
}while (i < n);
return val;
}
gcc -O1 -S -m32 fib_dw.c
fib_dw:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
movl 8(%ebp), %esi //esi = n
movl $0, %ecx //ecx = 0 =i
movl $0, %ebx //ebx=0 = val
movl $1, %eax //eax = 1 = nval
.L2:
addl $1, %ecx //i++
leal (%eax,%ebx), %edx//edx =val + nval = t
movl %eax, %ebx //val = nval
cmpl %esi, %ecx //比较i和n
jge .L3 //i大于等于n,跳转到L3,结束循环
movl %edx, %eax //nval = t
jmp .L2 //跳转到L2,继续循环
.L3:
popl %ebx
popl %esi
popl %ebp
ret
汇编代码会少做一次 nval = t 赋值操作,这对实际返回结果并没有什么影响,但是可以简化汇编代码,因为返回结果是需要保存在 eax 中的。