电子说
RV32I有32个通用寄存器,以及一个PC寄存器。其中有一个通过硬件设置的值恒为 0 的 x0 寄存器
注:RISC-V的32个寄存器x0~x31是用0~31这些数字来表示。
RISC-V有六种基本指令格式:
每个字段名称的含义:
funct7 | rs2 | rs1 | funct3 | rd | opcode |
---|---|---|---|---|---|
7位 | 5位 | 5位 | 3位 | 5位 | 7位 |
指令 | 示例 | 含义 |
---|---|---|
add | add a0, a1, a2 | a0 = a1 + a2 |
sub | sub a0, a1, a2 | a0 = a1 - a2 |
sll | sll a0, a1, a2 | a0 = a1 << a2 (低位补0) |
srl | srl a0, a1, a2 | a0 = a1 >> a2(高位补0) |
sra | sra a0, a1, a2 | a0 = a1 >> a2 (算术右移,高位补原来的符号位) |
slt | slt a0, a1, a2 | a1 < a2 ? 1 : 0 |
xor | xor a0, a1, a2 | a0 = a1 ^ a2 |
or | or a0, a1, a2 | a0 = a1 |
and | and a0, a1, a2 | a0 = a1 & a2 |
imm | rs1 | funct3 | rd | opcode |
---|---|---|---|---|
12位 | 5位 | 3位 | 5位 | 7位 |
指令 | 示例 | 含义 |
---|---|---|
addi | add | a0, a1, 0x50 |
slli | slli a0, a1, 5 | a0 = a1 << 5 (低位补0) |
srli | srli a0, a1, 5 | a0 = a1 >> 5 (高位补0) |
srai | sra a0, a1, 5 | a0 = a1 >> 5 (高位补原来的高位) |
slti | slti a0, a1, 0x50 | a1 < 0x50 ? 1 : 0 |
xori | xor a0, a1, 0x50 | a0 = a1 ^ 0x50 |
ori | ori a0, a1, 0x50 | a0 = a1 |
andi | andi a0, a1, 0x50 | a0 = a1 & 0x50 |
取值指令—Load
imm | rs1 | funct3 | rd | opcode |
---|---|---|---|---|
12位 | 5位 | 3位 | 5位 | 7位 |
lb x10, 0(x1) //将x1的值加上0,将这个值作为地址, 取出这个地址所对应的内存中的值, 将这个值赋值给x10(取出的是8位数值)
lh x10, 0(x1) //从内存中取出16位数值
lw x10, 0(x1) //从内存中取出32位数值
lbu x10, 0(x1) //从内存中取出8位无符号数值
lhu x10, 0(x1) //从内存中取出16位无符号数值
imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
---|---|---|---|---|---|
7位 | 5位 | 5位 | 3位 | 5位 | 7位 |
sb x10, 0(x1) //x1的值加上0,将这个值作为地址, 将x10的值存储到上述地址所对应的内存中去 (只会将x10的值的低8位写入)
sh x10, 0(x1) //只会将x10的值的低16位写入
sw x10, 0(x1) //只会将x10的值的低32位写入
imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1] | imm[11] | opcode |
---|---|---|---|---|---|---|---|
1位 | 6位 | 5位 | 5位 | 3位 | 4位 | 1位 | 7位 |
指令 | 示例 | 含义 | 备注 |
---|---|---|---|
beq | beq a1, a2, Lable | if(a1 == a2){goto Label;} | Lable是任意自定义的标签 |
bne | bne a1, a2, Lable | if(a1 != a2){goto Label;} | |
blt | blt a1, a2, Lable | if(a1 < a2){goto Label;} | |
bgt | bgt a1, a2, 100 | if(a1 > a2){goto Label;} | 100与Label对应着相同的指令, 实际上在运行时Label会变成pc+xxx |
bge | bge a1, a2, 100 | if(a1 <= a2){goto Label;} | |
ble | ble a1, a2, 100 | if(a1 >= a2){goto Lable;} |
imm[31:12] | rd | opcode |
---|---|---|
10位 | 5位 | 7位 |
lui x10, 0x65432 //得到立即数的高20位,低位补0,立即数范围为:0x00~0xFFFFF
imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
---|---|---|---|---|---|
1位 | 10位 | 1位 | 8位 | 5位 | 7位 |
jal ra, symbol // 跳转到Symbol中去, 并把ra设置成返回地址 Symbol 可以是自定义的Label ,也可以是某个函数名
jal ra, 100 // 跳转到pc + 100 * 2的地方中去, 并把ra设置成返回地址 pc相对寻址,对应的是位置无关代码(PIC)
jalr ra, 40(x10) //跳转到x10+40 的地方中去, 并把ra设置成返回地址x10+40必须是绝对地址,指向内存中某个确定的地方(往往是函数的开头),非PIC
例题
对于符号表示为:
add x9, x20, x21
的RISC-V指令,首先以十进制表示,然后用二进制表示
答案
有上面的介绍可知add指令的字段如下:
直接用十进制表示如下:
funct7 | rs2 | rs1 | funct3 | rd | opcode |
---|---|---|---|---|---|
0 | 21 | 20 | 0 | 9 | 51 |
一条指令的每一段称为一个宇段。
第一、第四和第六个字段(0、0 和 51)组合起来告诉RISC-V计算机该指令执行加法操作。
第二个字段给出了作为加法运算的第二个源操作数的寄存器编号(21 表示 x21),
第三个字段给出了加法运算的另一个源操作数(20代表×20)。
第五个字段存放要接收总和的奇存器编号(9代表x9)。
因此,该指令将寄存器 x20 和寄存器 x21 相加并将和存放在寄存器x9中。
用二进制表示如下:
funct7 | rs2 | rs1 | funct3 | rd | opcode |
---|---|---|---|---|---|
0000000 | 10101 | 10100 | 000 | 01001 | 0110011 |
总上,add x9, x20, x21
的RISC-V指令对应的机器码为: 00000001010110100000010010110011
例题
有以下几条汇编:
ld x9, 240(x10)
add x9, x21, x9
addi x9, x9, 1
sd x9, 240(x10)
将它们翻译为对应的机器码
答案
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !