web-dev-qa-db-ja.com

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で始まり、最後の数字はジャンプ命令の行き先を示しているように見えます。しかし、この数がどのように計算されるのか理解できません。また、5回目のジャンプが後方ジャンプであることを私に示すものは何もありません。

ジャンプ値はどのように計算されますか?

7
node ninja

オペコードエンコーディングの詳細については、リファレンスマニュアルをご覧ください。

ショートバージョン:32ビット命令では、32ビットジャンプ先を含めることはできません。オペコードは6ビットを使用し、命令用に26ビットを残します。ターゲットアドレスは、j命令に続く命令のアドレスの最初の4ビットを取得することによって構築され、次に2つのゼロビットがジャンプ命令オペランドから26ビットに追加されます。 (命令は32ビットであるため、アラインメントは便利で、最後の2つの0を省略できます。)

後方ジャンプへ:アドレスは相対ではなく絶対であるため、前方ジャンプか後方ジャンプかに関係なく、ジャンプ命令のアドレスにのみ依存します。

[〜#〜] edit [〜#〜]:より詳細な説明:アドレスxジャンプ命令jtjのジャンプオペランドを表すとします。 tは26ビット幅です。次の命令のアドレスのビットパターンは次のように計算されます。

upper_6_bits_of(x+4),t,0,0

したがって、ジャンプは[〜#〜]常に[〜#〜]絶対です。相対的なジャンプはありません。結果がxより小さい場合は後方ジャンプ、大きい場合は前方ジャンプになります(そして、愚かなことをしたい場合は、等しくします;-)。

それでは、例の5番目のジャンプを見てみましょう。

ジャンプターゲットの最初の6ビットは000000です。これは、ジャンプの背後にある命令のアドレスの上位6ビットが000000であるためです。

次の26ビットは、ジャンプ命令の下位26ビット、つまり00000000000000000000001000です。

最後の2ビットは00です。これは、が常に追加されるためです。

一緒に:000000000000000000000000000000000100000、これは16進数の20です。そしてそのアドレスには、フローを続行するラベル/命令が正確にあります。

15
flolo

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)

MIPS命令(MIPS16拡張を無視)は32ビット長であるため、左に2ビットシフトされます。つまり、すべて下位2ビットがゼロのアドレスで開始されます。

6
ninjalj