RISC-V 汇编指令笔记
本文主要作为RISC-V Instruction的一个梳理。
RISC-V Instruction 的格式通常为
Operation code + Destination register + First operand register + Second oprand register
如,add x1, x2, x0 对应的 opcode = add; rd = x1; rs1 = x2; rs2 = x0.
对于RISC-V,有32个寄存器,分别是:
RISC-V寄存器表
寄存器 | 调用名字 | 用途 | 存储者 |
x0 | zero | 常数0 | N.A. |
x1 | ra | 返回地址 | Caller |
x2 | sp | 栈指针 | Callee |
x3 | gp | 全局指针 | / |
x4 | tp | 线程指针 | / |
x5-x7 | t0-t2 | 临时存储 | Caller |
x8 | s0/fp | 保存用寄存器/帧指针(配合栈指针界定一个函数的栈) | Callee |
x9 | s1 | 保存用寄存器 | Callee |
x10-x11 | a0-a1 | 函数参数/返回值 | Caller |
x12-x17 | a2-a7 | 函数参数 | Caller |
x18-x27 | s2-s11 | 保存用寄存器 | Callee |
x28-x31 | t3-t6 | 临时存储 | Caller |
f0-f7 | ft0-ft7 | 浮点临时存储 | Caller |
f8-f9 | fs0-fs1 | 浮点保存用寄存器 | Callee |
f10-f11 | fa0-fa1 | 浮点函数参数/返回值 | Caller |
f12-f17 | fa2-fa7 | 浮点函数参数 | Caller |
f18-f27 | fs2-fs11 | 浮点保存用寄存器 | Callee |
f28-f31 | ft8-ft11 | 浮点临时存储 | Caller |
tips: callee:
是一个指针,指向拥有这个arguement对象的函数;
caller:保留着调用当前函数的函数的引用。
而RISC-V RV32标准指令集有以下几种框架:
- R-format for register-register arithmetic/logical operations
- I-format for register-immediate arith/logical operations and loads
- S-format for stores
- B-format for branches
- U-format for 20-bit upper immediate instructions
- J-format for jumps
- Others: Used for OS & Syncronization
R即Reg相关;I即立即数相关;S存储相关;B分支相关;U高位数相关(因为一条32位指令中无法表示高达32位的数据);J跳转相关。
tips: about arithmetic & logical operations.
- 逻辑右移(LSR)是将各位依次右移指定位数,然后在左侧补0,算术右移(ASR)是将各位依次右移指定位数,然后在左侧用原符号位补齐。
- 逻辑左移与算术左移操作相同。
- RISC-V采用小端格式(Little-Endian),即低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
R-Format
通常是xxx rd, rs1, rs2。
31 0
Funct7 | rs2 | rs1 | Funct3 | rd | opcode |
7 | 5 | 5 | 3 | 5 | 7 |
Opcode = 0110011
Funct7 + Funct3 + opcode defines what operation to perform.
|
Funct7 |
Funct3 |
opcode |
用途 |
ADD |
0000000 |
000 |
0110011 |
加法 |
SUB |
0100000 |
000 |
0110011 |
减法 |
SLL |
0000000 |
001 |
0110011 |
左移 |
SLT |
0000000 |
010 |
0110011 |
Set Less Than := rs1 < rs2 ? 1:0 |
SLTU |
0000000 |
011 |
0110011 |
SLT Unsigned |
XOR |
0000000 |
100 |
0110011 |
异或 |
SRL |
0000000 |
101 |
0110011 |
逻辑右移 |
SRA |
0100000 |
101 |
0110011 |
算术右移 |
OR |
0000000 |
110 |
0110011 |
或 |
AND |
0000000 |
111 |
0110011 |
与 |
相关伪指令:
mv rd, rs = addi rd, rs, x0
nop = addi r0, r0, x0
not rd, rs = xori rd, rs, 111111111111
Note: 因为某事突然发现RISC-V好像没有循环移位的指令(未查证),要实现循环移位估计要三条指令以上。
I-Format
Opcode 0010011
Immediate | rs1 | Funct3 | rd | opcode | |
12 | 5 | 3 | 5 | 7 |
Shift-by-immediate | rs1 | Funct3 | rd | opcode | |
0x00000 | 5 | 5 | 3 | 5 | 7 |
第一部分包括ADDI, SLTI, SLTIU, XORI, ORI, ANDI(立即数有12位)
和SLLI, SRLI, SRAI(立即数仅有5位)。
第二部分包括load instruction,格式同ADDI(12位的立即数)
Load Opcode 0000011
有LB(load byte) ,LH(load halfword=2 bytes), LW,LBU(load unsigned byte),LHU(load unsigned halfword)
S-Format
Opcode 0100011
imm[11:5] | rs2 | rs1 | Funct3 | imm[4:0] | opcode |
7 | 5 | 5 | 3 | 5 | 7 |
包括SB,SW,SH
B-Format
Opcode 1100011
imm[12] | imm[10:5] | rs2 | rs1 | Funct3 | imm[4:1] | imm[11] | opcode |
1 | 6 | 5 | 5 | 3 | 4 | 1 | 7 |
可以表示-4096~4094的范围
Note:The 12 immediate bits encode even 13-bit signed byte offsets (lowest bit of offset is always zero, so no need to store it).
包括BEQ,BNE,BLT(branch less than: if [rs1]<[rs2], then branch) ,BGE(branch greater than or equal: if [rs1]>=[rs2], then branch) ,BLTU,BGEU。
相关伪指令:
beqz x1, label = beq x1, x0, label
bnez x1, label = bne x1, x0, label
U-Format
imm[31:12] | rd | opcode |
20 | 5 | 7 |
LUI – Load Upper Immediate lui rd, upper im(20-bit)
e.x. lui x10, 0x87654 # x10 = original value → 0x87654000
AUIPC – Add Upper Immediate to PC
e.x. auipc t0, 1 # t0 = original value → PC + 0x00001000
auipc t0, 0 # t0 = original value → PC
相关伪指令:
加载立即数
li rd, imm(32-bit) = lui rd, imm(20-bit)
addi rd, rd, imm(12-bit)
加载地址
la rd, label = auipc rd, imm(20-bit)
addi rd, rd, imm(12-bit)
J-Format
imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
1 | 10 | 1 | 8 | 5 | 7 |
jal x0, label Discard return address
jal ra, function_name Call Function within 218 (1 instruction = 22 bytes).
jr ra
# Call function at any 32-bit absolute address
lui x1,
jalr ra, x1,
# Jump PC-relative with 32-bit offset
auipc x1,
jalr x0, x1,
相关伪指令:
j label = jal x0, label
ret = jr ra = jalr x0, ra, 0
Acknowledgement
- UC Berkeley CS61C
- http://www.kvakil.me/venus/ 可以在线编译RISC-V的工具