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



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 进行循环。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用RISC-V汇编语言实现大数计算乘除的示例代码: ``` # RISC-V大数计算乘除示例代码 # 定义大数位数 #define N 32 # 定义大数结构体 .struct BigInt .word sign # 符号位 .word data[N] # 数据位 .end # 定义乘法函数 .globl mul mul: addi sp, sp, -16 # 保存寄存器 sw ra, 0(sp) sw s0, 4(sp) sw s1, 8(sp) # 读取参数 mv s0, a0 # 大数1指针 mv s1, a1 # 大数2指针 mv a0, zero # 乘积指针 # 处理符号位 lw t0, 0(s0) lw t1, 0(s1) xor t2, t0, t1 srl t2, t2, 31 sw t2, 0(a0) # 初始化乘积为0 li t3, 0 li t4, 0 # 循环计算乘积 li t5, 0 li t6, 0 li t7, N mul_loop: beqz t7, mul_end # 结束循环 addi t7, t7, -1 lw t5, 4(s0) lw t6, 4(s1) mul t5, t5, t6 add t5, t5, t4 add t5, t5, t3 sw t5, 4(a0) srl t3, t5, 32 sll t4, t5, 32 srli t4, t4, 32 addi s0, s0, 4 addi s1, s1, 4 addi a0, a0, 4 j mul_loop mul_end: lw ra, 0(sp) lw s0, 4(sp) lw s1, 8(sp) addi sp, sp, 16 ret # 定义除法函数 .globl div div: addi sp, sp, -16 # 保存寄存器 sw ra, 0(sp) sw s0, 4(sp) sw s1, 8(sp) # 读取参数 mv s0, a0 # 大数1指针 mv s1, a1 # 大数2指针 mv a0, zero # 商指针 mv a1, zero # 余数指针 # 处理符号位 lw t0, 0(s0) lw t1, 0(s1) xor t2, t0, t1 srl t2, t2, 31 sw t2, 0(a0) # 初始化余数为被除数 li t3, 0 li t4, 0 li t5, 0 li t6, 0 li t7, N beqz t7, div_end # 被除数为0 addi t7, t7, -1 lw t5, 4(s0) lw t6, 4(s1) div_loop: blt t7, 0, div_end # 结束循环 sll t3, t3, 32 sll t4, t4, 32 sll t5, t5, 32 srl t6, t6, 32 add t3, t3, t4 add t4, t5, t6 li t5, 0 li t6, 0 li t8, 31 div_inner_loop: beqz t8, div_inner_end # 内层循环结束 addi t8, t8, -1 sll t5, t5, 1 sll t6, t6, 1 srl t7, t4, 63 add t5, t5, t7 andi t7, t4, 1 sll t6, t6, 1 or t6, t6, t7 addi t4, t4, -1 j div_inner_loop div_inner_end: sub t5, t5, 1 sub t6, t6, t3 srl t7, t6, 31 addi t7, t7, 1 xor t6, t6, t7 addi t6, t6, -1 add t3, t3, t5 addi s0, s0, 4 addi a0, a0, 4 addi t7, t7, -1 j div_loop div_end: sw t3, 4(a1) lw ra, 0(sp) lw s0, 4(sp) lw s1, 8(sp) addi sp, sp, 16 ret ``` 这个代码实现了一个BigInt结构体,其中包含一个符号位和一个32位的数据数组,用于存储大数。mul函数实现了大数乘法,div函数实现了大数除法。 在mul函数中,我们首先读取两个大数的指针,并准备一个用于存储乘积的指针。然后处理符号位,并初始化乘积为0。接下来进入循环,每次从两个大数中读取一个数据,并进行乘法运算。由于RISC-V的乘法指令只能得到低32位的乘积,因此我们需要使用加法将高位进位到下一次乘法中。最后将乘积存储到结果数组中,并更新进位值。重复上述步骤直到完成乘法。 在div函数中,我们首先读取两个大数的指针,并准备一个用于存储商和余数的指针。然后处理符号位,并初始化余数为被除数。接下来进入循环,每次将余数左移32位,并从被除数中读取一个数据。然后进入内层循环,将余数左移1位,并将被除数右移1位。如果余数大于等于除数,则将商的相应位设为1,并从余数中减去除数。最后将余数存储到结果数组中。重复上述步骤直到完成除法。 需要注意的是,这个代码只是一个简单的示例,对于实际应用还需要进行更多的优化和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值