MIPS汇编中的跳转指令

时间:2011-10-24 14:43:17

标签: assembly mips

这是我编写的一些用于测试跳转指令的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开头,最后的数字告诉跳转指令去哪里。但是,我无法弄清楚这个数字是如何计算出来的。此外,没有什么可以向我表明第五跳是向后跳跃。

如何计算跳跃值?

2 个答案:

答案 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位为零的地址开始。