MIPS 跳转和分支指令范围
MIPS jump and branch instructions range
我刚开始学习 MIPS,但我无法理解跳转和分支指令的范围。我知道 "far" PC 的跳跃和分支方式是有限制的,但我不明白为什么。
还有2个具体问题,如果PC
的当前值为0x00000000
,是否可以对随机地址进行1次跳转?如果 PC
的当前值为 0x00000600
,是否可以对随机地址执行 1 个分支?
MIPS 处理器使用固定大小的指令,其中每个指令字都是一个 字(即 4 字节 == 32 位)。所以只有这么多信息可以塞进这 4 个字节。
J
和JAL
指令使用32位中的6位来指定操作码。这留下 26 位来指定目标地址。虽然指令中没有直接指定目标地址(没有足够的位)——相反,会发生什么:
- 将目标地址的低28位右移2位,然后将低26位存入指令字。由于所有指令都必须字对齐,我们移出的两位将始终为零,因此我们不会丢失任何无法重新创建的信息。
- 发生跳转时,将这26位左移2位得到原来的28位,再与
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,所以目标地址变为(0 << 28) | 0x40002c
,等于0x40002c
,恰好是[=22=的地址].
b main
指令被编码为 0x0401fffd
。 16 个最低有效位的值为 0xfffd
,向左移动 2 位后变为 0x3fff4
。将其符号扩展为 32 位得到 0xfffffff4
。当将它添加到 b
之后的指令地址时,我们得到 0x400030 + 0xfffffff4
,它(当被截断为 32 位时)等于 0x400024
,它恰好是 [=31] 的地址=].
如果要跳转到某个任意地址,将地址加载到寄存器中,然后使用jr
或jalr
指令跳转。
我刚开始学习 MIPS,但我无法理解跳转和分支指令的范围。我知道 "far" PC 的跳跃和分支方式是有限制的,但我不明白为什么。
还有2个具体问题,如果PC
的当前值为0x00000000
,是否可以对随机地址进行1次跳转?如果 PC
的当前值为 0x00000600
,是否可以对随机地址执行 1 个分支?
MIPS 处理器使用固定大小的指令,其中每个指令字都是一个 字(即 4 字节 == 32 位)。所以只有这么多信息可以塞进这 4 个字节。
J
和JAL
指令使用32位中的6位来指定操作码。这留下 26 位来指定目标地址。虽然指令中没有直接指定目标地址(没有足够的位)——相反,会发生什么:
- 将目标地址的低28位右移2位,然后将低26位存入指令字。由于所有指令都必须字对齐,我们移出的两位将始终为零,因此我们不会丢失任何无法重新创建的信息。
- 发生跳转时,将这26位左移2位得到原来的28位,再与
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,所以目标地址变为(0 << 28) | 0x40002c
,等于0x40002c
,恰好是[=22=的地址].
b main
指令被编码为 0x0401fffd
。 16 个最低有效位的值为 0xfffd
,向左移动 2 位后变为 0x3fff4
。将其符号扩展为 32 位得到 0xfffffff4
。当将它添加到 b
之后的指令地址时,我们得到 0x400030 + 0xfffffff4
,它(当被截断为 32 位时)等于 0x400024
,它恰好是 [=31] 的地址=].
如果要跳转到某个任意地址,将地址加载到寄存器中,然后使用jr
或jalr
指令跳转。