这一期我们重新回到RISC-V的内容说明。

基本指令集
指令格式
在基本ISA中,有四种核心指令格式(R/I/S/U),如图 2.2所示。所有的指令都是固定32位长度的,并且在存储器中必须在4字节边界对齐。当发生一个条件分支或者无条件转移而且目标地址不是对齐到4字节时, 将会产生一个指令地址不对齐的异常。 如果条件分支没有发生(not taken),那么将不会产生一个取指不对齐异常。

基于立即数处理,还有额外两种指令格式变种(SB/UJ)

指令集功能分类
RV32I指令集按照指令功能可以分为5类。
- Integer Computational Instructions【整数计算指令,下称使用中文】
- Loads and Store Instructions【访存指令】
- Control Transfer Instructions【控制转移指令】
- Memory Ordering Instructions【内存顺序指令】
- Environment Call and Breakpoints【环境调用和断点】
这5类指令包括了一种或多种指令格式,下面分类给出各部分指令的简要功能介绍。
指令集总览
RV32I 基本指令集有47条指令,如下图:

是不是很多,这里给大伙提供一个网站,可以在线直接查看 Risc-V的指令功能 —— 跳转链接

指令详细说明
1. 高位立即数与地址构造
指令 |
格式 |
功能描述 |
示例 |
LUI |
lui rd, imm |
将 20 位立即数 imm 左移 12 位,写入 rd 的高位,低位补 0。 |
lui x5, 0x12345 → x5 = 0x12345000 |
AUIPC |
auipc rd, imm |
将 PC 当前值 + (imm << 12),结果写入 rd,用于构造全局地址或远跳转。 |
auipc x6 |
LUI 代码演示
.text
.global _start
_start:
lui x5, 0x12345
addi x5, x5, 0x678
stop:
j stop
.end

2. 控制转移指令
无条件跳转
指令 |
格式 |
功能描述 |
示例 |
JAL |
jal rd, offset |
跳转到 PC + offset,并将返回地址 PC+4 存入 rd(通常 rd=x1)。 |
jal x1, func → 调用函数 func |
JALR |
jalr rd, rs1, imm |
跳转到 rs1 + imm(地址最低位强制为 0),返回地址 PC+4 存入 rd。 |
jalr x0, x1, 0 → 跳转到 x1 并返回 |
JALR代码演示
.text
.global _start
_start:
li x6, 1
li x7, 2
jal x5, sum
stop:
j stop
sum:
add x6, x6, x7
jalr x0, 0(x5)
.end

条件分支
指令 |
格式 |
功能描述 |
示例 |
BEQ |
beq rs1, rs2, offset |
若 rs1 == rs2,跳转到 PC + offset。 |
beq x5, x6, loop → 相等则循环 |
BNE |
bne rs1, rs2, offset |
若 rs1 != rs2,跳转。 |
bne x5, x0, exit → 非零则退出 |
BLT |
blt rs1, rs2, offset |
若 rs1 < rs2(有符号比较),跳转。 |
blt x5, x6, less |
BGE |
bge rs1, rs2, offset |
若 rs1 >= rs2(有符号比较),跳转。 |
bge x5, x6, greater_eq |
BLTU |
bltu rs1, rs2, offset |
若 rs1 < rs2(无符号比较),跳转。 |
bltu x5, x6, uless |
BGEU |
bgeu rs1, rs2, offset |
若 rs1 >= rs2(无符号比较),跳转。 |
bgeu x5, x6, ugreater_eq |
BNE代码演示
.text
.global _start
_start:
li x5, 0
li x6, 5
loop:
addi x5, x5, 1
bne x5, x6, loop
stop:
j stop
.end
在这里插入图片描述
3. 内存访问指令
加载指令
指令 |
格式 |
功能描述 |
示例 |
LB |
lb rd, offset(rs1) |
从 rs1 + offset 加载字节(符号扩展后写入 rd)。 |
lb x5, 4(x6) → 加载字节到 x5 |
LH |
lh rd, offset(rs1) |
加载半字(符号扩展)。 |
lh x5, -8(x6) |
LW |
lw rd, offset(rs1) |
加载字(32 位数据)。 |
lw x5, 0(x6) |
LBU |
lbu rd, offset(rs1) |
加载无符号字节(高位补 0)。 |
lbu x5, 3(x6) |
LHU |
lhu rd, offset(rs1) |
加载无符号半字(高位补 0)。 |
lhu x5, 2(x6) |
存储指令
指令 |
格式 |
功能描述 |
示例 |
SB |
sb rs2, offset(rs1) |
将 rs2 的低 8 位存储到 rs1 + offset。 |
sb x5, 10(x6) → 存储字节 |
SH |
sh rs2, offset(rs1) |
存储低 16 位。 |
sh x5, -4(x6) |
SW |
sw rs2, offset(rs1) |
存储 32 位。 |
sw x5, 0(x6) |
4. 整数运算指令
立即数运算
指令 |
格式 |
功能描述 |
示例 |
ADDI |
addi rd, rs1, imm |
rs1 + 符号扩展的12位立即数,结果写入 rd。 |
addi x5, x6, -5 → x5 = x6 -5 |
SLTI |
slti rd, rs1, imm |
若 rs1 < imm(有符号比较),则 rd=1,否则 rd=0。 |
slti x5, x6, 10 → 检查是否小于 10 |
SLTIU |
sltiu rd, rs1, imm |
无符号比较 rs1 < imm,结果写入 rd。 |
sltiu x5, x6, 0xFFF |
XORI |
xori rd, rs1, imm |
rs1 ^ 符号扩展的立即数。 |
xori x5, x6, 0xFFFF → 按位取反 |
ORI |
ori rd, rs1, imm |
rs1 |
符号扩展的立即数。 |
ANDI |
andi rd, rs1, imm |
rs1 & 符号扩展的立即数。 |
andi x5, x6, 0xFF → 取低8位 |
ADDI代码演示
.text
.global _start
_start:
li x6, 2
addi x5, x6, 1
stop:
j stop
.end

