MIPS 分支而不是跳转

MIPS branch instead of jump

为什么要使用预定条件的分支,比如这样:

beq [=10=], [=10=], TEST

而不是像这样使用跳跃?

j TEST

分支用于测试条件,但在本例中,分支使用的条件始终为真。那么为什么要在跳跃上使用它呢?它以某种方式更快吗?

我遇到了这个 answer,但我不知道它是否确实是我问题的正确答案,因为我对搬迁一无所知。

J指令编码如下:

----------------------------
| opcode |   instr_index   |
----------------------------

instr_index 是目标地址的最低有效 28 位,右移 2 位得到 26 位值。你最终跳转到的地址是 (PC & 0xF0000000) | (instr_index << 2)

BEQ变体编码如下:

-----------------------------
| opcode | 0 | 0 |  offset  |
-----------------------------

你最终要跳转到的地址是 PC + sign_extend(offset << 2)

(注意,在这两种情况下,PC 是紧跟在 branch/jump 指令之后的指令地址,而不是 branch/jump 指令本身)。

现在,假设您有以下代码:

main:
j foo
nop
foo:

并且此代码原本打算加载到地址 0x00400024foo 的地址将是 0x0040002c,而 J 指令将被编码为 (2 << 26) | (0x0040002c >> 2) = 0x0810000b.

但随后您决定要重新定位此代码(将其复制到内存中的某个其他位置并在该位置执行)。假设您的代码现在正在 0x00410000 处执行。在这种情况下,我们希望 J 指令跳转到 0x00410008,但它仍然会跳转到 0x0040002c(0x00410004 & 0xF0000000) | (0x010000b << 2) = 0x0040002c)。

另一方面,如果您使用了 BEQ,您将得到指令词 0x10000001 ((4 << 26) | (4 >> 2))。即使代码被重新定位,您仍然会最终分支到正确的地址:0x00410004 + (1 << 2) = 0x00410008