这是我编写的一些用于测试跳转指令的MIPS汇编代码:
addi $a0, $0, 1
j next
next:
j skip1
add $a0, $a0, $a0
skip1:
j skip2:
add $a0, $a0, $a0
add $a0, $a0, $a0
skip2:
j skip3
loop:
add $a0, $a0, $a0
add $a0, $a0, $a0
add $a0, $a0, $a0
skip3:
j loop
当我运行汇编程序时,结果如下:
[0x000000] 0x20040001 # addi $a0, $zero, 1 ($a0 = 1)
[0x000004] 0x08000002 # j 0x0002 (jump to addr 0x0008)
[0x000008] 0x08000004 # j 0x0004 (jump to addr 0x0010)
[0x00000C] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x000010] 0x08000007 # j 0x0007 (jump to addr 0x001C)
[0x000014] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x000018] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x00001C] 0x0800000B # j 0x000B (jump to addr 0x002C)
[0x000020] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x000024] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x000028] 0x00842020 # add $a0, $a0, $a0 ($a0 = $a0 + $a0)
[0x00002C] 0x08000008 # j 0x0008 (jump to addr 0x0020)
查看跳转指令的机器代码,这就是我所看到的:
1st jump (just jumps to next instruction) 0x08000002
2nd jump (skips 1 instruction) 0x08000004
3rd jump (skips 2 instructions) 0x08000007
4th jump (skips 3 instructions) 0x0800000B
5th jump (skips 3 instructions backwards) 0x08000008
通过查看这些指令,看起来机器代码以跳转指令的08开头,最后的数字告诉跳转指令去哪里。但是,我无法弄清楚这个数字是如何计算出来的。此外,没有什么可以向我表明第五跳是向后跳跃。
如何计算跳跃值?
答案 0 :(得分:15)
请查看参考手册,了解有关操作码编码的更多详细信息。
短版本:在32位指令中,您不能包含32位跳转目标。操作码使用6位,为指令留下26位。通过取j
指令之后的指令地址的前4位来构造目标地址,然后将2个零位附加到跳转指令操作数的26位。 (由于指令是32位,对齐很有用,允许省略最后两个0。)
向后跳转:地址是绝对的,不是相对的,所以它只取决于跳转指令的地址,无论是向前跳跃还是向后跳跃。
编辑:更详细的说明: 我们在地址 x 跳转指令 j 。设 t 表示 j 的跳转操作数。 t 是26位宽。 下一条指令的地址位模式计算如下:
upper_6_bits_of(x+4),t,0,0
所以跳跃总是绝对。没有相对跳跃。当结果小于x然后它是向后跳跃,当它更大时它是向前跳跃(如果你想要一些愚蠢的东西,你使它相等; - )。
让我们看看你的例子的第5跳:
跳转目标的前6位是:000000,因为跳转后面指令地址的高6位是000000。
接下来的26位是跳转指令的最低26位,即00000000000000000000001000
最后2位是:00,因为总是附加。
我们共同拥有:0000000000000000000000000000100000,这是十六进制20.并且该地址正是流程应该继续的标签/指令。
答案 1 :(得分:6)
在MIPS中,J
是J型指令:
J-type instructions (Jumps)
3 22
1 65 0
+----+-------------------------+
| op | target |
+----+-------------------------+
所以我们有一个26位长的target
。它与下一条指令的PC结合如下:
I
I+1 PC <- (PC & 0xf0000000) | (target << 2)
它向左移2位,因为MIPS指令(忽略MIPS16扩展)长度为32位,这意味着它们都从低2位为零的地址开始。