while循环与do-while循环不同,是先判断循环条件。gcc会把while循环转换成如下格式的代码,再生成汇编代码:
if (循环条件不成立)
goto done
do
{
表达式
…
}while(循环条件)
done:
...
示例1:
int loop_while(int a, int b)
{
inti = 0;
intresult = a;
while (i < 256) {
result += a;
a-= b;
i+= b;
}
return result;
}
gcc -O1 -S -m32 while1.c
loop_while:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
movl 8(%ebp), %ecx //ecx = a
movl 12(%ebp), %eax //eax =b
movl %eax, %ebx //ebx = b
movl %ecx, %esi // esi = a =result
movl %eax, %edx //edx = b = i
movl %eax, %edi //edi = b
negl %edi //edi = -b
.L2:
addl %ecx, %esi // esi = result+ a = result
addl %edi, %ecx //ecx = a – b =a
addl %ebx, %edx //edx = i + b =i
movl %edx, %eax //eax = i
subl %ebx, %eax //eax = i-b
cmpl $255, %eax //比较eax和255
jle .L2 //如果小于等于跳转到L2,继续循环
movl %esi, %eax //跳出循环后,eax =result
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
对于本例,因为gcc确定第一次循环条件为真,所以省略了第一次判断。
int loop_while_goto(int a, int b)
{
inti = 0;
intresult = a;
loop:
result += a;
a-= b;
i+= b;
if(i <= 255)
goto loop;
return result;
}
gcc -O1 -S -m32 while2.c
loop_while_goto:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
movl 8(%ebp), %ecx
movl 12(%ebp), %eax
movl %eax, %ebx
movl %ecx, %esi
movl %eax, %edx
movl %eax, %edi
negl %edi
.L2:
addl %ecx, %esi
addl %edi, %ecx
addl %ebx, %edx
movl %edx, %eax
subl %ebx, %eax
cmpl $255, %eax
jle .L2
movl %esi, %eax
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
产生的汇编代码是一样的。
示例2:
int fib_w(int n)
{
int i = 1;
int val = 1;
int nval = 1;
while (i < n) {
intt = val+nval;
val= nval;
nval= t;
i++;
}
return val;
}
gcc -O1 -S -m32 fib_w.c
fib_w:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %ebx
movl 8(%ebp), %esi //esi = n
movl $1, %eax //nval=1
cmpl $1, %esi //比较n和1
jle .L4 //如果n小于等于1,跳转到L4,返回1。
movl $1, %ecx //ecx= i= 1
movl $1, %ebx //ebx=val = 1
movl $1, %eax //eax=nval = 1
.L5:
addl $1, %ecx //i++
leal (%eax,%ebx), %edx //t=val+ nval
movl %eax, %ebx //val = nval
cmpl %esi, %ecx //比较i和n
je .L4 //如果相等,跳转到L4,返回nval(=val)
movl %edx, %eax //nval = t
jmp .L5 //跳转到L5,继续循环
.L4:
popl %ebx
popl %esi
popl %ebp
ret
这个例子就是先判断条件,再使用 do-while 进行循环。