RISC-V汇编代码分析

??273? 2022-05-17 21:25:51

1. 安装交叉编译环境

1.1 安装环境

sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev libusb-1.0-0-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev device-tree-compiler pkg-config libexpat-dev

1.2 安装RISC-V

git clone https://github.com/riscv/riscv-tools.git
cd riscv-tools
git submodule update --init --recursive
git clone https://github.com/riscv/riscv-gnu-toolchain
cd riscv-gnu-toolchain
 
git submodule update --init --recursive
su
./configure --prefix=/opt/riscv
make -j4
export PATH=/opt/riscv/bin:$PATH
cd ..
export RISCV=/path/to/install/riscv/toolchain
./build.sh
export PATH=/path/to/install/riscv/toolchain/bin:$PATH 

2. C代码

#include<stdio.h>
 
int func(int a){
    return a+14;
}
 
int main()
{
    int a = 12;
    printf("ans=%d",func(a));
    return 0;
}

2.1 将c代码汇编为汇编文件

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

2.2 汇编代码及分析

    .file    "test.c"
    .option pic
    .text
    .align    1
    .globl    func
    .type    func, @function
func:
    addi    sp,sp,-32               # sp为栈顶指针,sp-32,为函数分配空间
    sd    s0,24(sp)                 # s0为栈底指针,存储s0的值
    addi    s0,sp,32                # s0=sp+32,将s0指向栈底
    mv    a5,a0                     # 这两句保存a5的值
    sw    a5,-20(s0)                
    lw    a5,-20(s0)                # 将s0-20中的值存放到a5中
    addiw    a5,a5,14               # a5 = a5 + 14
    sext.w    a5,a5                 # sign-extend(符号拓展)
    mv    a0,a5                     # a0为函数返回值
    ld    s0,24(sp)                 # 恢复s0的值
    addi    sp,sp,32                # 恢复sp的值
    jr    ra                        # 无条件跳转到返回地址
    .size    func, .-func
    .section    .rodata
    .align    3
.LC0:
    .string    "ans=%d"             # 将字符串"ans=%d"放入内存
    .text
    .align    1
    .globl    main                  # 声明main为全局符号
    .type    main, @function
main:
    addi    sp,sp,-32               # sp为栈顶指针,sp-32,为函数分配空间
    sd    ra,24(sp)                 # ra存储返回地址,存储ra的值
    sd    s0,16(sp)                 # s0为栈底指针,存储s0的值
    addi    s0,sp,32                # s0 = sp + 32,将s0指向栈底
    li    a5,12                     # a5存储int型变量a,赋初值12
    sw    a5,-20(s0)                # 这两句保存a5的值
    lw    a5,-20(s0)
    mv    a0,a5                     # 将a5作为调用函数的参数
    call    func                    # 调用函数func
    mv    a5,a0                     # a0为函数func的返回值,存入a5
    mv    a1,a5
    lla    a0,.LC0                  # 加载.LC0的内容
    call    printf@plt              # 调用printf函数
    li    a5,0                      # main函数返回值为0,先让a5储存0
    mv    a0,a5                     # 然后将a5的值存在a0,作为main函数的返回值
    ld    ra,24(sp)                 # 恢复ra的值
    ld    s0,16(sp)                 # 恢复s0的值
    addi    sp,sp,32                # 恢复sp的值
    jr    ra                        # 无条件跳转到返回地址
    .size    main, .-main
    .ident    "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
    .section    .note.GNU-stack,"",@progbits

250

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

567

社区成员

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

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