RISC-V 常用指令与 C 语言对照
1. 算术运算指令
加法 (ADD/ADDI)
c
// C 语言
int a = 5;
int b = 3;
int c = a + b; // 寄存器相加
int d = a + 10; // 立即数相加
asm
# RISC-V 汇编
li a0, 5 # a0 = 5
li a1, 3 # a1 = 3
add a2, a0, a1 # a2 = a0 + a1 (寄存器相加)
addi a3, a0, 10 # a3 = a0 + 10 (立即数相加)
减法 (SUB)
c
// C 语言
int result = a - b;
asm
# RISC-V 汇编
sub a2, a0, a1 # a2 = a0 - a1
addi a2, a0, -5 # a2 = a0 - 5 (减立即数用 addi 负数)
乘法与除法 (MUL/DIV)
c
// C 语言
int product = a * b;
int quotient = a / b;
int remainder = a % b;
asm
# RISC-V 汇编 (需要 M 扩展)
mul a2, a0, a1 # a2 = a0 * a1
div a3, a0, a1 # a3 = a0 / a1 (有符号除法)
rem a4, a0, a1 # a4 = a0 % a1 (取余)
2. 逻辑运算指令
c
// C 语言
int and_result = a & b;
int or_result = a | b;
int xor_result = a ^ b;
asm
# RISC-V 汇编
and a2, a0, a1 # a2 = a0 & a1
or a3, a0, a1 # a3 = a0 | a1
xor a4, a0, a1 # a4 = a0 ^ a1
andi a5, a0, 0xFF # a5 = a0 & 0xFF (立即数)
ori a6, a0, 0x10 # a6 = a0 | 0x10
xori a7, a0, 0x01 # a7 = a0 ^ 0x01
3. 移位指令
c
// C 语言
int left = a << 2; // 左移
int right = a >> 2; // 算术右移 (有符号)
unsigned int uright = (unsigned)a >> 2; // 逻辑右移
asm
# RISC-V 汇编
slli a2, a0, 2 # a2 = a0 << 2 (左移立即数)
sll a2, a0, a1 # a2 = a0 << a1 (左移寄存器)
srai a3, a0, 2 # a3 = a0 >> 2 (算术右移,保留符号)
srli a4, a0, 2 # a4 = a0 >> 2 (逻辑右移,补0)
4. 数据加载与存储
c
// C 语言
int array[10];
int value = array[0]; // 加载
array[1] = value; // 存储
char c = *ptr; // 字节加载
asm
# RISC-V 汇编
# 假设 a0 = array 的基地址
lw a1, 0(a0) # 加载字 (32位): a1 = array[0]
lw a1, 4(a0) # a1 = array[1] (偏移4字节)
sw a1, 8(a0) # 存储字: array[2] = a1
lb a2, 0(a0) # 加载字节 (有符号扩展)
lbu a2, 0(a0) # 加载字节 (无符号扩展)
sb a2, 0(a0) # 存储字节
lh a3, 0(a0) # 加载半字 (16位,有符号)
lhu a3, 0(a0) # 加载半字 (无符号)
sh a3, 0(a0) # 存储半字
# RV64 额外指令
ld a4, 0(a0) # 加载双字 (64位)
sd a4, 0(a0) # 存储双字
5. 条件分支
c
// C 语言
if (a == b) {
// do something
}
if (a < b) {
// do something
}
asm
# RISC-V 汇编
# if (a == b)
beq a0, a1, equal_label # 相等则跳转
bne a0, a1, not_equal # 不等则跳转
# if (a < b) - 有符号比较
blt a0, a1, less_than # a0 < a1 则跳转
bge a0, a1, greater_equal # a0 >= a1 则跳转
# if (a < b) - 无符号比较
bltu a0, a1, less_unsigned
bgeu a0, a1, ge_unsigned
if-else 完整示例
c
// C 语言
if (x > 0) {
y = 1;
} else {
y = -1;
}
asm
# RISC-V 汇编
# x 在 a0, y 在 a1
blez a0, else_branch # if x <= 0, goto else
li a1, 1 # y = 1
j end_if # 跳过 else
else_branch:
li a1, -1 # y = -1
end_if:
6. 循环结构
for 循环
c
// C 语言
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
asm
# RISC-V 汇编
li a0, 0 # sum = 0
li t0, 0 # i = 0
li t1, 10 # 循环上限
loop:
bge t0, t1, done # if i >= 10, exit
add a0, a0, t0 # sum += i
addi t0, t0, 1 # i++
j loop # 继续循环
done:
while 循环
c
// C 语言
while (n > 0) {
n--;
}
asm
# RISC-V 汇编
# n 在 a0
while_loop:
blez a0, while_end # if n <= 0, exit
addi a0, a0, -1 # n--
j while_loop
while_end:
7. 函数调用
c
// C 语言
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 5);
}
asm
# RISC-V 汇编
# main 函数
main:
addi sp, sp, -16 # 分配栈空间
sw ra, 12(sp) # 保存返回地址
li a0, 3 # 第一个参数
li a1, 5 # 第二个参数
jal ra, add # 调用 add 函数
# 返回值在 a0
lw ra, 12(sp) # 恢复返回地址
addi sp, sp, 16 # 释放栈空间
ret # 返回
# add 函数
add:
add a0, a0, a1 # a0 = a + b (返回值)
ret # 等价于 jalr x0, ra, 0
递归函数示例 (阶乘)
c
// C 语言
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
asm
# RISC-V 汇编
factorial:
addi sp, sp, -16 # 分配栈空间
sw ra, 12(sp) # 保存返回地址
sw a0, 8(sp) # 保存 n
li t0, 1
ble a0, t0, base_case # if n <= 1, goto base_case
addi a0, a0, -1 # n - 1
jal ra, factorial # 递归调用
lw t0, 8(sp) # 恢复 n
mul a0, t0, a0 # n * factorial(n-1)
j fact_end
base_case:
li a0, 1 # return 1
fact_end:
lw ra, 12(sp) # 恢复返回地址
addi sp, sp, 16 # 释放栈空间
ret
8. 数组访问
c
// C 语言
int arr[5] = {1, 2, 3, 4, 5};
int value = arr[3]; // 读取 arr[3]
arr[2] = 100; // 写入 arr[2]
asm
# RISC-V 汇编
# 假设 a0 = arr 基地址
# 读取 arr[3]
li t0, 3 # 索引
slli t0, t0, 2 # t0 = 3 * 4 (int 是 4 字节)
add t1, a0, t0 # t1 = &arr[3]
lw a1, 0(t1) # a1 = arr[3]
# 或者直接用偏移
lw a1, 12(a0) # a1 = arr[3] (偏移 = 3 * 4)
# 写入 arr[2]
li t2, 100
sw t2, 8(a0) # arr[2] = 100
9. 比较与设置
c
// C 语言
int flag = (a < b); // 比较结果 0 或 1
asm
# RISC-V 汇编
slt a2, a0, a1 # a2 = (a0 < a1) ? 1 : 0 (有符号)
sltu a2, a0, a1 # 无符号比较
slti a2, a0, 10 # a2 = (a0 < 10) ? 1 : 0 (立即数)
10. 加载大立即数
c
// C 语言
int x = 0x12345678;
asm
# RISC-V 汇编
lui a0, 0x12345 # 加载高 20 位
addi a0, a0, 0x678 # 加低 12 位
# 或使用伪指令
li a0, 0x12345678 # 汇编器自动展开
寄存器使用约定总结
| 寄存器 | ABI 名称 | 用途 |
| x0 | zero | 恒为 0 |
| x1 | ra | 返回地址 |
| x2 | sp | 栈指针 |
| x10-x17 | a0-a7 | 函数参数/返回值 |
| x5-x7, x28-x31 | t0-t6 | 临时寄存器 |
| x8-x9, x18-x27 | s0-s11 | 保存寄存器 |