RISC-V ASM

RISC-V ASM

主要是RV32I的asm

operation

instruction(指令):直接对应二进制机器指令的字符串

pseudo-instruction(伪指令):一条伪指令指示汇编器产生多条实际的指令(instruction)

direction(指示/伪操作):通过类似指令的形 式(以“.”开头),通知汇编器如何控制代码的产生等,不对应具体的指令,比如.text是告诉汇编器放到.text节里,

macro:采用 .macro/.endm 自定义的宏

指令编码格式

image-20230710232853854

funct3和funct7和opcode决定指令类型(加减乘除等等)

funct3:funct代表function 3代表占了3bits

  • R-type:(Register),每条指令中有三个 fields,用于指定3个寄存器参数
  • I-type: (Immediate),每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits)。
  • S-type: (Store),每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits,但 fields 的组织方式不同于 I-type)
  • B-type: (Branch),每条指令除了带有两个寄存器参数外,还带有一个立即数参数(宽度为 12 bits,但取值为 2 的倍数)。
  • U-type: (Upper),每条指令含有一个寄存器参数再加上一个立即数参数(宽度为 20bits,用于表示一个立即数的高 20 位)
  • J-type: (Jump),每条指令含有一个寄存器参数再加上一个立即数参数(宽度为 20bits)

rd:r代表register d代表destination

rs:s代表source

算法运算指令

ADD

ADD RD(5),RS1(5),RS2(5) RD=RS1+RS2

5表示占5个bit

编码格式:R-type

image-20230721154322672

  • opcode:01 100 11
  • fuct3:000 funct7 0000000

SUB

SUB RD, RS1, RS2 RD=RS1-RS2

编码格式:R-type

image-20230721154425111

  • opcode:01 100 11
  • fuct3:000 funct7 0100000

ADDI(ADD Immediate)

ADDI RD, RS1, IMM RD=RSI+IMM

编码格式:I-type

image-20230721155114720

立即数只能表是-211211-1 (-20482047) 立即数参与运算前会被做符号拓展位32位imm

LUI(Loda Upper Immediate)

LUI RD,IMM RD=IMM<<12

编码格式:U-type

image-20230721163824345

和ADDI指令配合使用来给寄存器赋值大立即数

lui x1,0x12345
addi x1,0x678 ; x1=0x12345678

对于低12位的符号位是1的情况,由于addi有符号拓展,就需要用减法来实现

比如想让x1=0x12345fff

lui x1,0x12346
addi x1,-1

LI(Load Immediate)

LI RD,IMM RD=IMM

伪指令 可以给某个寄存器赋32位的值,就不需要我们自己用lui和addi指令来做,而是由汇编器来完成

AUIPC

AUIPC RD IMM RD=IMM<<12+PC

编码格式:U-type

image-20230721171932394

LA(Load Address)

LA RD,LABEL 加载一个函数或变量的地址

伪指令 汇编器会利用auipc指令和其他指令来生成

NEG

NEG RD,RS RD=-RS

伪指令 实际是SUB RD,x0,RS(零寄存器x0)

MV

MV RD,RS RD=RS

伪指令 实际上是ADDI RD,RS,0

NOP

就是nop啦hh

伪指令 实际上是ADDI x0,x0,0

逻辑运算指令

AND

AND RD,RS1,RS2 RD = RS1 & RS2

编码格式:R-type

image-20230721173921186

OR

OR RD,RS1,RS2 RD = RS1 | RS2

编码格式:R-type

image-20230721174008445

XOR

AND RD,RS1,RS2 RD = RS1 ^ RS2

编码格式:R-type

image-20230721174111167

ANDI

AND RD,RS1,IMM RD = RS1 & IMM

编码格式:I-type

image-20230721174041635

ORI

AND RD,RS1,IMM RD = RS1 & IMM

编码格式:I-type

image-20230721174138698

XORI

AND RD,RS1,IMM RD = RS1 & IMM

编码格式:I-type

image-20230721174152255

NOT

