32位汇编语言学习笔记(9)--分析while循环的汇编代码

时间:2023-01-03 01:18:18


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 //比较eax255

       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 //比较n1

       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 //比较in

       je     .L4 //如果相等,跳转到L4,返回nval(=val)

       movl   %edx, %eax //nval = t

       jmp    .L5 //跳转到L5,继续循环

.L4:

       popl   %ebx

       popl   %esi

       popl   %ebp

       ret

这个例子就是先判断条件,再使用 do-while 进行循环。