RISC-V 常用汇编指令

RISCV 常用汇编指令


相关寄存器

寄存器ABI 名用途Saver
x0zero读取时总为 0, 写入时不起任何效果-
x1ra存放函数返回地址 (return address)Caller
x2sp存放栈指针 (stack pointer)Callee
x3gpglobal pointer-
x4tpthread point-
x5 - x7t0 - t2临时 (temporaries) 寄存器,Callee 可能会使用这些寄存器,所以 Callee 不保证这些寄存器中的值在函数调用过程中保持不变,这意味着对于 Caller 来说,如果需要的话,Caller 需要自己在调用 Callee 之前保存临时寄存器中的值。Caller
x28 - x31t3 - t6临时寄存器,同上Caller
x8 - x9s0/fp - s1保存 (saved) 寄存器,Callee 需要保证这些寄存器的值在函数返回后仍然维持函数调用之前的原值,所以一旦 Callee 在自己的函数中会用到这些寄存器则需要在栈中备份并在退出函数时进行恢复。Callee
x18 - x27s2 - s11保存寄存器,同上Callee
x10 - x11a0 - a1参数 (argument) 寄存器,用于在函数调用过程中保存第一个和第二个参数,以及在函数返回时传递返回值。Caller
x12 - x17a2 - a7参数 (argument) 寄存器,如果函数调用时需要传递更多的参数,则可以用这些寄存器,但注意用于传递参数的寄存器最多只有 8 个 (a0 ~ a7) ,如果还有更多的参数则要利用栈。Caller

Caller :调用者,Callee : 被调用函数【这里可以视为在 Caller (函数)中调用 Callee (函数)】
Caller 维护的寄存器,在运行被调函数前不会被保存,函数返回时这些寄存器可能会被改变,所以在调用前由 Caller 保存维护。
Callee 维护的寄存器,在运行被调函数前会被保存,函数返回后这些寄存器与运行被调函数前相同。


算术运算指令

指令语法描述例子
addadd rd,rs1,rs2(rs1 + rs2) 的值保存到 rdadd x5,x6,x7
subsub rd,rs1,rs2(rs1 - rs2)的值保存到 rdsub x5,x6,x7
luilui rd,immrd = (imm << 12) (20位的立即数左移12位)lui x5,0x12345
auipcauipc rd,imm(20bit)rd = (imm << 12) + pc (相对 pc 的偏移值)auipc x5,0x1234
伪指令语法等价语句描述例子
negneg rd,rssub rd,x0,rsrd = ~rs (取反)neg x5,x6
mvmov rd,rsaddi rd,rs,0rd = rsmov x5,x6
nopnopaddi x0,x0,0空指令nop
lili rd,immrd = imm (32bit) 直接加载32位立即数li x5,0x12345678
lala rd,addrrd = addr 加载地址到寄存器la x5,0x12345

逻辑运算指令

指令语法描述例子
andand rd,rs1,rs2rd = (rs1 & rs2)and x5,x6,x7
oror rd,rs1,rs2rd = (rs1 | rs2)or x5,x6,x7
xorxor rd,rs1,rs2rd = (rs ^ rs2)xor x5,x6,x7
andiandi rd,rs,immrd = (rs & imm)andi x5,x6,10
oriori rd,rs,immrd = (rs | imm)ori x5,x6,20
xorixori rd,rs,immrd = (rs ^ imm)xori x5,x6,10
伪指令语法等价语句描述例子
notnot rd,rsxori rd,rs,-1按位取反not x5,x6

移位运算指令

逻辑移位 补零

指令语法描述例子
sllsll rd,rs1,rs2(rs1 << rs2)sll x5,x6,x7
srlsrl rd,rs1,rs2(rs1 >> rs2)srl x5,x6,x7
sllisll rd,rs1,imm(rs1 << imm)slli x5,x6,10
srlisrl rd,rs1,immrd = (rs1 >> imm)srli x5,x6,20

算术移位(只有右移,补符号位)

指令语法描述例子
srasra rd,rs1,rs2rd = (rs1 << rs2)sra x5,x6,x7
sraisrai rd,rs1,immrd = (rs1 >> imm)srl x5,x6,20

内存读写指令

imm 为12bit有符号整数

读指令

指令语法描述例子
lblb rd,imm(rs)从内存 imm+rs 处读取8bit数据(符号拓展)到 rd 中(符号拓展)lb x5,40(x6)
lbulbu rd,imm(rs)从内存 imm+rs 处读取8bit无符号整数(0扩展)到 rd 中(0扩展)lbu x5,40(x6)
lhlh rd,imm(rs)从内存 imm+rs 处读取16bit数据(符号拓展)到 rd 中(符号拓展)lh x5,40(x6)
lhulhu rd,imm(rs)从内存 imm+rs 处读取16bit无符号整数(0扩展)到 rd 中(0扩展)lhu x5,40(x6)
lwlw rd,imm(rs)从内存 imm+rs 处读取32bit数据到 rd 中lw x5,40(x6)

写指令

指令语法描述例子
sbsb rs2,imm(rs1)将rs2中的8bit数据写入内存 imm+rs1 处sb x5,40(x6)
shsh rs2,imm(rs1)将rs2中的16bit数据写入内存 imm+rs1 处sb x5,40(x6)
swsw rs2,imm(rs1)将rs2中的32bit数据写入内存 imm+rs1 处sb x5,40(x6)

条件分支指令

