RISC-V 中 JAL 和 JALR 指令的偏移地址

2023-12-31

在 RISC-V 规范中,JAL 和 JALR 指令中的立即数被转换为跳转偏移量,如下所示:

  1. 将给定立即数符号扩展为 XLEN 位。

  2. 将 LSB 设置为零。

我对此有几个问题。

问题1

对于 JAL,这给出了一个范围:

000000000000 to 111111111110

即4KiB。

在这里,如果 LSB 必须始终为零,为什么不将立即数视为地址的强制零 LSB 之前的 12 位,从而将地址范围增加到:

[000000000000]0 to [111111111111]0      

[ ] 表示给定的立即偏移量,内部会在给定的立即偏移量末尾加零。那是,

  1. 左移一位给出地址。

  2. 将结果符号扩展至 XLEN 位。

问题2

如何区分正偏移和负偏移?是否使用了给定偏移量的 MSB?


JAL有一个 20 位偏移量和一个寄存器作为操作数。

其操作是pc := pc + sxt ( imm20 << 1 ).

从公式中可以看出,分支是与 pc 相关的。立即数可以达到 +/- 1 MBJAL本身。立即数移位一位,真正的 LSB 始终为零,因此不进行编码。

由于 RISC V 支持 16 位倍数(两个字节)的指令,因此我们不能假设下一个 LSB 也为零,就像 MIPS(具有 32 位指令)一样。

寄存器操作数在JAL除了执行分支之外,还可以选择用于捕获返回地址。

JAL的功能是使用其 20 位范围执行相对较远的 pc 分支或调用。 (与 RISC V 条件分支指令相比,RISC V 条件分支指令只有 12 位,范围为 +/- 4 KB。)


JALR有一个 12 位偏移量和两个寄存器作为操作数。

其操作是pc := ( rs1 + sxt ( imm12 ) ) & -2.

从公式中可以看出,分支是寄存器间接的,相对于中的值rs1.

Like JAL, JALR还可以捕获返回地址。

JALR用于从函数返回(又名RET在装配中。在这种形式中,$ra 用作源寄存器,并且不捕获返回地址)。这使用零作为偏移量(即不需要偏移量)。

JALR还用于执行间接函数调用:通过函数指针、虚拟方法分派等进行调用。这些用途也使用零作为偏移量。

JALR也可以依次使用AUIPC.


AUIPC有一个 20 位偏移量和一个寄存器作为操作数。

其操作是rd := pc + ( imm20 << 12 ).

它计算 pc 相对立即数的上半部分(同时还提供非相对 pc 的下半部分)。

结合JALR,这可以完成 32 位 pc 相关的分支或调用。

AUIPC r5, labelFarAway      # AUIPC encodes upper 20 bits of label's distance from pc
JALR r5, $ra, labelFarAway  # JALR encodes the lower 12 bits of same
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RISC-V 中 JAL 和 JALR 指令的偏移地址 的相关文章

  • NOP 雪橇如何工作?

    我找不到回答这个问题的好来源 我知道 nop sled 是一种用于规避缓冲区溢出攻击中堆栈随机化的技术 但我无法理解它是如何工作的 有什么简单的例子可以说明这种方法 128 字节 nop sled 等术语是什么意思 有些攻击包括使程序跳转到
  • 分配内存空间的宏

    我需要让一个汇编程序员来计算帕斯卡三角形 https en wikipedia org wiki Pascal 27s triangle 这样帕斯卡三角形的每一行都与其他行分开存储在内存中 我想做一个 但我不知道如何使用宏在汇编中做到这一点
  • 我试图在 AAM 指令之后使用 AX 中存储的值将其除以 2,为什么它不适用于 2 位数字输出?

    英语不是我的母语 请原谅输入错误 我将在此处显示的代码是一项作业 我真的需要了解发生了什么事 我在 DosBox 0 74 和 TASM 汇编器中使用 Intel 8086 语法 当我必须除以 2 时 代码的问题在于三角形的面积 注意 程序
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 在汇编中显示两位数? [复制]

    这个问题在这里已经有答案了 我对汇编编程完全陌生 在课堂作业的示例中 需要将两个数字相加并显示总和 我发现神秘的是当其是两位数时显示总和 这是我的代码 mov al num1 mov bl num2 add al bl add ax 303
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • 为什么 Solaris 汇编器生成的机器代码与 GNU 汇编器在这里不同?

    我为 amd64 编写了这个小汇编文件 对于这个问题来说 代码的作用并不重要 globl fib fib mov edi ecx xor eax eax jrcxz 1f lea 1 rax ebx 0 add rbx rax xchg r
  • NASM 轮班操作员

    您将如何在寄存器上进行 NASM 中的位移位 我读了手册 它似乎只提到了这些操作员 gt gt lt lt 当我尝试使用它们时 NASM 抱怨移位运算符处理标量值 您能解释什么是标量值并举例说明如何使用 gt gt and lt lt 另外
  • 汇编基础知识:输出寄存器值

    我刚刚开始学习汇编语言 我已经陷入了 在屏幕上显示存储在寄存器中的十进制值 的部分 我使用 emu8086 任何帮助将不胜感激 model small Specifies the memory model used for program
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 在 x86-64 CPU 上通过交叉修改代码重现意外行为

    Question 对于可能在 x86 或 x86 x64 系统上触发意外行为的交叉修改代码有哪些想法 在这些系统中 交叉修改代码中的所有操作均已正确完成 但在执行处理器之前执行序列化指令除外修改代码 如下所述 我有一个 Core 2 Duo
  • 在 x86 ASM 中测试零通常哪个更快:“TEST EAX, EAX”与“TEST AL, AL”?

    测试 AL 中的字节是否为零 非零通常哪个更快 TEST EAX EAX TEST AL AL 假设之前有一个 MOVZX EAX BYTE PTR ESP 4 指令加载了一个带有零扩展的字节参数到 EAX 的其余部分 防止了我已经知道的组
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • “rep stos”x86 汇编指令序列有什么作用?

    我最近偶然发现了以下汇编指令序列 rep stos dword ptr edi For ecx重复 存储内容eax到哪里edi指向 递增或递减edi 取决于方向标志 每次 4 个字节 通常 这用于memset型操作 通常 该指令简单地写成r
  • 如何在 Debian 上编译 DOS 程序?

    在我的汇编语言课程中 我们使用 DPMI 编写 DOS 程序 不幸的是 我无法一直使用 32 位 Windows 机器 我在我使用的几乎每台计算机上都安装了 Debian 虚拟机 我已经安装了 DOSBox 和 DOSEMU 有什么办法可以

随机推荐