RISC-V加载指令中的地址偏移是否硬编码?

Lin*_*nus 3 assembly riscv

出于教育目的,我使用https://godbolt.org/z/7F-Lhm进行翻译

// C++ code
char i = 3;
char A[] = {0,1,2,3,4,5};  
int myfunction() {
    return A[i];
}
Run Code Online (Sandbox Code Playgroud)

进入

# RISC-V instructions 
myfunction():                        # @myfunction()
        lui     a0, %hi(i)
        lbu     a0, %lo(i)(a0)
        lui     a1, %hi(A)
        addi    a1, a1, %lo(A)
        add     a0, a0, a1
        lbu     a0, 0(a0)
        ret
i:
        .byte   3                       # 0x3

A:
        .ascii  "\000\001\002\003\004\005"
Run Code Online (Sandbox Code Playgroud)

但为什么是A[i]“装载” add a0, a0, a1lbu a0, 0(a0)而不是“仅仅装载” lbu a0, a0(a1)

lbu dest, offset(baseAdress)如果仅允许destbaseAdresse为寄存器地址,而offset是指令字本身中的硬编码数字,则这是有意义的。但在上面的相同代码中我看到lbu a0, %lo(i)(a0)所以offset显然也可以是“有些变量”?

也许我不明白这一点的原因是因为我$hi $lo一开始就不太明白为什么这个东西是必要的。我们为什么要做lui a0, %hi(i)lbu a0, %lo(i)(a0)而不是仅仅lbu a0, 0(i)

Eri*_*idt 6

\n

不仅仅是 lbu a0, a0(a1)?

\n
\n

RISC V(和MIPS)没有基址寄存器+索引寄存器寻址模式\xe2\x80\x94,它们都只有一种,那就是基址寄存器+立即数。

\n

因此A+i所需的寄存器+寄存器操作必须用单独的加法指令来完成。

\n
\n

而不是 lbu a0, 0(i)?

\n
\n

32 位指令中没有足够的空间来保存全局地址,因此使用了多个指令。

\n
\n

您已将变量声明为全局变量,因此其中一些代码是关于访问全局变量的。

\n
myfunction():                        # @myfunction()\n        lui     a0, %hi(i)      <--- 1st part of 2 instructions for the char i global\n        lbu     a0, %lo(i)(a0)  <--- 2nd instruction for fetching the char i global\n        lui     a1, %hi(A)      <--- 1st part of 2 instructions for A global array\n        addi    a1, a1, %lo(A)  <--- 2nd instruction for fetching addr of A global\n\n        add     a0, a0, a1      <--- the array indexing A + i\n        lbu     a0, 0(a0)       <--- the dereference *(A+i)\n        ret\ni:\n        .byte   3                       # 0x3\n\nA:\n        .ascii  "\\000\\001\\002\\003\\004\\005"\n
Run Code Online (Sandbox Code Playgroud)\n

如果您尝试不同的方法,您会看到其中一些消失,这样您就可以更直接地看到数组引用:

\n
int myfunction(char A [], int i) {\n    return A[i];\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n
myfunction(char*, int):                      # @myfunction(char*, int)\n    add     a0, a0, a1\n    lbu     a0, 0(a0)\n    ret\n
Run Code Online (Sandbox Code Playgroud)\n