RISC-V 中 JAL 的定义是什么以及如何使用它?

win*_*e99 5 architecture hardware cpu-architecture riscv

我不明白 JAL 在 RISC-V 中是如何工作的,因为我看到了多个相互矛盾的定义。例如,如果我参考这个网站:https : //rv8.io/isa.html

它说: JAL rd,offset将第三个参数作为偏移量,但在某些情况下会显示JAL rd, imm。有什么不同?

看来,JAL应该采取功能和RD返回其输出(我不知道为什么有些人士把它称为ra并且rd在同一时间)。但如果是这样,子程序或函数是什么?rd似乎被定义为寄存器目的地,imm似乎只是一个整数..

真的很困惑请帮忙。

小智 8

jal指令中imm(或imm20)是一个 20 位的二进制数。

offset解释immjal指令:内容imm被左移1个位置,然后符号扩展为一个地址的大小(32个或64位,目前),从而使具有-1百万的值的整数(约) 到 +100 万。

这个offset整数被加到jal指令本身的地址上,得到你要调用的函数的地址。这个新地址被放入 PC,程序继续执行,无论指令位于该地址。

同时,将 后面的指令地址jal存入 CPU 寄存器中rd。被调用的函数可能稍后会使用 this 返回,使用jalr rn指令。

RISC-V 硬件允许将 32 个整数寄存器中的任何一个指定为rd. 如果给出寄存器 0 (x0) 则rd返回地址将被丢弃,您实际上拥有 +/1 MBgoto而不是函数调用。

标准的 RISC-V ABI(一种软件约定,与硬件无关)指定对于正常功能rd应该是寄存器 1(x1),然后通常称为ra(返回地址)。寄存器 5 (x5) 也常用于特殊的运行时库函数,例如在函数开始和结束时保存和恢复寄存器的特殊函数。

RISC-V 指令集手册建议 CPU 设计人员可能会选择添加特殊硬件 (a return address stack) 来使严格嵌套的jal x1/x5,offset和 `jalr x1/x5' 比预期运行得更快,因此遵循标准 ABI。但是,即使使用其他寄存器,程序也能正常工作。


Eri*_*idt 3

看来您混淆了机器代码和汇编语言。

从机器代码的角度来看,整个指令及其所有字段都只是数字:

  • 有些是编码诸如操作码之类的字段,
  • 有些是编码诸如寄存器号之类的字段,并且,
  • 有些字段是编码有符号或无符号整数之类的数字。

这些编码由指令集架构定义。该硬件专门设计用于根据 ISA 规范解释这些数字位字段。

汇编器、链接器和操作系统加载程序共同允许您使用符号值来形成指令,而不是各个字段的数字(甚至整个指令的一个数字):

  • 操作码字段中操作码编号的操作码助记符,
  • 寄存器字段中的寄存器编号的寄存器名称,以及,
  • 数字操作数字段中各种立即值的标签(甚至是复杂的表达式)。

我不会太认真地对待一篇文章提到ravs. 的问题rd。它可能表明存在差异,或者只是记录指令的机器代码字段的不同方式。

JAL 指令对两个操作数进行编码:寄存器和立即数。

所识别的寄存器号将使用返回地址的位置(即 jal 指令的位置 — 加上 jal 指令的长度)进行更新,以便寄存器获取jal 之后的下一个连续(按地址)指令的值,这是调用的正确返回地址。

与指令中的所有位字段一样,立即数是一种编码 - 解码值最终产生分支目标地址。它是通过将立即位字段转换为带符号的偏移量来计算的,并添加到 jal 指令的 pc 中。该编码允许 18 位(分布在多个位字段中)加上一个符号位,并且不会对偏移量的最后一位进行编码(分支目标始终是 16 位对齐,这意味着最后一位无论如何都将始终为零,因此它是不存储)。最终,jal 指令本身可以达到 -0.5MB 到 +0.5MB。

如前所述,执行硬件将立即(子)字段转换为偏移量,并将其添加到 pc 中以标识最终分支/调用目标。我们可以用汇编语言提供标签和其他复杂的表达式,这是这些语言的一个特性,其目的是将标签和其他表达式压缩为处理器所需的立即位域常量,以到达预期的位置。目标代码中存在重定位和/或加载代码中的修复的复杂交互,确保这些立即位字段保存有用的位模式,硬件可以基于运行时相对简单的字段提取和添加来使用该位模式以到达预期位置。


为了使函数能够相互调用而不侵犯彼此的脚趾,调用者和被调用者的 asm 代码必须就以下所有内容达成一致:

  • 传递的参数
  • 已传递返回地址
  • 返回值
  • 保留寄存器
  • 暂存寄存器

这被广泛地称为调用约定。它规定了调用者如何对被调用者一无所知,反之亦然。它对哪个寄存器或堆栈位置保存第一个参数、第二个参数等施加了软件约定要求。哪个寄存器或堆栈位置保存返回地址、如何传送返回值以及保留调用者环境的哪些寄存器通过调用与可能通过调用擦除(划痕)。

当正确遵守约定时,调用者(不知道被调用者的实现,只知道参数的类型和返回值,也称为函数签名)可以

  • 通过调用将局部变量安全地存储在机器寄存器中,
  • 传递参数
  • 调用被调用者,
  • 返回给调用者,
  • 然后,接收返回值并继续

  • “ra”表示*返回地址*,它是通常用作操作数的“x1”寄存器的助记符。`rd` 表示*寄存器目的地*,它是指令写入的寄存器的通用参数名称。 (3认同)