RISC-V:PC 绝对与 PC 相对

RISC-V: PC Absolute vs PC Relative

我是 RISC-V 的新手。

我无法理解何时编写 PC(程序计数器)相关指令以及何时编写 PC 绝对指令。

例如,lui 后跟 jalr 指令的指令被认为是 PC-absolute,并且 auipc 后跟 jalr 指令的指令被认为是 PC-relative.

据我了解,所有指令都将由 PC 执行,因此执行此类 PC 绝对指令似乎是隐藏的(即 PC 不知情)。

对我来说,那些PC绝对指令不会被执行。

有人可以提供一些基本示例来帮助我理解这一点吗?

PC-relative
absolute

如果地址是相对于代码本身的地址计算的,则调用某些指令(或代码)"PC relative"。

当地址不是相对于指令本身的地址计算时,您调用指令 "absolute"。

不幸的是,我不知道 RISC V CPU,但以下(旧)68000 CPU 的示例向您展示了它的含义:

x:
    lea.l (PC+y-x-2), a0
    lea.l (y).l, a0
  ...
y:

两条指令都会将地址y加载到寄存器a0

不过还是有区别的:

假设代码位于地址0x1000,地址y位于地址0x2000。

现在我们将代码移动到地址 0x1200 并在那里执行代码。会发生什么?

第一条指令会将地址 0x2200 加载到寄存器:

地址计算相对于指令地址:计算为(address of the instruction)+0x1000。因为指令现在位于地址 0x1000 而不是 0x1200,所以要写入寄存器的值将是 0x2200,而不是 0x2000。

这叫做(PC)相对寻址

第二条指令会将地址0x2000加载到寄存器中。它总是将值 0x2000 加载到寄存器中 - 指令本身的地址无关紧要。

这称为绝对寻址

我认为您遇到的问题是“绝对 PC”的概念,这实际上不是一回事。您的选项是“PC 相对”和“绝对”。 RISC-V 定义了两个寻址指令,可以有效地实现这些模式:

  • lui(加载高位立即数):这会将 rd 设置为 32 位值,低 12 位为 0,高 20 位来自 U 型立即数。
  • auipc(将高位立即数添加到程序计数器):这会将 rd 设置为当前 PC 和一个 32 位值的总和,低 12 位为 0,高 20 位来自 U 型立即数的位。

这些指令本质上是相同的:它们都采用 U 型立即数(即 32 位数量的高 20 位),将其添加到某物中,并在 rd 中产生结果.不同之处在于 lui 将立即数添加到 0,而 auipc 将立即数添加到 PC。有时更容易将这两种寻址模式视为“PC 相对”和“0 相对”,因为这样可以更明确地区分。

虽然 auipclui 都设计为双指令对中的第一条指令,但第二条指令并不是特别相关。 auipclui 都填充了 32 位地址的高 20 位,而与它们配对的指令则填充了低 12 位。 I 和 S 格式的指令被设计成在这里可以很好地配对,并且在基本 ISA 中的每条指令都有一个 I 或 S 变体,这样的格式对它们来说是有意义的。

作为一个具体的例子,下面的C代码执行了一个非常简单的

int global;
int func(void) { return global; }

举个例子,假设global位于0x20000004,func中第一条指令的PC为0x10000008。

当使用 -mcmodel=medlow(0 相对寻址模式)编译时,您将得到

func:
    lui a0, 0x20000
    lw  a0, 0x004(a0)

可以看到,global(0x2000004)的完整绝对地址被填充到指令对中。另一方面,当使用 -mcmodel=medany(PC 相对寻址模式)编译时,您将得到

func:
    auipc a0, 0x10000
    lw    a0, 0x004(a0)

这次指令对中只出现了auipc的PC与目标符号的偏移量。发生这种情况是因为 PC 明确地(通过使用 auipc 指令)包含在寻址计算中。在这种情况下,auipca0 设置为 0x2000004:执行的计算是 a0 = PC + (imm20 << 12),这里我们有 0x10000004 用于 PC 和 0x10000 对于 imm20.

这些相对于 PC 的寻址序列还允许少量的位置独立性:如果您非常小心地限制您正在做的事情,则可以生成链接的二进制文件,当以不同的偏移量加载时仍然可以工作他们是有联系的。实际上,这对于 POSIX 式系统中的完全位置无关寻址是不够的(这就是为什么我们也有一个 -fPIC 参数,就像其他人一样),但是如果你在严格约束的嵌入式系统,您也许可以摆脱它。

对于最后的皱纹,就像 RISC-V ISA 中的几乎所有其他东西一样,auipclui 使用的立即数被符号扩展到 XLEN。在 32 位系统上,这些寻址模式可以生成系统中的任何地址,但对于 64 位系统则不然。这就是为什么我们将这些寻址模式称为“medany”和“medlow”:“med”代表“medium”,这意味着所有全局符号都必须适合的 4GiB window。 “low”部分意味着这个 window 以绝对地址 0 为中心,而在“any”部分意味着这个 window 以它链接的任何 PC 为中心。