使用具有预定条件的分支的原因是什么,例如:
beq $0, $0, TEST
而不只是像这样使用跳跃?
j TEST
分支用于测试条件,但在这种情况下,分支的使用条件始终为true。那么为什么要跳过它?它以某种方式更快吗?
我偶然发现了answer,但我不知道这是否确实是我问题的正确答案,因为我对重新安置一无所知。
答案 0 :(得分:1)
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
都是紧接在分支/跳转指令之后的指令的地址,而不是分支/跳转指令本身。)
现在,假设您有以下代码:
main:
j foo
nop
foo:
此代码原本打算在地址0x00400024
加载。 foo
的地址将为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
。