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

时间:2020-05-28 08:55:29

标签: 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];
}

进入

# 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"

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

如果只有lbu dest, offset(baseAdress)dest被允许用于寄存器baseAdresseoffset,而lbu a0, %lo(i)(a0)是指令字本身中的硬编码数字,这将是有道理的。但是在上面的相同代码中,我看到了offset,所以$hi $lo显然也可以是“有些变量”?

也许我不明白这一点的原因是因为我真的不明白为什么lui a0, %hi(i)这个东西首先是必要的。为什么我们要做lbu a0, %lo(i)(a0)lbu a0, 0(i)而不是{{1}}?

2 个答案:

答案 0 :(得分:2)

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

RISC V(和MIPS)没有基址寄存器+基址寄存器寻址模式-它们都只有一个,即基址寄存器+立即数。

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

而不只是lbu a0,0(i)?

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


您已将变量声明为全局变量,因此某些代码与访问全局变量有关。

myfunction():                        # @myfunction()
        lui     a0, %hi(i)      <--- 1st part of 2 instructions for the char i global
        lbu     a0, %lo(i)(a0)  <--- 2nd instruction for fetching the char i global
        lui     a1, %hi(A)      <--- 1st part of 2 instructions for A global array
        addi    a1, a1, %lo(A)  <--- 2nd instruction for fetching addr of A global

        add     a0, a0, a1      <--- the array indexing A + i
        lbu     a0, 0(a0)       <--- the dereference *(A+i)
        ret
i:
        .byte   3                       # 0x3

A:
        .ascii  "\000\001\002\003\004\005"

如果尝试其他方法,您会发现其中一些消失了,因此您可以直接查看数组引用:

int myfunction(char A [], int i) {
    return A[i];
}

myfunction(char*, int):                      # @myfunction(char*, int)
    add     a0, a0, a1
    lbu     a0, 0(a0)
    ret

答案 1 :(得分:1)

正如Erik Eidt所说,i是全局变量,即位于32/64位可寻址内存中的某个位置,并且可以随时更改。

i的32/64位地址分为两部分,因为不能立即对32/64位进行编码。 %hi(i)%lo(i)i地址的上部和下部。 i已从内存中加载,因为在两次调用myfunction()之间可能已更改。