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

时间:2022-10-17 03:32:31


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,这时比较yn

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

       jge     .L3 //i大于等于n,跳转到L3,结束循环

        movl   %edx, %eax //nval = t

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

.L3:

       popl    %ebx

       popl    %esi

       popl    %ebp

       ret

 

汇编代码会少做一次 nval = t 赋值操作,这对实际返回结果并没有什么影响,但是可以简化汇编代码,因为返回结果是需要保存在 eax 中的。