NOT RD,RS RD=!RS 非

伪指令 实际上是XOR RD,RS,-1

移位运算指令

>>>逻辑移位

SLL(Shitf Left Logical)

SLL RD,RS1,RS2 RD=RS1<<RS2

编码格式:R-type

image-20230721180716677

SRL(Shitf Right Logical)

SRL RD,RS1,RS2 RD=RS1>>RS2

编码格式:R-type

image-20230721180838972

SLLI(Shitf Right Logical Immediate)

SLLI RD,RS1,IMM RD=RS1<<IMM

编码格式:I-type

image-20230721180802935

SRLI(Shitf Right Logical Immediate)

SRLI RD,RS1,IMM RD=RS1>>IMM

编码格式:I-type

image-20230721180904728

>>>算数移位

SRA(Shitf Right Arithmetic)

SRA RD,RS1,RS2 RD=RS1>>RS2

编码格式:R-type

image-20230721181748545

SRAI

SRA RD,RS1,IMM RD=RS1>>IMM

编码格式:I-type

image-20230721181807571

shamt(shift amount)意为移动量,五个bit来描述2^5 – 1=31对于RV32就够了

内存读写指令load store

LB(Load Byte)

LB RD,IMM(RS1) *(Byte*)(RD) = *(Byte*)(RS1+IMM) 读取的数据做符号拓展

LH(Load Halfword)

LH RD,IMM(RS1) *(Halfword*)(RD) = *(Halfword*)(RS1+IMM) 读取的两字节数据做符号拓展

LW(Load Word)

LW RD,IMM(RS1) *(Word*)(RD) = *(Wword*)(RS1+IMM) 四字节

LBU(Load Byte Unsigned)

LBU RD,IMM(RS1) *(Byte*)(RD) = *(Byte*)(RS1+IMM) 读取的数据做零拓展

LHU(Load HalfWord Unsigned)

LHU RD,IMM(RS1) *(Halfword*)(RD) = *(Halfword*)(RS1+IMM) 读取的数据做零拓展

编码格式均为I-type

image-20230721182935536

SB(Store Byte)

SB RS2,IMM(RS1) *(Byte*)(RS1+IMM)=RS2[0:7]

SH(Stroe Halfword)

SB RS2,IMM(RS1) *(Halfword*)(RS1+IMM)=RS2[0:15]

SW(Store Word)

SB RS2,IMM(RS1) *(Word*)(RS1+IMM)=RS2

编码格式均为S-type

image-20230721185513346

条件分支指令

image-20230721190529161

跳转的目标地址计算方法:先将 IMM x 2,符号扩展后和 PC 值相加得到最终的目标地址,所以跳转范围是以 PC 为基准,+/- 4KB 左右 ([-4096, 4094])。

image-20230721192040448

b-type里是没有0位的应为0位永远为0,-4096, 4094是因为 2*(-2^(11),2^(11)-1)

image-20230721194722440

JAL RD,LABEL

编码格式J-type

image-20230721213626062

调用子过程,把20位宽的立即数2后进行符号拓展和pc值相加,然后把下一条指令地址写入RD,所以跳转范围应该是2*(-2^(19),2^(19)-1)即(-1048576,1048574)约等于+/-1M*

JALR RD,IMM(RS1)

编码格式I-type

image-20230721214742447

调用子过程,把12bit的IMM进行符号拓展后和RS1相加,将结果最低1bit设置为0(确保地址按照两字节对齐),跳转地址以RS1为基准,-2^11,2^11-1,上下**+/-2k**

对于超过1M的远距离跳转

auipc x6,IMM 
jalr x1,x6,IMM

J

J offset 相当于x86的jmp

伪指令 相当于JAL x0,offset

JR

JR RS

伪指令 相当于JALR x0,0(RS)

调用约定

image-20230721235450399

基于调用约定的伪指令

image-20230722001809195

TODO: emm,编译32位riscv时缺少头文件了,暂时没解决,64位又有一点点不一样,暂时不做实例分析