RISC-V汇编代码分析

csdn_myx 2022-05-17 19:19:25

一、RISC-V 通用寄存器

RISC-V 包含如下寄存器,其中 x0 ~ x31 为32个基础通用寄存器,每个寄存器的作用见下表描述。

img

其中最重要的寄存器包括:

  • ra:保存函数返回地址
  • sp:栈顶寄存器
  • a0 - a7:用于传递函数参数和返回值

上表最后一列表明在函数调用时该寄存器中的值由调用者还是被调用者来保存。例如,a0 - a7 由 Caller 来保存,所以在调用之前 Caller 就需要将这些寄存器的值暂存到栈上,以便调用返回时恢复,否则其值可能会被 Callee 修改。

二、RISC-V 基本指令

RISC-V 的指令集设计非常的精简,其只包含如下六种基本指令:

  • R类型:寄存器-寄存器操作;
  • I类型:短立即数和访存load操作;
  • S类型:访存store操作;
  • B类型:条件跳转操作;
  • U类型:长立即数;
  • J类型:无条件跳转。

具体格式如下所示:

img

三、RISC-V 汇编代码分析

接下来,我们以一个计算最大公约数的 C 程序来分析 RISC-V 汇编代码。

源程序如下:

#include <stdio.h>

int gcd(int a, int b) {
  return b ? gcd(b, a%b) : a;
}

int main() {
  int a = 12, b = 18;
  printf("%d\n", gcd(a,b));
}

通过如下命令编译为 RISC-V 汇编程序:

riscv64-linux-gnu-gcc -S -o test.s test.c

汇编程序及其分析如下(寄存器用$前缀表示):

        .file   "test.c"
        .option pic
        .text
        .align  1
        .globl  gcd
        .type   gcd, @function
gcd:
        addi    sp,sp,-32 ;栈帧指针下移
        sd      ra,24(sp) ;暂存$ra的值到栈上
        sd      s0,16(sp) ;暂存$s0的值到栈上
        addi    s0,sp,32 ;s0指向栈底
        mv      a5,a0 ;$a5 = a
        mv      a4,a1 ;$a4 = b
        sw      a5,-20(s0) ;暂存a到栈上
        mv      a5,a4 ;$a5 = b
        sw      a5,-24(s0) ;暂存b到栈上
        lw      a5,-24(s0)
        sext.w  a5,a5 ;符号扩展
        beqz    a5,.L2 ;若b为0则跳转到.L2
        lw      a4,-20(s0) ;$a4 = a
        lw      a5,-24(s0) ;$a5 = b
        remw    a5,a4,a5 ;$a5 = a % b
        sext.w  a4,a5 ;$a4 = a % b
        lw      a5,-24(s0) ;$a5 = b
        mv      a1,a4 ;$a1 = a % b
        mv      a0,a5 ;$a0 = b
        call    gcd ;递归调用gcd
        mv      a5,a0 ;$a5 = gcd(b, a%b)
        j       .L3 ;跳转到.L3
.L2:
        lw      a5,-20(s0) ;$a5 = a
.L3:
        mv      a0,a5 ;$a0 = $a5
        ld      ra,24(sp) ;恢复$ra的值
        ld      s0,16(sp) ;恢复$s0的值
        addi    sp,sp,32 ;退栈到旧栈顶
        jr      ra ;调用返回
        .size   gcd, .-gcd
        .section        .rodata
        .align  3
.LC0:
        .string "%d\n"
        .text
        .align  1
        .globl  main
        .type   main, @function
main:
        addi    sp,sp,-32
        sd      ra,24(sp)
        sd      s0,16(sp)
        addi    s0,sp,32
        li      a5,12
        sw      a5,-24(s0)
        li      a5,18
        sw      a5,-20(s0)
        lw      a4,-20(s0)
        lw      a5,-24(s0)
        mv      a1,a4 ;$a1 = 18
        mv      a0,a5 ;$a0 = 12
        call    gcd
        mv      a5,a0
        mv      a1,a5 ;$a1 = gcd(12,18)
        lla     a0,.LC0 ;$a0 = "%s\n"
        call    printf@plt
        li      a5,0
        mv      a0,a5
        ld      ra,24(sp)
        ld      s0,16(sp)
        addi    sp,sp,32
        jr      ra
        .size   main, .-main
        .ident  "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
        .section        .note.GNU-stack,"",@progbits

作者:357

...全文
109 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

567

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