指令语法描述例子
beqbeq rs1,rs2,imm如果rs1 == rs2,跳转到 imm 地址处beq x5,x6,100
bnebne rs1,rs2,imm如果rs1 != rs2,跳转到 imm 地址处bne x5,x6,100
bltblt rs1,rs2,imm如果rs1 < rs2(有符号方式),跳转blt x5,x6,100
bltubltu rs1,rs2,imm如果rs1 < rs2(无符号方式),跳转bltu x5,x6,100
bgeblt rs1,rs2,imm如果rs1 >= rs2(有符号方式),跳转bge x5,x6,100
bgeubltu rs1,rs2,imm如果rs1 >= rs2(无符号方式),跳转bgeu x5,x6,100

跳转的目标地址计算方法(对齐):(imm<<1)+pc 具体编程时由标号给出

伪指令语法等价语句例子
bleble rs1,rs2,offset如果 rs1 <= rs2,跳转到 offset 地址处ble x5,x6,100
bleubleu rs1,rs2,offset如果 rs1 <= rs2(无符号),跳转到 offset 地址处bequ x5,x6,100
bgtbgt rs1,rs2,offset如果 rs1 >= rs2,跳转到 offset 地址处bgt x5,x6,100
bgtubgtu rs1,rs2,offset如果 rs1 >= rs2(无符号),跳转到 offset 地址处bgtu x5,x6,100
beqzbeqz rs1,offset如果 rs1 == 0,跳转到 offset 地址处beqz x5,x6,100
bnezbnez rs1,offset如果 rs1 != 0,跳转到 offset 地址处bnez x5,x6,100
bltzbltz rs1,offset如果 rs1 < 0,跳转到 offset 地址处bltz x5,x6,100
blezblez rs1,offset如果 rs1 <= 0,跳转到 offset 地址处blez x5,x6,100
bgtzbgtz rs1,offset如果 rs1 > 0,跳转到 offset 地址处bgtz x5,x6,100
bgezbgez rs1,offset如果 rs1 >= 0,跳转到 offset 地址处bgez x5,x6,100

无条件跳转指令

指令语法描述例子
jaljal rd,label指令的下一条指令地址存入rd,跳转到label (20bit)jal x1,label
jalrjalr rd,imm(rs)12bit的imm符号拓展,(rs+imm)低位置0存到rd,跳转jarl x1,0(x5)
伪指令语法等价语句描述
jj offsetjal x0,offset [不会保存跳转前的地址]j label
jrjr rsjalr x0,0(rs) [不会保存跳转前的地址]jr x5

函数调用

伪指令语法等价语句描述例子
jaljal offsetjal x1,offset保存返回地址到x1,跳转到 offsetjal label
jalrjalr rsjalr x1,0(rs)保存返回地址到x1,跳转到rs寄存器保存的地址jalr label
callcall offsetauipc x1,offset[31:12]+offset[11];jalr x1,ofsset[11:0] (x1)call fun
retretjalr x0,0(x1)返回ret

参考

### RISC-V 架构汇编语言入门 #### 什么是RISC-V? RISC-V是一种基于精简指令集计算(RISC)原则的开源指令集架构(ISA)[^1]。这种开放标准允许任何人设计、制造和销售RISC-V芯片和软件而不必支付专利费用。 #### 基础概念 在深入探讨具体的汇编语法前,理解一些基础的概念非常重要: - **寄存器**:RISC-V拥有32个通用目的寄存器,每个都是64位宽,在RV64I版本中;对于RV32I,则是32位宽。这些寄存器用于存储数据并参与运算操作。 - **内存模型**:采用Load/Store架构意味着只有特定类型的加载(load)和储存(store)指令可以访问内存地址中的值[^2]。 #### 指令格式 每条RISC-V指令都有固定的长度——通常是32比特,并由以下几个部分组成: - opcode (操作码): 定义要执行的操作类型 - rs1, rs2 (源寄存器): 提供输入数值给算术逻辑单元(ALU) - rd (目标寄存器): 存储ALU的结果 - imm (立即数): 直接编码于指令内的常量值 #### 示例代码 下面是一个简单的例子,展示了如何用RISC-V汇编语言编写一段程序来加两个数字并将结果保存到另一个位置: ```assembly .text # 开始定义可执行代码段 main: # 主函数标签 li t0, 5 # 将整数5加载至临时寄存器t0 li t1, 7 # 同样地初始化第二个变量为7 add t2, t0, t1 # 把t0+t1的结果放入t2 ebreak # 结束调试模式下的运行 ``` 这段代码首先设置了`.text`节表示接下来的内容将是机器能够执行的指令序列。接着通过`li`(load immediate)命令分别向两个不同的暂存器`t0`, `t1`赋初值5和7。最后利用`add`指令完成两者的相加以获得最终求和后的值,并将其放置在一个新的暂存器`t2`里。 #### 控制流语句 除了基本的数据处理外,控制结构也是任何编程环境中不可或缺的一部分。这里简单介绍几种常见的条件分支以及循环机制是如何在RISC-V汇编中实现的: ##### 条件跳转 当需要根据某个表达式的真假决定是否转向其他地方继续执行时,就可以使用如下形式之一来进行判断: - beq rs1,rs2,label —— 如果rs1等于rs2则跳转到label处; - bne rs1,rs2,label —— 若不等则转移; - blt/bge ... etc. 例如: ```assembly beq zero, ra, exit # 当ra==0时跳转到exit标记的位置 ``` ##### 循环 为了重复某些动作直到满足一定条件为止,可以通过组合上述提到过的比较与跳跃指令达成效果。比如最常用的while-do风格伪代码转换成实际汇编的样子可能是这样的: ```assembly loop_start: sltiu t0, a0, 1 # 设置标志位(t0),如果a0<1成立就置true beqz t0, loop_end # 如果上面设置失败即跳出循环体 # (此处省略具体业务逻辑) j loop_start # 返回顶部重新评估终止条件 loop_end: ``` 以上就是关于RISC-V汇编语言的一些基础知识概述及其应用实例说明。希望这能帮助读者建立起对该主题初步的认识框架。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值