RISC-V 常用汇编指令集

RISC-V 常用汇编指令集

一、 通用寄存器介绍

寄 存 器 ABI名 用途 Saver
x0 zero 读取时总为 0, 写入时不起任何效果 (只有读RO 权限) -
x1 ra 存放函数返回地址 (return address) Caller
x2 sp 存放栈指针 (stack pointer) Callee
x3 gp global pointer -
x4 tp thread point -
x5 - x7 t0 - t2 临时 (temporaries) 寄存器,Callee 可能会使用这些寄存器,所以 Callee 不保证这些寄存器中的值在函数调用过程中保持不变,这意味着对于 Caller 来说,如果需要的话,Caller 需要自己在调用 Callee 之前保存临时寄存器中的值。 Caller
x8 - x9 s0/fp - s1 保存 (saved) 寄存器,Callee 需要保证这些寄存器的值在函数返回后仍然维持函数调用之前的原值,所以一旦 Callee 在自己的函数中会用到这些寄存器则需要在栈中备份并在退出函数时进行恢复 Callee
x10 - x11 a0 - a1 参数 (argument) 寄存器,用于在函数调用过程中保存第一个和第二个参数,以及在函数返回时传递返回值。 Caller
x12 - x17 a2 - a7 参数 (argument) 寄存器,如果函数调用时需要传递更多的参数,则可以用这些寄存器,但注意用于传递参数的寄存器最多只有 8 个 (a0 ~ a7) ,如果还有更多的参数则要利用栈。 Caller
x18 - x27 s2 - s11 保存 (saved) 寄存器,Callee 需要保证这些寄存器的值在函数返回后仍然维持函数调用之前的原值,所以一旦 Callee 在自己的函数中会用到这些寄存器则需要在栈中备份并在退出函数时进行恢复。 Callee
x28 - x31 t3 - t6 临时 (temporaries) 寄存器,Callee 可能会使用这些寄存器,所以 Callee 不保证这些寄存器中的值在函数调用过程中保持不变,这意味着对于 Caller 来说,如果需要的话,Caller 需要自己在调用 Callee 之前保存临时寄存器中的值。 Caller

Caller :调用者

Callee : 被调用函数

static void Caller (void)
{
    Callee ();
}

  
  
    
    
    
    
  • 1
  • 2
  • 3
  • 4

二、算术运算指令

指令 语法 描述 例子
add add rd,rs1,rs2 rd = rs1 + rs2 add x5,x6,x7
addi addi a0, a0, 4 a0 = a0 + 4, 加立即数,并且检查溢出 addi a0, a0, 4
sub sub rd,rs1,rs2 (rs1 - rs2)的值保存到 rd sub x5,x6,x7
lui lui rd,imm rd = (imm << 12) (20位的立即数左移12位) lui x5,0x12345
auipc auipc rd,imm(20bit) rd = (imm << 12) + pc (相对 pc 的偏移值) auipc x5,0x1234

三、逻辑运算

指令 语法 描述 例子
and 与运算 and rd,rs1,rs2 rd = (rs1 & rs2) and x5,x6,x7
or 或运算 or rd,rs1,rs2 rd = (rs1 rs2)
xor 异或运算 xor rd,rs1,rs2 rd = (rs ^ rs2) xor x5,x6,x7
andi 与立即数 andi rd,rs,imm rd = (rs & imm) andi x5,x6,10
ori 或立即数 ori rd,rs,imm rd = (rs imm)
xori 异或立即数 xori rd,rs,imm rd = (rs ^ imm) xori x5,x6,10

立即数可以理解成C 语言里的常数

四、伪指令

伪指令 语法 等价语句 描述 例子
neg neg rd,rs sub rd,x0,rs rd = ~rs (取反) neg x5,x6
mv mov rd,rs addi rd,rs,0 rd = rs mov x5,x6
nop nop addi x0,x0,0 空指令 nop
li li rd,imm - - rd = imm (32bit) 直接加载32位立即数 li x5,0x12345678
la la rd,addr - - rd = addr 加载地址到寄存器 la x5,0x12345
not not rd,rs xori rd,rs,-1 按位取反 not x5,x6

五、 移位运算指令

5.1、逻辑移位,补零

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

5.2、 0x01 << 3 (0000 0001) --> (0000 1000) 0x08 低 三位补 0

5.3、算术移位

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

六、 内存读写指令

注释: imm 为12 bits 有符号整数(立即数)

6.1、读指令

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

6.2、 写指令

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

七、条件分支指令

7.1、条件指令

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

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

7.2、伪指令

伪指令 语法 描述 例子
ble ble rs1,rs2,offset 如果 rs1 <= rs2,跳转到 offset 地址处 ble x5,x6,100
bleu bleu rs1,rs2,offset 如果 rs1 <= rs2(无符号),跳转到 offset 地址处 bequ x5,x6,100
bgt bgt rs1,rs2,offset 如果 rs1 >= rs2,跳转到 offset 地址处 bgt x5,x6,100
bgtu bgtu rs1,rs2,offset 如果 rs1 >= rs2(无符号),跳转到 offset 地址处 bgtu x5,x6,100
beqz beqz rs1,offset 如果 rs1 == 0,跳转到 offset 地址处 beqz x5,x6,100
bnez bnez rs1,offset 如果 rs1 != 0,跳转到 offset 地址处 bnez x5,x6,100
bltz bltz rs1,offset 如果 rs1 < 0,跳转到 offset 地址处 bltz x5,x6,100
blez blez rs1,offset 如果 rs1 <= 0,跳转到 offset 地址处 blez x5,x6,100
bgtz bgtz rs1,offset 如果 rs1 > 0,跳转到 offset 地址处 bgtz x5,x6,100
bgez bgez rs1,offset 如果 rs1 >= 0,跳转到 offset 地址处 bgez x5,x6,100

八、无条件跳转指令

8.1、无条件跳转指令

指令 语法 描述 例子
jal jal rd,label 指令的下一条指令地址存入rd,跳转到label (20bit) jal x1,label
jalr jalr rd,imm(rs) 12bit的imm符号拓展,(rs+imm)低位置0存到rd,跳转 jarl x1,0(x5)

8.2 伪指令

指令 语法 描述 例子
j j offset jal x0,offset [不会保存跳转前的地址] j label
jr jr rs jalr x0,0(rs) [不会保存跳转前的地址] jr x5

九、函数调用

9.1、伪指令

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

能举一个risc-v指令集中的sext.w指令的范例吗?
可以,sext.w指令的作用是将一个16位的有符号数扩展为32位的有符号数,例如:

lw t0, 0(s0) # 从地址s0+0处读取一个16位的有符号数 sext.w t1, t0 # 将t0中的16位有符号数扩展为32位有符号数,并存储到t1中

注意:以上回答仅供参考,具体实现方式可能因处理器架构和编译器而异

你可能感兴趣的:(risc-v,汇编)