Die J
Befehl codiert wird, wie folgt:
----------------------------
| opcode | instr_index |
----------------------------
instr_index
die niedrigstwertigen 28 Bits der Zieladresse ist, rechts um 2 verschoben, um Ihnen einen 26-Bit-Wert. Und die Adresse Sie Springen am Ende ist (PC & 0xF0000000) | (instr_index << 2)
Die BEQ
Variante kodiert wird, wie folgt:
-----------------------------
| opcode | 0 | 0 | offset |
-----------------------------
und die Adresse Sie Verzweigung am Ende zu ist PC + sign_extend(offset << 2)
.
(In beiden Fällen ist die Adresse der Anweisung unmittelbar nach der Verzweigung/Sprunganweisung, nicht die Sprung-/Sprunganweisung selbst). Jetzt
, lassen Sie uns sagen, dass Sie den folgenden Code haben:
main:
j foo
nop
foo:
Und dass dieser Code ist ursprünglich an der Adresse 0x00400024
geladen werden soll. Die Adresse foo
ist dann 0x0040002c
, und die J
-Anweisung wird als (2 << 26) | (0x0040002c >> 2)
= 0x0810000b
codiert.
Aber dann entscheiden Sie, dass Sie diesen Code verschieben (kopieren Sie es an einen anderen Speicherort im Speicher und führen Sie es an diesem Speicherort). Angenommen, Ihr Code wird jetzt unter 0x00410000
ausgeführt. In diesem Fall möchten wir, dass die Anweisung J
zu 0x00410008
springt, aber es springt immer noch zu 0x0040002c
((0x00410004 & 0xF0000000) | (0x010000b << 2)
= 0x0040002c
). Wenn Sie andererseits BEQ
verwendet hätten, hätten Sie das Befehlswort 0x10000001
((4 << 26) | (4 >> 2)
). Selbst wenn der Code verschoben wird, verzweigen Sie immer noch zur richtigen Adresse: 0x00410004 + (1 << 2)
= 0x00410008
.