算术运算指令(Arithmetic Instructions)
ADD
- 语法:ADD RD, RS1, RS2
- 示例:add x5, x6, x7(x5 = x6 + x7)
- 编码格式:R-type
- opcode(7):0110011(OP)
- funct3取值000;funct7取值0000000
- rs1(5):第一个 operand(source register 1)
- rs2(5): 第二个 operand(source register 2)
- rd(5):destination register 用于存放求和的结果
SUB(Substract)
- 语法:SUB RD, RS1, RS2
- 示例:sub x5, x6, x7(x5 = x6 - x7)
- 编码格式:R-type
ADDI
- 语法:ADDI RD, RS1, IMM
- 示例:addi x5, x6, -5(x5 = x6 + -5)
- 编码格式:I-type
- opcode(7):0b0010011(OP-IMM)
- funct3(3):和 opcode 一起决定最终的指令类型
- rs1(5):第一个 operand(source register 1)
- rd(5):存放求和结果
- imm(12):immediate,立即数,代替了 R-type 的第三个寄存器和 funct7
- 在参与算术运算前该 immediate 会被“符号扩展”为一个 32 位的数(重要)
- 这个立即数可以表达的范围为-2^11,+22^11,即 -2048, -2047。
- RISC-V 中并没有 SUBI 指令
LUI(Load Upper Immediate)
- 语法:LUI RD, IMM
- 示例:lui x5, 0x12345(
x5 = 0x12345 << 12
) - 编码格式:U-type
- opcode(7):0b0110111(LUI)
- rd(5):存放结果
- imm(20):立即数
- LUI 指令会构造一个 32 bits 的立即数,这个立即数的高 20 位对应指令中的 imm,低 12 位清零,这个数作为结果存放在 rd 中
LI(Load Immediate)
- 语法:LI RD, IMM
- 示例:li x5, 0x12345678(x5 = 0x12345678)
- LI (Load Immediate)是一个伪指令(pseudo-instruction)
- 汇编器会根据 IMM 的实际情况自动生成正确的真实指令(instruction)
(把麻烦直接丢给汇编器)
AUIPC
- 语法:AUIPC RD, IMM
- 示例:auipc x5, 0x12345
- 编码格式:U-type
- 和 LUI 类似,AUIPC 也会构造一个 32 bits 的立即数,这个立即数的高 20 位对应指令中的 IMM,低 12 位清零。但和 LUI 不同的是,AUIPC 会先把这个立即数和 PC 值相加,将相加后的结果存放在 RD 中
LA(Load Address)
- 语法:LA RD, LABEL
- 示例:la x5, foo
- LA 是一个伪指令(pseudo-instruction)
- 具体编程时给出需要加载的 label,编译器会根据实际情况根据 auipc 和其他指令自动生成正确的指令序列
- 常用于加载一个函数或者变量的地址
基于算术指令搞的一些其他指令
伪指令 | 语法 | 等价指令 | 指令描述 | 例子 |
---|---|---|---|---|
NEG | NEG RD, RS | SUB RD, x0, RS | 将 RS 中的值取反并将结果存放在 RD 中 | neg x5, x6 |
MV | MV RD, RS | ADDI RD, RS, 0 | 将 RS 中的值拷贝到 RD 中 | mv x5, x6 |
NOP | NOP | ADDI x0, x0, 0 | 什么都不做 | nop |
知识扩展:二进制原码,反码,补码
- 原码:最高位为符号位,其他位存放这个数的二进制绝对值
- 反码:正数和原码相同;负数除了符号位以外的所有位反转,1变成0,0变成1(如 10010 => 11101)
- 补码:正数的原码,反码,补码都一样;负数补码是反码的二进制值加一(如:11101 => 11110)
- 负数补码是反码的二进制值加一只是求法,并不是定义