gpt4 book ai didi

assembly - 使用 LUI 和 ADDI 了解 RISC-V 汇编中的 EQU 和 >> 运算符

转载 作者:行者123 更新时间:2023-12-02 19:24:25 29 4
gpt4 key购买 nike

我的教授将此作为家庭作业问题的答案之一发布。谁能帮我解决这个问题吗?我不明白他对 CON1 - CON4 做了什么以及 >> 和 0x0FFF 是什么意思。

CON1:   EQU 6000
CON2: EQU 6245
CON3: EQU 10000
CON4: EQU 10245
A: DM 4 ; DM is Define Memory

addi t1, x0, A ; t1 = &A

lui t0, (CON1>>12) + ((CON1 & 0x0800)>>11)
addi t0, t0, CON1&0xFFF
sd t0, 0(t1) // Cut and paste from last question of Quiz1
// Blank line between groups of statements
lui t0, (CON2>>12) + ((CON2 & 0x0800)>>11)
addi t0, t0, CON2&0xFFF
sd t0, 8(t1)

lui t0, (CON3>>12) + ((CON3 & 0x0800)>>11)
addi t0, t0, CON3&0xFFF
sd t0, 16(t1)

lui t0, (CON4>>12) + ((CON4 & 0x0800)>>11)
addi t0, t0, CON4&0xFFF
sd t0, 24(t1)
// We need this to avoid the NO INSTRUCTION error
ebreak x0, x0, 0 ; Suspend program.

如有任何帮助,我们将不胜感激,谢谢。我们正在使用 RISC-V

最佳答案

在RISC-V基础指令集中,每条指令都以32位编码。这意味着立即操作数的空间仅限于几个位。因此,要将更大的常量放入寄存器(RV32G/RV64G 也是 32 或 64 位宽),您需要将其拆分并使用多个指令移动部分,即 RV32G 为 2 个,RV64G 为 8 个。

使用 32 位 RISC-V (RV32G),可以通过加载上立即数 ( lui ) 和添加立即数 ( addi ) 来加载更大的常量操作说明。 lui 的立即操作数是 20 位宽,而 addi允许 12 位立即数操作数。因此,它们足以加载最多使用 32 位的常量。

lui对立即操作数进行符号扩展并将其左移 12 位,并将结果加载到目标寄存器中。因此得名。 addi在添加它之前,还会对它的直接操作数进行符号扩展。

因此,使用 RV32G,可以使用 lui 加载更大的常数接下来是 addi必须取高 20 位,将它们逻辑右移 12 位,这样 12 位左移 lui被取消。然后对低 12 位进行掩码,得到 addi 的操作数.

如果 addi 就足够了不对其直接操作数进行符号扩展。如果确实如此,因为最高位设置为 1,我们必须增加 lui操作数使得多余的符号位在加法中再次被清零。

假设我们表示常数 x 的高位部分与 h ,低位带有l ,由于 RISC-V 在寄存器溢出时实现了二进制补码和算术换行,因此我们可以使用模算术来看到:

     h + l = x                             # taking register widths into account:
=> (h + l) % 2**32 = x % 2**32 # in case l is sign extended:
=> (h + l + e + c) % 2**32 = x % 2**32 # replace e with the additional sign bits:
<=> (h + l + 4294963200 + c) % 2**32 = x % 2**32 # eliminate c:
<=> (h + l + 4294963200 + 4096) % 2**32 = x % 2**32
<=> (h + l) % 2**32 + (4294963200 + 4096) % 2**32 = x % 2**32
<=> (h + l) % 2**32 + 0 = x % 2**32

因此,我们必须将 lui 加 1立即操作数(左移 12 位后等于 4096)当且仅当 addi 的立即操作数是符号扩展的。

在您的汇编示例中,>>表示右移,<<左移和 &逻辑与。它们用于实现所描述的分割和算术,例如在

 lui t0,  (CON1>>12) + ((CON1 & 0x0800)>>11)
addi t0, t0, CON1&0xFFF

哪里CON1 & 0x0800屏蔽 12 位,即 addi 的符号位立即操作数。如果设置了 ((CON1 & 0x0800)>>11)计算结果为 1,从而消除了以下 addi 添加的多余符号位操作说明。 CON1&0xFFF屏蔽最低 12 位。

在标准 RISC-V 汇编中,只需使用立即加载 ( li ) 伪指令即可避免所有这些繁琐的位管理,例如:

li     t1, 6245

汇编器自动将其转换为最佳指令序列(例如使用 objdump 检查):

lui    t1, 0x2
addi t1, t1,-1947

或者,使用 GNU 作为汇编器,也有将操作数分为上部和下部的指令:

lui    a1, %hi(6245)
addi a1, a1, %lo(6245)

这可以说比代码片段中的困惑更具可读性。

这也适用于 GNU 中的符号,例如:

.set CON2, 6245

li a1, 6245

lui a2, %hi(CON2)
addi a2, a2, %lo(CON2)

li a3, CON2

# => a1 == a2 == a3

关于assembly - 使用 LUI 和 ADDI 了解 RISC-V 汇编中的 EQU 和 >> 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59869014/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com