算术运算指令(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)
  • 负数补码是反码的二进制值加一只是求法,并不是定义