移位运算
指令 |
格式 |
功能描述 |
示例 |
SLLI |
slli rd, rs1, shamt |
逻辑左移 rs1,移位数为 shamt(0-31),结果写入 rd。 |
slli x5, x6, 2 → x5 = x6 << 2 |
SRLI |
srli rd, rs1, shamt |
逻辑右移(高位补 0)。 |
srli x5, x6, 3 |
SRAI |
srai rd, rs1, shamt |
算术右移(高位补符号位)。 |
srai x5, x6, 4 |
SLLI代码演示
.text
.global _start
_start:
li x6, 1
slli x5, x6, 3
stop:
j stop
.end

寄存器-寄存器运算
指令 |
格式 |
功能描述 |
示例 |
ADD |
add rd, rs1, rs2 |
rs1 + rs2,结果写入 rd。 |
add x5, x6, x7 |
SUB |
sub rd, rs1, rs2 |
rs1 - rs2。 |
sub x5, x6, x7 |
SLL |
sll rd, rs1, rs2 |
逻辑左移 rs1,移位数为 rs2 的低 5 位。 |
sll x5, x6, x7 |
SLT |
slt rd, rs1, rs2 |
若 rs1 < rs2 |
(有符号比较),则 rd=1,否则 rd=0。 |
SLTU |
sltu rd, rs1, rs2 |
无符号比较 rs1 < rs2,结果写入 rd。 |
sltu x5, x6, x7 |
XOR |
xor rd, rs1, rs2 |
按位异或。 |
xor x5, x6, x7 → x5 = x6 ^ x7 |
SRL |
srl rd, rs1, rs2 |
逻辑右移(高位补 0)。 |
srl x5, x6, x7 |
SRA |
sra rd, rs1, rs2 |
算术右移(高位补符号位)。 |
sra x5, x6, x7 |
OR |
or rd, rs1, rs2 |
按位或。 |
or x5, x6, x7 → x5 = x6 |
AND |
and rd, rs1, rs2 |
按位与。 |
and x5, x6, x7 → x5 = x6 & x7 |
ADD代码演示
.text
.global _start
_start:
li x6, 1
li x7, 2
add x5, x6, x7
stop:
j stop
.end

5. 系统与同步指令
指令 |
格式 |
功能描述 |
示例 |
FENCE |
fence 内存屏障,确保其前后的内存访问顺序。 |
fence → 保证访存顺序 |
|
ECALL |
ecall 触发环境调用(如系统调用或切换到更高权限模式)。 |
ecall → 执行系统调用 |
|
EBREAK |
ebreak 触发调试断点,通常用于调试器介入。 |
ebreak → 进入调试模式 |
|
结语
这一期讲了RV32I的所有指令集,下一期我们来看看指令在CPU中是经过了那些过程才最终实现出来的。
感谢大伙观看,别忘了三连支持一下
大家也可以关注一下我的其它专栏,同样精彩喔~
下期见咯~
