2016-12-18 4 views
1

Ich habe einen Auftrag, in dem ich einige Dinge über den folgenden MIPS Assembler-Code zu erklären:MIPS Assembly, lui 0x1001

.data 
x: .word 4711 
y: .word 10 
z: .word 0x0A91 
e: .word 0 

.text 
.globl main 
main: 
lw $2, x 
lw $3, y 
lw $4, z 
add $2, $2, $3 
sub $3, $2, $4 
sw $3, e 
li $2, 10 
syscall 

Der erste Befehl lw $2, x in zwei Anweisungen getrennt wird, wenn montiert. Die Anweisungen sind lui $1, 0x00001001 gefolgt von lw $2, 0x00000000($1). Ich verstehe, dass lui den Hex-Wert 1001 in den oberen Teil des Registers verschiebt und der in $ 1 gespeicherte Wert 0x10010000 ist, aber ich verstehe nicht, woher der 1001 kommt und was der zweite Befehl überhaupt bedeutet. Ich würde wirklich jede Hilfe zu diesem Thema schätzen. Ich benutze MARS, um dieses Programm zusammenzustellen und auszuführen.

+0

'0x10010000' die Adresse des 'X' sein geschieht. – Jester

+0

Oh, ok Dann danke – Max

Antwort

2

MIPS-Anweisungen sind 32 Bits lang, und so werden die Adressen von einem Programm verwendet.
Das bedeutet, dass die Anweisung lw keine vollständige 32-Bit-Adresse als Sofortadresse angeben kann. Einfach gesagt, die Anweisung lw $t, var ist nicht gültig (für sehr wenige Fälle zu erwarten).

In der Tat, seine Codierung ist

lw $t, offset($s) 
1000 11ss ssst tttt iiii iiii iiii iiii 

Wo der i Bits zeigt, dass nur 16 Bits eine Adresse (und das ein Basisregister angeben werden verwendet, muss immer angegeben werden, schließlich die $zero Register können verwendet werden).

So hat der Monteur diesen Trick: wenn Sie ein verwenden lw $t, var es diese Anweisung in zwei Anweisungen montiert, eine, die die oberen 16 Bits der Adresse in $at und ein lw laden, die $at als Basisregister mit dem Einsatz untere 16 Bits der Adresse als Offset.

lui $at, ADDR_H   #ADDR_H is ADDR >> 16 
lw $t, ADDR_L($at)   #ADDR_L is ADDR & 0xffff 

anzumerken, dass, da die lw liest aus $at + ADDR_L die Endadresse verwendete ADDR_H < < 16 + ADDR_L = ADDR. Wie erwartet.

Es Subtilität ist hier, von Mike Spivey (ihm Vielen Dank) wies darauf hin, siehe unten

Diese Art von Anweisungen, die nicht direkt in die ISA abbildet, sind pseudo- genannt Anweisung. Das $at Register ist für den Assembler genau für die Implementierung reserviert.


In MARS Sie die Pseudo-Anweisungen von unchecking Einstellungen deaktivieren> erweitert Erlaubnisse (pseudo) Anweisungen und Format.
Während das Programmieren ohne Pseudobefehle ziemlich schnell ärgerlich wird, lohnt es sich mindestens einmal, die MIPS-Architektur vollständig zu verstehen.


Mike Spivey korrekt festgestellt, dass die 16-Bit-Immediate-Offset vorzeichenerweitert ist bevor zu dem Basisregister addiert wird.
Dies erfordert eine Korrektur des Werts, den ich genannt habe, falls ADDR_L negativ ist, wenn er als 16-Bit Zweierkomplementnummer interpretiert wird.
Wenn sich dies als wahr herausstellt, muss ADDR_H inkrementiert werden.
Die allgemeine Formel für ADDR_H kann ADDR_H = ADDR >> 16 + ADDR[15] korrigiert werden, in dem ADDR[15] den Wert von Bit 15 von ADDR bezeichnet (die das Vorzeichenbit ADDR_L ist.

+0

Ein kleiner Fehler: der Offset in einer lw-Anweisung ist signiert, daher ist es nicht korrekt, ADDR_H mit einer Verschiebung allein zu berechnen.Wenn ADDR_L negativ wird, muss ADDR_H um 1 erhöht werden.Der Assembler sieht zu natürlich nach dem. –

+0

@MikeSpivey Vielen Dank! Das ist ein sehr guter Punkt! Ich glaube, es genügt, Bit15 der ursprünglichen Adresse zu ADDR_H hinzuzufügen, um es zu beheben. Ich bearbeite die Antwort. –

+0

Wann Ich schreibe einen MIPS-Assembler, ich gebe kurz ADDR_L = (kurz) ADDR; kurz ADDR_H = (ADDR - ADDR_L) >> 16; assert (ADDR == ADDR_H << 16 + ADDR_L); was zur gleichen Sache kommt. –

Verwandte Themen