MIPS-Prozessoren verwenden Größengrößenbefehle fester Größe, wobei jedes Befehlswort ein Wort ist (d. H. 4 Bytes == 32 Bits). Es gibt also nur so viele Informationen, die in diese 4 Bytes gepackt werden können.
Die Anweisungen J
und JAL
verwenden 6 der 32 Bits, um den Opcode anzugeben. Dies lässt 26 Bits übrig, um die Zieladresse zu spezifizieren. Die Zieladresse wird allerdings nicht direkt in dem Befehl spezifiziert (es sind nicht genügend Bits für das) - Statt dessen, was geschieht, ist dies:
- Die niedrigen 28 Bits der Zieladresse werden 2 Bits rechts verschoben, und dann werden die 26 niedrigstwertigen Bits in dem Befehlswort gespeichert. Da alle Anweisungen wortorientiert sein müssen, werden die zwei Bits, die wir herausgeschoben haben, immer Nullen sein, so dass wir keine Information verlieren, die wir nicht wiederherstellen können.
- Wenn der Sprung auftritt, werden diese 26 Bits um 2 Bits nach links verschoben, um die ursprünglichen 28 Bits zu erhalten, und dann werden sie mit den 4 höchstwertigen Bits der Adresse des Befehls nach dem
J
/JAL
kombiniert, um eine 32- Bitadresse.
Dies macht es möglich, in dem gleichen 256MB-Bereich (2^28) auf jede Anweisung zu springen, die der Sprungbefehl in befindet.
Für die Verzweigungsbefehle gibt es 16 Bits zur Verfügung um die Zieladresse anzugeben. Diese werden als vorzeichenbehaftete Offsets relativ zu dem Befehl gespeichert, der auf den Verzweigungsbefehl folgt (wiederum mit zwei angewendeten Bits der Verschiebung, da es nicht notwendig ist, etwas zu speichern, von dem wir wissen, dass es immer 0 ist). So ist der tatsächliche Offset nach der Wiederherstellung der 2 niedrigstwertigen Bits 18 Bits, der dann vorzeichenerweitert auf 32 Bits ist und zur Adresse des Befehls, der auf den Verzweigungsbefehl folgt, addiert wird. Dies macht es möglich, innerhalb des Verzweigungsbefehls auf +/- 128kB zu verzweigen.
Betrachten wir den folgenden Code an Adresse geladen 0x00400024:
main:
j foo
nop
foo:
b main
nop
Die j foo
Instruktion als 0x0810000b
codiert wird. Die 26 niedrigstwertigen Bits haben den Wert 0x10000b
, der nach dem Verschieben von 2 Bits nach links zu 0x40002c
wird. Die 4 höchstwertigen Bits der Adresse des Befehls, der auf j
folgt, sind Null, daher wird die Zieladresse , was 0x40002c
entspricht, was zufällig die Adresse foo
ist.
Die Anweisung b main
ist als 0x0401fffd
codiert. Die 16 niedrigstwertigen Bits haben den Wert 0xfffd
, was nach dem Verschieben von 2 Bits nach links zu 0x3fff4
wird. Sign-extending das auf 32 Bits gibt uns 0xfffffff4
.Und wenn wir das zu der Adresse der Anweisung hinzufügen, die der b
folgt, erhalten wir 0x400030 + 0xfffffff4
, die (wenn auf 32 Bits abgeschnitten) gleich 0x400024
ist, die zufällig die Adresse main
ist.
Wenn Sie zu einer beliebigen Adresse springen wollen, laden Sie die Adresse in ein Register und verwenden Sie die jr
oder jalr
Anweisung zu springen.
Warum fügen wir 4 höchstwertige Bits der Adresse des Befehls, d. H. PC, zur Sprungadresse von (26 Bits) hinzu. Wie bedeuten diese 4 sig Bits? Und warum nur die ersten 4 Bits. – hsnsd
@hsnsd: Siehe meine Antwort: _ "Wenn der Sprung auftritt, werden diese 26 Bits um 2 Bits nach links verschoben, um die ursprünglichen 28 Bits zu erhalten, und dann werden sie mit den 4 höchstwertigen Bits der Adresse des Befehls nach dem" J'/'JAL' zur Bildung einer 32-Bit-Adresse" _. So funktioniert die Anweisung. – Michael