有人可以解释 ARM 中的分支操作码吗?

Can someone explain the branch opcode in ARM?

我正在尝试创建一个操作码以跳转到某个地址。

我查看了手册,发现:

B<c> <label>

31 30 29 28 | 27 26 25 24 | 23 ................. 0
    cond      1  0  1  0          imm24

我不明白 condimm24 是什么。我将如何创建一个操作码以分支到某个地址,例如分支到 0xbeffffbc?

看看ARM指令集,你正在寻找分支指令。您可以轻松创建标签并跳转到它们(跳转到代码中的特定位置),但我认为这不是您想要做的。

如果你想跳转到一个内存地址,有很多方法可以做到这一点(寻址模式)。立即寻址、间接寻址、... 您应该在这里找到您要搜索的说明:ARM branch instructions

您真的应该看看寻址是如何工作的。在汇编中编程时了解它的作用是至关重要的。

在这里您可以找到不同寻址模式的工作原理: ARM addressing modes Summary of the different addressing modes

基本上你需要知道你在内存中(不多于或少于位)。因此,必须就如何组织记忆做出某些决定。某些部分或为特定事物保留。

有了这个内存,你可以很容易地建立一个堆栈,只需要记住最上面位置的地址(第一个空闲位置,即 SP(堆栈指针))。然后你可以使用相对于堆栈指针的地址。这也是他们实施 procedure calls.

的方式

底层工作信息: Working of the stack

在大多数体系结构中,imm 是一个立即数(在实际指令中编码)。因此,我假设 imm24 是一个 24 位长的立即数。这个 imm 值通常是有符号的。

大多数 jmp 指令与当前 Program Counter 相关。这意味着编码到指令中的立即数被添加到程序计数器,它将指向下一条指令。如果 imm 值为负数,将从当前程序计数器中减去该值。否则,imm 值将添加到程序计数器。

要创建到您的地址0xbeffffbc的分支,您需要知道当前指令的地址并计算它们之间的差值。

B 是最大 +/-32MB 的 relative 分支。 immediate编码了目标地址相对于当前PC的有符号偏移量(即这条指令+8)——注意这个偏移量是以words,而不是bytes计算的;由于指令始终是字对齐的,因此任何偏移量的低两位将始终为 00,因此在编码中隐含。

cond 与大多数其他 ARM 指令中的谓词字段相同。如果你已经到了探索指令编码的地步,你可能应该已经意识到这一点——ARM ARM 的 "Conditional Execution" 部分(v7A/R 版本中的 A8.3 部分我手头有)有完整的细节。

ARM ARM 的典型烦恼是,虽然编码字段及其代表的值在指令描述中有描述,但您有时不得不交叉引用伪代码弄清楚到底发生了什么。

如果您的分支指令位于 0xb0 并且您想跳转到 0xbc,则编码指令的 imm24 部分的值为 3。

你指令的 imm24 部分中的这个数字 3 告诉你 [指令数] 你正在从当前位置移动到你想去的地方。

imm24 编码为 3 而不是您期望的 12 的原因(因为分支位于 0xb0 而您希望位于 0xbc,相差 12)是因为 imm24 中编码的偏移值是使用以下值计算的PC寄存器,一个相对于地址分支的值位于(0xb0),顺便说一下,它不是你想象的0xb0而是0xb8.

您的 PC 寄存器的值是指令地址分支前 2 条指令(由于流水线),因此您的分支指令的实际位置是 0xb8 而不是 0xb0。

所以 ARM 指令的大小为 4 个字节,而您要移动 3 个指令,因此 3 x 4 会给您 12 个 0xb0 到 0xbc 的差值。

因此,如果您想完全按照上述格式格式化您的指令

你会有一个操作码告诉处理器分支即将到来(一个特定值)然后是一个可选条件(cond 部分)它告诉你在什么条件下它应该使这个分支,例如如果它小于或更多,然后是上面解释的 imm24 部分,这将构成您的完整说明。