我刚开始学习 MIPS,但在理解跳转和分支指令的范围时遇到了麻烦。我知道 PC 可以跳跃和分支的“远”有多远是有限制的,但我不明白为什么。
还有2个具体问题,如果当前值PC
是 0x00000000
,是否可以对随机地址执行 1 JUMP?如果 PC
的当前值是 0x00000600
,是否可以对随机地址执行 1 BRANCH?
最佳答案
MIPS 处理器使用固定大小的指令,其中每个指令字都是一个字(即 4 字节 == 32 位)。所以只有这么多信息可以塞进这 4 个字节中。J
和 JAL
指令使用 32 位中的 6 位来指定操作码。这留下了 26 位来指定目标地址。尽管没有直接在指令中指定目标地址(没有足够的位) - 相反,会发生以下情况:
J
后面的指令地址的4个最高有效位结合起来。/JAL
形成一个 32 位地址。 这使得可以跳转到跳转指令所在的相同 256MB 范围 (2^28) 中的任何指令(或者如果启用了延迟分支;跳转到与延迟中的指令相同的 256MB 范围内的任何指令)投币口)。
对于分支指令,有 16 位可用于指定目标地址。这些存储为相对于分支指令之后的指令的有符号偏移量(再次应用两位移位,因为没有必要存储我们知道始终为 0 的东西)。所以恢复2个最低有效位后的实际偏移量为18位,然后将其符号扩展为32位并添加到分支指令之后的指令地址。这使得可以在分支指令内分支到 +/-128kB。
考虑在地址 0x00400024 加载的以下代码:
main:
j foo
nop
foo:
b main
nop
j foo
指令编码为 0x0810000b
. 26 个最低有效位的值为 0x10000b
, 左移 2 位后变成 0x40002c
. j
后面的指令地址的4个最高有效位为零,所以目标地址变为 (0 << 28) | 0x40002c
, 等于 0x40002c
,恰好是foo
的地址.b main
指令编码为 0x0401fffd
. 16 个最低有效位的值为 0xfffd
, 左移 2 位后变为 0x3fff4
.将其符号扩展到 32 位给我们 0xfffffff4
.并将其添加到 b
之后的指令地址时我们得到 0x400030 + 0xfffffff4
,其中(当截断为 32 位时)等于 0x400024
,恰好是main
的地址.如果要跳转到某个任意地址,请将地址加载到寄存器中并使用
jr
或 jalr
指令跳跃。
关于assembly - MIPS 跳转和分支指令范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36442586/