RISCV-LEARN

Load Immediate

想要将一个立即数加载到寄存器中,可以使用伪指令li,但是li实际对应的指令是什么呢?汇编器是如何做的?

addi lui li slli

1744940736835

sext全称Sign EXTension;通过上图可以看到,立即数只有12位,那么如果我想处理的立即数不止12位怎么办?

1744940973694

lui指令虽然有load,但是和访存一点关系也没有,其能够设置一个寄存器的高20位的值,与此同时,低12位的值被设置为0。

那么,如果想要将一个32位的立即数加载到寄存器中,就需要结合addi和lui了,即伪指令li。

1744941357080

li的具体展开由汇编器来实现,会根据立即数的位数来决定展开后的指令。

1744941794815

shamt全称SHift AMounT,表示移位量,共6位,即最多移63位。故对于RV32而言,shamt[5]=0时才合法,否则目的寄存器为0。

问题

在RV32I中,假设想要将32位立即数0x12345678加载到寄存器x5中:

lui x5, 0x12345		# x5:0x12345000
addi x5, x5, 0x678	# x5:0x12345678

在RV64I中,假设想要将64位立即数0x123456789ABCDE0F加载到寄存器x5中:

lui x5, 0x12345		# x5:0x0000000012345000
addi x5, x5, 0x678	# x5:0x0000000012345678
slli x5, x5, 12		# x5:0x0000012345678000
addi x5, x5, 0x9AB	# x5:0x00000123456789AB
slli x5, x5, 12		# x5:0x00123456789AB000
addi x5, x5, 0xCDE	# x5:0x00123456789ABCDE
slli x5, x5, 8		# x5:0x123456789ABCDE00
addi x5, x5, 0x0F	# x5:0x123456789ABCDE0F

以上过程,均可以用li伪指令来替代,但汇编器在解析li时做的事情不仅是简单的转换,还需要考虑立即数的实际情况,比如考虑下面这种情况:

在RV32I中,假设想要将32位立即数0x12345FFF加载到寄存器x5中:

lui x5, 0x12345		# x5:0x12345000
addi x5, x5, 0xFFF	# x5:0x12344FFF

通过上面步骤得到的x5的值是0x12344FFF,因为addi在执行加法操作前,会将立即数sext为32位,故而如果只是将li做简单转换而不分析立即数的实际情况,会出现错误,正确做法:

lui x5, 0x12346		# x5:0x12345000
addi x5, x5, 0xFFF	# x5:0x12345FFF

li伪指令总结(RV32I):

例子

接下来看看实际的程序,这里有一个C语言程序:

#include <stdio.h>
int main()
{
    int a = 0x00000678;
    int b = 0x12345678;
    int c = 0x12345FFF;
    return 0;
}

经过gcc和objdump可以得到:

# gcc -g -c li.c -o li.o
# objdump -S li.o

li.o:     file format elf64-littleriscv


Disassembly of section .text:

0000000000000000 <main>:
#include <stdio.h>
int main()
{
   0:   1101                    add     sp,sp,-32
   2:   ec22                    sd      s0,24(sp)
   4:   1000                    add     s0,sp,32
    int a = 0x00000678;
   6:   67800793                li      a5,1656
   a:   fef42623                sw      a5,-20(s0)
    int b=0x12345678;
   e:   123457b7                lui     a5,0x12345
  12:   67878793                add     a5,a5,1656 # 12345678 <.LASF9+0x123455a1>
  16:   fef42423                sw      a5,-24(s0)
    int c=0x12345FFF;
  1a:   123467b7                lui     a5,0x12346
  1e:   17fd                    add     a5,a5,-1 # 12345fff <.LASF9+0x12345f28>
  20:   fef42223                sw      a5,-28(s0)
    return 0;
  24:   4781                    li      a5,0
  26:   853e                    mv      a0,a5
  28:   6462                    ld      s0,24(sp)
  2a:   6105                    add     sp,sp,32
  2c:   8082                    ret