Post on 20-Oct-2019
208 4 Prozessor-Datenpfad
d) Schreiben Sie für den Universalrechner ein Programm in Assembler-Sprache,
welches den Radius eines Kreises vom Eingang 0 einliest, die Fläche des Kreises
berechnet und das Ergebnis in Register R0 ablegt. Verwenden Sie für ⇡ den Wert
3,141592 in der angegebenen Genauigkeit.
4.3 Assembler 209
T e) Schreiben Sie für den Universalrechner ein Programm in Assembler-Sprache,
welches die Längen der beiden Katheten eines rechtwinkligen Dreiecks über die
Eingänge 0 und 1 einliest, die Länge der Hypothenuse berechnet und das Ergebnis
im Register R0 ablegt
T f) Schreiben Sie für den Universalrechner ein Programm in Assembler-Sprache,
welches den Radius eines Kreises vom Eingang 0 einliest, den Umfang des
Kreises berechnet und das Ergebnis in Register R0 ablegt. Verwenden Sie für ⇡
den Wert 3,141592 in der angegebenen Genauigkeit.
210 4 Prozessor-Datenpfad
Assembler als Übersetzer
Um ein Assembler-Programm für den Universalrechner zu übersetzen, iteriert der As-
sembler der Reihe nach über alle Programmzeilen und führt für jede Zeile folgendes aus:
• Wenn die Programmzeile ‘‘leer’’ ist (nur Leerzeichen, Tabulatorzeichen und
Zeilenumbruch-Zeichen enthält), wird die Zeile ignoriert.
• Wenn die Programmzeile nicht leer ist,
• wird das erste Wort (alle Zeichen bis zum ersten Leerzeichen oder
Tabulator) als Befehls-Zeichenkette interpretiert und das zweite Wort
als Operanden-Zeichenkette; die Operanden-Zeichenkette wird bei
den Kommas in zwei bzw. drei Operanden aufgetrennt;
• entspricht die Befehls-Zeichenkette der Zeichenkette ‘‘INPUT’’, wird
• vom erste Operanden das ‘‘R’’ entfernt, das übrigbleibende
Zeichen in eine Zahl gewandelt und diese im Befehlswort als
D abgespeichert (z.B. D = 001 für R1, D = 010 für R2, ...)
• der zweite Operand im Befehlswort als M1 abgespeichert
(z.B. M1 = 00, falls zweiter Operand den Wert 0 hat)
• entspricht die Befehls-Zeichenkette den Zeichenketten ‘‘ADD’’ oder
‘‘SUB’’ oder ‘‘MUL’’ oder ‘‘DIV’’, wird
• von den drei Operanden das ‘‘R’’ entfernt und die übrig
bleibenden Zahlen im Befehlswort als D (erster Operand),M3
(zweiter Operand) und M4 (dritter Operand) abgespeichert,
und
• der Wert von M2 bei ‘‘ADD’’ auf 0012 gesetzt, bei ‘‘SUB’’ auf
0102, bei ‘‘MUL’’ auf 0112, bei ‘‘DIV’’ auf 1002, und
• M1 auf 112 gesetzt;
• entspricht die Befehls-Zeichenkette der Zeichenkette ‘‘SQRT’’, wird
• von beiden Operanden das ‘‘R’’ entfernt und die übrig blei-
benden Zahlen im Befehlswort als D (erster Operand) bzw.
M4 (zweiter Operand) abgespeichert
• M2 auf 1012 und
• M1 auf 112 gesetzt;
4.3 Assembler 211
• entspricht die Befehls-Zeichenkette der Zeichenkette ‘‘SET’’, wird
• vom ersten Operanden das ‘‘R’’ entfernt und die übrig blei-
bende Zahl im Befehlswort als D abgespeichert
• der zweite Operand in K abgespeichert (z.B. 00000000012 für
1 oder 11111111112 für �1
• M2 auf 0002 und
• M1 auf 112 gesetzt.
Neben dieser Grundfunktionalität würde ein richtiger Assembler auch noch diverse
Fehlerüberprüfungen durchführen, beispielsweise ob nur gültige Befehle und Operanden
verwendet wurden, ob alle Operanden angegeben sind, ob das Format der Operanden
stimmt, ob die Konstanten nicht zu groß sind etc. Das Grundprinzip jedoch ist immer
das selbe: Assembler-Programme werden durch eine eindeutige Abbildungsregel in
Befehlsworte übersetzt.
Betrachten Sie die folgende Codesequenz:
INPUT R0,0MUL R0,R0,R0INPUT R1,1MUL R1,R1,R1ADD R0,R0,R1SQRT R0,R0
Befehlsformat: K (10 Bit) – D (3 Bit) – M4 (3 Bit) – M3 (3 Bit) – M2 (3 Bit) – M1 (2 Bit)
a) Übersetzen Sie das Programm in Befehlsworte des Universalrechners mit Hilfe
obiger Übersetzungsregeln. Geben Sie für alle irrelevanten Bits ‘‘x’’ an
212 4 Prozessor-Datenpfad
Betrachten Sie die folgende Codesequenz:
MUL R0,R0,R1SET R1,255DIV R1,R0,R2ADD R1,R1,R3
b) Übersetzen Sie das Programm in Befehlsworte des Universalrechners mit Hilfe
obiger Übersetzungsregeln. Geben Sie für alle irrelevanten Bits ‘‘x’’ an
Betrachten Sie die folgende Codesequenz:
SET R0,0INPUT R1,0ADD R0,R0,R1INPUT R1,1ADD R0,R0,R1INPUT R1,2ADD R0,R0,R1SET R1,3DIV R0,R0,R3
T c) Übersetzen Sie das Programm in Befehlsworte des Universalrechners mit Hilfe
obiger Übersetzungsregeln. Geben Sie für alle irrelevanten Bits ‘‘x’’ an
4.3 Assembler 213
Betrachten Sie den Datenpfad des Universalrechners.
SUBb
aa-b
MUL
ADD
DIVb
aa/b
0123
76543
0123
1234
210
0123
76543210
0123
0123
D11
3
D6D5 3
D3D2 3
A7
A0
…
D1D0 2
M1
M4
M3
M2
a
b
c
Add1 0
1
clk
reset
0123
76543210
D13D12
R7
R6
R5
R4
R3
R2
R1
R0
3
0
M1
M2
M3
M4
D10
BZ
pX
5
M3A2
A1
M4
M2
M1
M0
D4
D7D8
D10D9
D23
D14
D
R K…
0
MSB…
10 10
n-10
n
214 4 Prozessor-Datenpfad
Gegeben ist folgende Codesequenz:
SET R0,5INPUT R4,2ADD R0,R0,R1DIV R7,R0,R1
d) Übersetzen Sie das Programm in Befehlsworte des Universalrechners lediglich mit
Hilfe des Datenpfads (ohne Übersetzungsregeln). Geben Sie für alle irrelevanten
Bits ‘‘x’’ an
Gegeben ist folgende Codesequenz:
SET R1,2SQRT R2,R1INPUT R2,1MUL R5,R0,R1
T e) Übersetzen Sie das Programm in Befehlsworte des Universalrechners lediglich mit
Hilfe des Datenpfads (ohne Übersetzungsregeln). Geben Sie für alle irrelevanten
Bits ‘‘x’’ an
215
5 Befehlssätze und deren Klassifikation
Befehlssatz
Unser Universalrechner kennt 7 verschiedene Befehle: ADD, SUB, MUL, DIV, FSQRT, INPUTund SET. Die Menge (im mathematischen Sinne) der Befehle, die ein Prozessor versteht,
nennt man auch den Befehlssatz (Satz im Sinne von Menge; engl.: instruction set) des
Prozessors. Befehlssätze lassen sich in mehrfacher Hinsicht klassifizieren.
Klassifikation nach Komplexität
CISC = Complex Instruction Set Architecture
CISC-Befehlssätze enthalten sehr mächtige, ‘‘komplexe’’ Befehle, um mit möglichst
wenig Assembler-Code viel zu erreichen. Beispiel: Laden von zwei Operanden aus dem
Speicher, Multiplikation der Operanden, Abspeichern des Ergebnisses im Speicher als
ein Befehl. Dieses Prinzip war in den 1970er-Jahren gängig, da die verfügbaren Speicher
sehr klein waren und so weniger Platz benötigt wurde. Zudem gab es noch keine
(vernünftigen) Compiler, d.h. Programme wurde in Assembler-Sprache geschrieben.
Durch die mächtigen Befehle ging das Programmieren schneller, da sich die Befehle
fast wie eine Hochsprache verhielten. Durch die Unterschiedlichkeit der Befehle ist das
Befehlswort bzgl. der Länge variabel, d.h. die Befehlswortbreite schwankt je nach Befehl
z.B. zwischen 1 und 16 Byte.
RISC = Reduced Instruction Set Architecture
Bei RISC-Befehlssätzen ist die Mächtigkeit der Befehle stark reduziert. Komplexe Opera-
tionen werden durch mehrere einfache Befehle gelöst, statt durch einen sehr mächtigen
Befehl. Beispiel Multiplikation zweier im Speicher liegender Zahlen:
• 2 Lade-Befehle, um Operanden vom Speicher in Register zu laden
• 1 Multiplikation-Befehl, der zwei Register-Werte multipliziert und das Ergebnis
wieder in einem Register abspeichert
• 1 Speicher-Befehl, um das Ergebnis vom Register in den Speicher zu schreiben
Durch Compiler und Programmierung in Hochsprache ist die Mächtigkeit einzelner Be-
fehle nicht mehr ausschlaggebend für die Programmiereffizienz. Durch die Verfügbarkeit
größerer Speicher besteht keine Notwendigkeit mehr, Speicher durch mächtige Befehle
zu sparen.
Die Befehle eines RISC-Prozessors haben in der Regel alle die selbe Befehlswortlänge
bzw. nur wenige verschiedene Wortbreiten. Beispiel: 4 Byte für Speicherbefehle und
216 5 Befehlssätze und deren Klassifikation
2 Byte für alle anderen Befehle. Das macht die Hardware einfacher und damit auch
schneller.
Klassifikation nach Verortung der Operanden
Register-Speicher-Architektur
Bei einer Register-Speicher-Architektur können die Operanden der Befehle sowohl in
Registern, als auch im Speicher stehen.
Register-Register-Architektur/Load-Store-Architektur
Bei Register-Register-Architekturen müssen Quell- und Zieloperand in Registern stehen.
Quelloperanden, die im Speicher stehen, müssen zunächst mit einem Lade-Befehl (engl.
load instruction) vom Speicher in ein Register geladen werden, bevor sie verarbeitet
werden können. Soll das Ergebnis eines Befehls im Speicher abgelegt werden, so
muss das Ergebnis zunächst in einem Register abgelegt werden, bevor es mit einem
Speicher-Befehl (engl. store instruction) vom Register in den Speicher geschrieben
werden kann.
Da Speicherzugriffe nur über Lade- und Speicher-Befehle erfolgen, nenn man Register-
Register-Architekturen auch Load-Store-Architekturen.
Klassifikation nach der Anzahl der Operanden
Drei-Adress-Maschine
Bei einer Drei-Adress-Maschine können bis zu zwei Quell- und ein Zieloperand explizit
angegeben werden. Da das bei unserem Universalrechner ebenfalls möglich war, ist
unser Universalrechner eine Drei-Adress-Maschine.
Beispiel: ADD R0,R1,R2 , addiere Register R1 zum Register R2 und speichere das
Ergebnis in Register R0 ab.
Zwei-Adress-Maschine
Bei einer Zwei-Adress-Maschine ist ein Quell-Operand gleichzeitig auch Zieloperand.
Beispiel: ADD R0,R1, addiere Register R0 zum Register R1 und speichere das Ergebnis
in Register R0 ab.
Ein-Adress-Maschine/Akkumulator-Maschine
Bei einer Ein-Adress-Maschine wird nur ein einziger Quell-Operand angegeben. Zweiter
Quell-Operand und Ziel-Operand ist implizit immer das sog. Akkumulator-Register.
Beispiel: ADD R1 , addiere Register R1 zum Akkumulator-Register und speichere das
Ergebnis wieder im Akkumulator-Register ab.
217
Null-Adress-Maschine/Stack-Maschine
Bei einer Null-Address-Maschine muss bei einer Operation kein Operand angegeben
werden, da als Operand immer implizit die auf einem Stack oben liegenden Werte
verwendet werden. Das Ergebnis wird wieder auf dem Stack abgelegt. Beispiel:
push 3push 4add
Zunächst wird die Zahl 3 auf dem Stack abgelegt, danach die Zahl 4. Anschließend
werden beide Zahlen addiert. Das Ergebnis wird wieder auf dem Stack abgelegt.
218 6 MMIX-Prozessor
6 MMIX-Prozessor
In diesem Kapitel beschäftigen wir uns mit dem MMIX-Prozessor. Der MMIX-Prozessor
wurde von Donald Ervin Knuth zu Lehr- und Forschungszwecken an der Stanford Uni-
versity entwickelt. Donald Knuth ist Mathematiker und ein berühmter Computer-Pionier.
Von ihm stammen unter anderem die berühmten Bücher ‘‘The Art of Computer Pro-
gramming’’ sowie das Text-Satzsystem TEX, ein Vorfahre von LATEX, mit dem z.B. dieses
Skript erstellt wurde. Für mehr Infos, siehe http://www-cs-faculty.stanford.edu/~uno/.
‘‘MMIX’’ steht für die römische Zahl 2009, die sich alsMittelwert mehrerer RISC-Rechner-
Kennzahlen ergibt: (CrayI + IBM801 + RISCII + ClipperC300 + AMD29K + Motorola88K
+ IBM601 + In-teli960 + Alpha21164 + POWER2 + MIPSR400 + HitachiSuperH4 +
StrongARM110 + Sparc64) / 14 = 28126 / 14 = 2009.
MMIX ist ein Prozessor-Modell, d.h. kein real existierender Prozessor. Damit gibt es
keine Legacy-Effekte aufgrund gewünschter Rückwärtskompatibilitäten, was nicht nur
die Programmierung, sondern auch die Implementierung des Prozessors sehr einfach
und verständlich macht. Simulations-Tools zum MMIX-Prozessor können von der LDV-
Webseite heruntergeladen werden.
Der MMIX ist eine Register-Register-Architektur mit 256 Allzweck-Registern und 32
Spezial-Registern. Die Wortbreite beträgt 64 Bit (Register, Rechenwerk, Daten- und
Adress-Busse), der Adressbereich umfasst 264 Byte. Der Befehlssatz umfasst 256
Befehle. Für alle Befehle beträgt die Befehlswortlänge 32 Bit. Donald Knuth gibt für die
Ausführungszeit der meisten Befehle 1 Takt an, was typisch für RISC-Prozessoren ist.
Diese Ausführungszeit bezieht sich jedoch auf den von Donald Knuth erstellten Simulator
und nicht auf die von uns entwickelte Datenpfad-Realisierung.
6.1 Programmiermodell 219
6.1 Programmiermodell
ALU
32 Spezialregister 256 Allzweckregister Speicher
OP32 Bit Befehlswort
X Y Z
8, 16, 24 Bit
64 Bit
PUT
GET
LDx
STx
8, 16, 32, 64 Bit
64 Bit64 Bit
64 Bit 64 Bit 8 Bit
0
31
0
1 1
264 - 1
0
255
1
STCO
• Die Operanden, die vom Rechenwerk (ALU = Arithmetic Logic Unit) verarbeitet
werden, entstammen entweder den Allzweckregistern (64 Bit Wortbreite) oder
direkt dem Befehlswort (Direktoperand; 8, 16, 24 Bit).
• Ein vom Rechenwerk berechnetes Ergebnis (Zieloperand) wird immer in einem
Allzweckregister abgelegt.
• Daten aus dem Speicher müssen erst mit Ladebefehlen (LDx) in ein Allzweckre-
gister geladen werden, bevor Sie vom Rechenwerk verarbeitet werden können.
• Daten können mit Speicherbefehlen (STx) von einem Allzweckregister in den
Speicher geschrieben werden.
• Die Wortbreite für Speicherzugriffe beträgt 8, 16, 32 oder 64 Byte. Für jede
Wortbreite gibt es einen eigenen Lade- bzw. Speicherbefehl, was mit dem ‘‘x’’
bei ‘‘LDx’’ bzw. ‘‘STx’’ gekennzeichnet ist.
• Der Zugriff auf die Spezialregister erfolgt mit PUT (vom Allzweckregister ins
Spezialregister schreiben) bzw. mit GET (Daten vom Spezialregister in ein
Allzweckregister einlesen).
• Mit dem STCO-Befehl können 8 Bit breite Operanden vom Befehlswort in den
Speicher geschrieben werden.
220 6 MMIX-Prozessor
6.2 RegisterDie Register sind kleine, jedoch sehr schnelle Speicherelemente, die im Prozessor-Kern
untergebracht sind. Die Wortbreite der Register entspricht typischerweise der Breite
der Datenworte, die vom Prozessor verarbeitet werden können. Beim MMIX sind die
Register 64 Bit groß.
Allzweckregister
Allzweckregister (engl. general purpose register) sind Register, die keinen bestimmten
Zweck haben, sondern universell verwendet werden können. Gemeint ist, dass diese
Register als Operanden für alle Befehle verwendet werden können. Es gibt bei Allzweck-
registern also keine festgelegte Bindung zwischen einem bestimmten Register und einer
bestimmten auszuführenden Operation (z.B. Festkomma-Addition, Basis-Adresse für
Speicherzugriff, ...).
Die 256 Allzweckregister des MMIX haben keine besonderen Namen, sondern werden
von 0 bis 255 durchnummeriert und über diese Nummer angesprochen. Um Regis-
ter von Zahlen unterscheiden zu können wird der Registernummer ein Dollarzeichen
vorangestellt. $0 meint also den Inhalt von Register 0, während 0 die Zahl 0 meint.
Computerprogramme verwenden sowohl globale als auch lokale Variable: Globale
Variable können von allen Programmteilen verwendet werden, lokale nur von einem
Teilausschnitt, z.B. einer Funktion. Beim MMIX werden lokale Variable in den unteren
Allzweckregistern ($0, $1, ... = lokale Register) und globale Variable in den oberen
Allzweckregistern ($255, $254, ... = globale Register) abgelegt. Die dazwischen liegenden
unbenutzten Register werden beim MMIX marginale Register genannt.
Die Nummer des ersten freien lokalen Registers ist in Spezialregister rL abgelegt, die
Nummer des ersten globalen Registers in Spezialregister rG.
Globale Register
Lokale Register
Marginale Register
$0
$255
$(rG)
$(rL)
t
6.2 Register 221
Spezialregister
Spezialregister (engl. special purpose registers) haben im Gegensatz zu Allzweckregis-
tern einen bestimmten Zweck, d.h. jedes Spezialregister hat seine ganz eigene Aufgabe.
Spezialregister können als eine Art Schnittstelle zwischen Hardware und Software ange-
sehen werden, die es der Software ermöglicht, bestimmte Hardware-Einstellungen vor-
zunehmen (z.B. Setzen von Taktfrequenz-Multiplikatoren, Konfiguration von Interrupts,
...) oder aufgetretene Ereignisse (z.B. Division durch 0, Zeitablauf bei Timer-Interrupt, ...)
durch die Software erfassbar/auswertbar zu machen.
Der MMIX-Prozessor hat 32 Spezialregister, die rA, rB, rC, ... rZ, rBB, rTT, rWW rXX,rYY und rZZ genannt werden. Zugriff auf die Spezialregister ist bei MMIX nur über die
Befehle PUT (Wert von Allzweckregister in Spezialregister kopieren) und GET (Wert von
Spezialregister in Allzweckregister kopieren) möglich.
Nachfolgende Abbildung zeigt das Spezialregister rA, das Arithmetische Status Register.
0 0 R1 R0 D V W I O U Z X D V W I O U Z X
Interrupt Enable (Freischalten) Interrupt Event (Auftreten)
Gleitkommazahl ungenau (z.B. 1.0 / 3.0)Gleitkomma-Division durch 0Gleitkomma-UnterlaufGleitkomma-ÜberlaufUnerlaubte Gleitkomma- operation, z.B. sqrt(-1.0)Überlauf bei Wandlung Gleit- komma- in FestkommazahlFestkomma-ÜberlaufFestkomma-Division durch 0
00: Nächster Wert (standard)01: Abrunden (Richtung 0)10: Aufrunden (Richtung +∞)11: Abrunden (Richtung -∞)
nicht verwendet
Gleitkomma-Rundungsmodus
Beispiele für weitere Spezialregister:
• Im Falle einer Multiplikation 64 Bit · 64 Bit = 128 Bit werden in rH die oberen 64
Bit des Ergebnisses abgelegt.
• Im Falle einer Division 128 Bit : 64 Bit = 64 Bit werden in rD die oberen 64 Bit
des 128 Bit breiten Dividenden abgelegt.
• Bei einer Festkomma-Division wird in rR der Rest der Division abgelegt (Modulo-
Operation).
222 6 MMIX-Prozessor
Verständnisfragen/Aufgaben
Allgemein
T a) Was ist ein Register?
T b) Wo findet man Register in einem Computer-System?
T c) Daten welcher Größenordnung kann ein Register aufnehmen: Byte, kilobytes,
megabytes, gigabytes or terabytes?
Allzweckregister
a) Was sind Allzweckregister?
b) Geben Sie ein Beispiel für eine typische Verwendung eines Allzweckregisters an.
c) Über wieviele Allzweckregister verfügt derMMIX-Prozessor?WelcheNamen haben
sie?
6.2 Register 223
T d) Was ist der Unterschied zwischen einem globalen und einem lokalen Register?
Spezialregister
a) Was ist ein Spezialregister?
b) Geben Sie eine typische Anwendung eines Spezialregisters an.
T c) Über wieviele Spezialregister verfügt der MMIX-Prozessor? Wie werden sie ge-
nannt (Prinzip)?
T d) Kann jeder MMIX-Befehl Spezialregister verwenden?
T e) Welches Spezialregister stellt Informationen über Arithmetische Operationen zur
Verfügung?
T f) In welchem Spezialregister kann man die oberen 64 Bit eines 128 Bit breiten
Festkomma-Dividenden ablegen?
224 6 MMIX-Prozessor
T g) In welchem Register werden die oberen 64 Bit des Ergebnisses einer Festkomma-
Multiplikation abgelegt?
T h) In welchem Spezialregister legt das Rechenwerk den Rest einer Festkomma-
Division ab?
i) Müssen ‘‘normale’’ Programme häufig auf Spezialregister zugreifen?
j) Was müssen Sie tun, wenn Sie einzelne Bits eines Spezialregisters verändern
wollen?
Die letzte Aufgabe hat gezeigt, dass zur Bearbeitung von Spezialregistern zwei zusätzli-
che Befehle ausgeführt werden müssen. Diese Ausführung kostet Zeit.
k) Können Sie sich einen Grund vorstellen, warum nicht alle MMIX-Befehle in Spezi-
alregister schreiben bzw. Spezialregister lesen können?
6.3 Speicher 225
6.3 SpeicherDer Speicher desMMIX ist Byte-adressiert, d.h. das kleinste adressierbare Datenelement
ist ein Byte (8 Bit).
Wortbreiten
Das Speichern (Allzweckregister ! Speicher; engl. store) bzw. Laden (Speicher !Allzweckregister; engl. load) wird in folgenden Wortbreiten unterstützt:
• 1 Byte (8 Bit)
• 2 Byte (16 Bit), beim MMIX Wyde genannt,
• 4 Byte (32 Bit), beim MMIX Tetra genannt,
• 8 Byte (64 Bit), beim MMIX Octa genannt.
Ausrichtung der Daten im Speicher - Alignment
Bei Speichermodulen sind die einzelnen Byte in der Regel auf mehrere Speicherchips
verteilt, bei einer Wortbreite von 64 Bit kann ein Speichermodul (ohne Speicherung von
Paritätsbits) beispielsweise aus 16 Chips zu je 4 Bit oder 8 Chips zu je 8 Bit aufgebaut
sein.
Betrachten Sie das nachfolgende (einseitige) Speichermodul, in dem 64 Bit breite
Datenworte aus 8 Speichermodulen zu je 8 Bit aufgebaut werden (es werden keine
Paritätsbits betrachtet).
0 1 2 3 4 5 6 7
• Bei Zugriffen auf ein einzelnes Byte wird nur auf einen einzigen Speicherchip
zugegriffen. Dabei können die letzten drei Adressbits dazu verwendet werden,
den Speicherchip auszuwählen und die übrigen Adressbits wählen dann eine
Adresse innerhalb des ausgewählten Chips aus.
• Bei Zugriffen auf 16 Bit breite Datenworte wählen die Adressbits 1 und 2 (das
Adressbit 0 wird nicht ausgewertet) eine der vier Speicherchip-Gruppen (0,1),
(2,3), (4,5) oder (6,7) aus. Die übrigen Adressbits (ab 3 aufwärts) wählen dann
eine Adresse innerhalb der ausgewählten Chips aus. Das 16 Bit Datenwort setzt
sich dann aus den 2 · 8 Bit der ausgewählten Speicherchip-Gruppe zusammen.
A does se
iwhip Chipus m
. - - 0000
-- O O O A
÷ ::: :\. . +-- 0100 -00€
-- Oro A
f 8- or co
. - - o re A II-
-10O O
-. 10,0 A
(
I
32 - - 32
→ ②t 32
226 6 MMIX-Prozessor
• Bei Zugriffen auf 32 Bit breite Datenworte wählt das Adressbit 2 (Adressbits
0 und 1 werden ignoriert) eine der zwei Speicherchip-Gruppen (0,1,2,3) oder
(4,5,6,7) aus. Die Adressbits 3, 4, 5, ... wählen eine Adresse innerhalb der
ausgewählten Chips aus. Das 32 Bit Datenwort setzt sich dann aus den 4 · 8 Bit
der ausgewählten Speicherchip-Gruppe zusammen.
• Bei Zugriffen auf 64 Bit breite Datenworte werden die Adressbits 0, 1 und 2
ignoriert. Die übrigen Adressbits wählen eine Adresse innerhalb der ausgewähl-
ten Chips aus. Das 64 Bit breite Datenwort setzt sich dann aus den 8 · 8 Bit der
ausgewählten Speicherchip-Gruppe zusammen.
Aus mehreren Byte zusammengesetzte Daten werden also idealerweise so im Speicher
ausgerichtet (engl. aligned), dass auf sie gemäß obigem Schema mit nur einem einzigen
Speicherzugriff zugegriffen werden kann.
Datenworte können prinzipiell natürlich auch anders abgelegt werden, bspw. kann ein 32
Bit breites Datenwort auch auf die Chips 1, 2, 3 und 4 verteilt werden. Der Nachteil hierbei
ist jedoch, dass die Daten dann durch die Verdrahtung auf dem Speichermodul nicht
automatisch richtig zusammengesetzt werden, sondern entweder durch zusätzliche
Hardware oder durch Software-Befehle richtig zusammengefügt werden müssen. Aus
diesem Grund werden aus mehreren Byte zusammengesetzte Datenworte in der Regel
immer in der beschriebenen Weise ausgerichtet, sind also immer ‘‘aligned’’.
Der MMIX unterstützt das beschriebene Alignment, indem er durch Löschen der nieder-
wertigsten Adressbits die Menge gültiger Wortadressen wie folgt einschränkt:
0x0000000000000002
0x00000000000000070x0000000000000006
0x0000000000000004
0x00000000000000090x0000000000000008
0x0000000000000003
0x000000000000000A
0x00000000000000000x0000000000000001
0x0000000000000005
OctaX
X
X
X
X
TetraWyde
X
X
X
X
X
X
Byte
XXXXXXXXXXX
… … … … …
6.3 Speicher 227
Das bedeutet:
• Bytes können an jeder Adresse abgelegt werden,
• Wydes können nur an Adressen abgelegt werden, die ein Vielfaches von 2 sind,
• Tetras können nur an Adressen abgelegt werden, die ein Vielfaches von 4 sind,
• Octas können nur an Adressen abgelegt werden, die ein Vielfaches von 8 sind.
Big- und Little Endian
Die Ausrichtung der Daten im Speicher (Alignment) beschreibt die Byte-Adressen, an
denen aus mehreren Byte zusammengesetzte Datenworte abgelegt werden können. Ein
32 Bit breites Datenwort beginnt beispielsweise an einer durch 4 teilbarer Adresse und
nimmt noch die nächsten vier Byte ein.
Damit ist jedoch noch keine Aussage über die Adressen innerhalb der Menge der erlaub-
ten Byte-Adressen getroffen, an der die verschiedenen Byte eines Datenworts abgelegt
werden. Sollen die Byte eines aus mehreren Byte zusammengesetzten Datenworts der
Reihe nach im Speicher abgelegt werden, gibt es zwei Möglichkeiten:
• Durch die (gültig ausgerichtete) Wort-Adresse wird das höherwertigste Byte
adressiert. Das nennt man Big Endian.
• Durch die (gültig ausgerichtete) Wort-Adresse wird das niederwertigste Byte
adressiert. Das nennt man Little Endian.
Beispiele für Big-Endian Prozessoren sind MMIX, MIPS, SPARC, Atmel AVR32 etc.,
Beispiele für Little-Endian-Prozessoren sind Intel x86, Renesas SH, ...
Beispiel: 32 Bit Zahl 0x01234567 an Adresse 0x0000 0000 0000 0000:
0x010x23
0x670x450x0000000000000002
0x00000000000000010x0000000000000000
0x0000000000000003
0x670x45
0x010x23
Big Endian Little Endian
228 6 MMIX-Prozessor
Speicherorganisation
Die Adressbreite des MMIX beträgt 64 Bit, d.h. der MMIX kann 264 Byte adressieren,
von 0x0000 00000000 0000 bis 0xFFFFFFFFFFFFFFFF. Dieser Speicherbereich wird
wie folgt aufgeteilt:
0x0000 0000 0000 0000= Text_Segment
Text-Segment0x0000 0000 0000 00FF0x0000 0000 0000 0100
0x1FFF FFFF FFFF FFFF
Daten-Segment0x2000 0000 0000 0000
= Data_Segment
0x3FFF FFFF FFFF FFFF
Pool-Segment0x4000 0000 0000 0000
= Pool_Segment
0x5FFF FFFF FFFF FFFF
Stack-Segment0x6000 0000 0000 0000
= Stack_Segment
0x7FFF FFFF FFFF FFFF
Betriebssystem-Segment
0x8000 0000 0000 0000
0xFFFF FFFF FFFF FFFF
Globale Variable (Heap)
Lokale Variable, Stack
MMIX-Befehle
Interrupt-Vektoren
Text-Segment: Programme und Interrupt-Vektoren
Im Text-Segment wird ausführbarer Befehlscode als aufeinander folgende Befehlsworte
abgelegt. Da alle Befehlsworte 4 Byte breit sind, beginnen die Befehlsworte immer an
einer durch 4 teilbaren Adresse.
MMIX-Programme können ab Adresse 0x100 im Speicher abgelegt werden. An welcher
Adresse ein Programmgenau beginnt, ist in derSymboltabelle derObjektdatei festgelegt.
• Die Objektdatei enthält Befehlsworte für den jeweiligen Prozessor (hier: MMIX),
die vom Loader (Teil des Betriebssystems das auszuführende Programme in
den Speicher lädt) beim Starten des Programms in das Textsegment geladen
6.3 Speicher 229
werden. Neben den Befehlen enthält die Objektdatei auch Informationen über
Vorbelegungen des Speichers sowie die Symboltabelle.
• Die Symboltabelle spezifiziert eine Menge von (Name ! Adresse)-Paaren,
über die Einsprungspunkte in Module, Funktionen, Blöcke etc. gefunden
werden können. MMIX-Programme beginnen an der Adresse, die durch den
Symboltabellen-Eintrag ‘‘Main’’ festgelegt ist.
Von Adresse 0x00 bis 0xFF ist die Interrupt-Vektor-Tabelle abgelegt. Die Interrupt-Vektor-
Tabelle ist der Speicherbereich, in dem die Interrupt-Vektoren (s.u.) eines Prozessors
abgelegt sind. Nachfolgende Abbildung zeigt den Aufbau der Interrupt-Vektor-Tabelle
beim MMIX.
0x8C0x88
0x780x74
0x54
0x2C
0x4C0x48
0x70
0x7C
0x84
0x18
0x10
0x600x64
0x5C
0x3C
0x24
0x00
0x34
0x0C
0x04
0x68
0x50
0x20
0x44
0x80
0x28
0x1C
0x08
0x6C
0x14
0x40
0x38
0x30
0x58
Allgemeine Trips
Division durch Null
Integer-Überlauf
Überlauf Gleitkomma-Festkomma-Wandlung
Ungültige Gleitkoma-Operation
Gleitkomma-Überlauf
Gleitkomma-Unterlauf
Gleitkomma-Division durch NULL
Gleitkommazahl ungenau
230 6 MMIX-Prozessor
• Interrupts sind (asynchrone) Programm-Unterbrechungen. Sie können auftre-
ten, wenn ein Fehler aufgetreten ist (z.B. Division durch 0, Speicherzugriffs-
fehler), Zeitgeber (sog. Timer) abgelaufen sind, angeschlossene Geräte Daten
empfangen haben etc.
• Interrupt-Service-Routinen (ISRs) sind Funktionen, die zur Behandlung der
Interrupts aufgerufen werden. Beim Auftreten eines Timer-Interrupts können
beispielsweise von einem angeschlossenen Gerät empfangene Daten verarbei-
tet werden, Meßwerte von einem externen Sensor eingelesen werden oder – im
Falle des Betriebssystem-Schedulers – ein Prozess unterbrochen und ein an-
derer Prozess gestartet werden (time slicing). Interrupt-Service-Routinen sind
wie normale Funktionen, werden jedoch nicht durch das laufende Software-
Programm explizit (synchron) aufgerufen (wie z.B. ‘‘printf()’’ zur Ausgabe von
Zeichen auf dem Bildschirm). Sie werden durch asynchron auftretende externe
oder interne Ereignisse ausgelöst und durch die darauf folgende hardwareba-
sierte Änderung des Befehlszählers aufgerufen.
• Interrupt-Vektoren beschreiben für Interrupt-fähige Ereignisse die Adressen
der zugehörigen ISRs, d.h. die Stellen im Speicher, an die der Prozessor im
Fehlerfall automatisch verzweigen soll. Um im Ereignis-Fall automatisch in die
entsprechende ISR zu verzweigen, muss in der Regel
• die Behandlung von Interrupts allgemein freigeschaltet sein (z.B. Bit
‘‘globally enable interrupts’’ in einem Spezialregister), aber auch
• das betreffende Ereignis (z.B. ‘‘Division durch Null’’ explizit zur Feh-
lerbehandlung durch Interrupts freigeschaltet sein; beim MMIX bei-
spielsweise über das betreffende ‘‘Interrupt-Enable’’-Bit in rA.
Für viele Fehler gibt es eigene Interrupt-Vektoren, wie z.B. bei ‘‘Division durch
Null’’. Andere Fehler werden oft zu einem ‘‘allgemeinen Interrupt’’ zusammen-
gefasst.
Es gibt verschiedene Möglichkeiten, die Sprungziele der ISRs durch die
Interrupt-Vektoren zu beschreiben. Die gängigsten sind:
• Interrupt-Vektoren enthalten direkt die Adresse der ISR,
• Interrupt-Vektoren enthalten die Adresse der ISR indirekt, d.h. sie
enthalten die Speicher-Adresse des Datenworts, in dem die ISR-
Adresse steht,
• Interrupt-Vektoren enthalten vom Prozessor ausführbare Befehle; die
Befehle enthalten entweder die ISR selbst, oder einen Sprungbefehl zur
6.3 Speicher 231
ISR. Dieses Verfahren wird auch beim MMIX verwendet. Dazu werden
in die Interrupt-Vektoren Befehle eingetragen, die in die jeweiligen
ISRs verzweigen.
Daten-Segment
Das Datensegment dient zur Aufnahme von Daten, die während der Befehlsausführung
anfallen bzw. verarbeitet werden.Globale und statische Daten sowie zur Laufzeit allozierte
Datenwerden auf dem Heap abgelegt. Dieser beginnt ab Adresse 0x2000000000000000
und wächst in Richtung höherer Adressen. Lokale Datenwerden auf dem Stack abgelegt,
der bei Adresse 0x3FFFFFFFFFFFFFFF bzw. 0x3FFFFFFFFFFFFFF8 (für Octas) beginnt
und in Richtung niedrigerer Adressen wächst.
Pool-Segment
Das Pool-Segment ist ein Speicherbereich, der für den Datenaustausch zwischen
Programm und Betriebssystem gedacht ist. Im Pool-Segment werden beispielsweise
Programmen ihre Aufruf-Parameter übergeben. Dazu wird bei Programmstart in Register
0 die Anzahl der Parameter (argc = argument count) übergeben und in Register 1
die Adresse auf eine Null-terminierte Liste aus Zeigern, von denen jeder auf einen
Parameter zeigt. Adresse 0x4000000000000000 enthält die Adresse des ersten freien
Pool-Segment-Datenworts. Nachfolgende Abbildung zeigt das Poolsegment beim Aufruf
eines Programms skalprodarg mit den Parametern 4, 1, 2, 3, 4, 10, 20, 30 und 40.
Adresse Wert (hex) Wert (ascii)
0x4000000000000000 0x40000000000000b8 @ \0 \0 \0 \0 \0 \0 ©0x4000000000000008 0x4000000000000060 @ \0 \0 \0 \0 \0 \0 `0x4000000000000010 0x4000000000000070 @ \0 \0 \0 \0 \0 \0 p0x4000000000000018 0x4000000000000078 @ \0 \0 \0 \0 \0 \0 x0x4000000000000020 0x4000000000000080 @ \0 \0 \0 \0 \0 \0 Ç0x4000000000000028 0x4000000000000088 @ \0 \0 \0 \0 \0 \0 ê0x4000000000000030 0x4000000000000090 @ \0 \0 \0 \0 \0 \0 É0x4000000000000038 0x4000000000000098 @ \0 \0 \0 \0 \0 \0 ÿ0x4000000000000040 0x40000000000000a0 @ \0 \0 \0 \0 \0 \0 á0x4000000000000048 0x40000000000000a8 @ \0 \0 \0 \0 \0 \0 ¿0x4000000000000050 0x40000000000000b0 @ \0 \0 \0 \0 \0 \0 ░0x4000000000000058 0x0000000000000000 \0 \0 \0 \0 \0 \0 \0 \00x4000000000000060 0x736b616c70726f64 s k a l p r o d0x4000000000000068 0x6172670000000000 a r g \0 \0 \0 \0 \00x4000000000000070 0x3400000000000000 4 \0 \0 \0 \0 \0 \0 \00x4000000000000078 0x3100000000000000 1 \0 \0 \0 \0 \0 \0 \00x4000000000000080 0x3200000000000000 2 \0 \0 \0 \0 \0 \0 \00x4000000000000088 0x3300000000000000 3 \0 \0 \0 \0 \0 \0 \00x4000000000000090 0x3400000000000000 4 \0 \0 \0 \0 \0 \0 \00x4000000000000098 0x3130000000000000 1 0 \0 \0 \0 \0 \0 \00x40000000000000a0 0x3230000000000000 2 0 \0 \0 \0 \0 \0 \00x40000000000000a8 0x3330000000000000 3 0 \0 \0 \0 \0 \0 \00x40000000000000b0 0x3430000000000000 4 0 \0 \0 \0 \0 \0 \00x40000000000000b8 0x0000000000000000 \0 \0 \0 \0 \0 \0 \0 \0
Ls - l - a
int main ( int Argo ,clear * argues )
{
jrefurnoi
232 6 MMIX-Prozessor
Stack-Segment
Das Stack-Segment dient beim sog. Register-Stack des MMIX zur Auslagerung von
Registern. Dieses Segment wird von uns nicht verwendet.
Betriebssystem-Segment
Dieser Speicherbereich ist für das Betriebssystem vorgesehen. Durch die gewählte
Aufteilung kann am höherwertigsten Adress-Bit direkt abgelesen werden, ob der ausge-
führte Befehl zum Betriebssystem (kernel space) oder zu einem Benutzerprogramm (user
space) gehört. Damit lässt sich ein zwei Stufen umfassendes Privilegierungs-System auf-
bauen, bei dem beispielsweise
• bestimmte Befehle nur vom Betriebssystem verwendet werden dürfen oder
• Zugriffe auf bestimmte Resourcen (Register, angeschlossene Geräte, ...) nur
dem Betriebssystem erlaubt sind.
6.3 Speicher 233
Virtueller Speicher
Die gezeigte Einteilung des Speichers in verschiedene Segmente bezieht sich auf den
sog. virtuellen Speicher.
Virtueller Speicher meint, dass die Speicheradressen, auf die ein Programm zugreift,
nicht den realen, physikalischen Speicheradressen entsprechen. Die Umwandlung er-
folgt durch die Hardware und wird vom Betriebssystem durch Einstellungen in Spezial-
registern gesteuert. Auf diese Weise gaukelt das System einem Programm z.B. einen 64
Bit großen Adressraum vor, obwohl beispielsweise nur 8 GB Arbeitsspeicher im System
installiert sind. Durch die vom Betriebssystem überwachte Abbildung von virtuellen auf
reale Adressen kann ein Programm auf jede beliebige Speicheradresse zugreifen ohne
mit dem Speicher anderer Programme zu kollidieren.
Text-Segment
Daten-Segment
Pool-Segment
Stack-Segment
Betriebssystem-Segment
Globale Variable (Heap)
Lokale Variable, Stack
MMIX-Befehle
Interrupt-Vektoren
Text-Segment
Daten-Segment
Pool-Segment
Stack-Segment
Betriebssystem-Segment
Globale Variable (Heap)
Lokale Variable, Stack
MMIX-Befehle
Interrupt-Vektoren
Text-Segment
Daten-Segment
Pool-Segment
Stack-Segment
Betriebssystem-Segment
Globale Variable (Heap)
Lokale Variable, Stack
MMIX-Befehle
Interrupt-Vektoren
Virtueller Speicher dreier Programme realer Speicher
0
264-1
0
233-1
234 6 MMIX-Prozessor
Aufgaben
Verständnis Speicher
T a) Wozu verwendet ein Computer Arbeitsspeicher?
T b) Wo findet man den Arbeitsspeicher in einem Computersystem? Auf dem
Prozessor-Kern? Auf dem Mainboard? Als externes Gerät?
T c) Sind Zugriffe auf den Arbeitsspeicher in der Regel schneller oder langsamer als
Zugriffe auf Register?
T d) Begründen Sie Ihre Antwort auf die letzte Frage.
6.3 Speicher 235
Alignment
T a) Welche Wortbreiten werden bei Speicherzugriffen vom MMIX unterstützt? Wie
werden diese genannt?
T b) Wofür steht der Begriff Alignment?
T c) Warum wird Alignment angewendet?
T d) Was würde passieren, wenn ein 64 Bit breites Datenwort an einer durch 4, aber
nicht durch 8 teilbaren Adresse abgelegt werden würde?
236 6 MMIX-Prozessor
T e) Welche Eigenschaft müssen Byte-, Wyde-, Tetra- und Octa-Adressen beim MMIX
haben?
Big- und Little-Endian
a) Welche Art von Daten betrifft die Abspeicherung als Big- oder Little-Endian?
b) Verwendet der MMIX-Prozessor Big- oder Little-Endian?
c) Was bedeutet Big- und Little-Endian? Was ist der Unterschied?
d) Wie wird die 16 Bit-Zahl 0x1234 im Speicher an der Adresse 0x2000000000000000
abgelegt im Falle einer Big-Endian- und einer Little-Endian-Maschine?
0x2000000000000000
0x2000000000000001
Adresse Big Endian Little Endian
6.3 Speicher 237
T e) Wie wird im Speicher an der Adresse 0x2000000000000008 die 32 Bit-Zahl
0x12345678 abgelegt im Falle einer Big-Endian- und einer Little-Endian-Maschine?
0x200000000000000B
0x200000000000000A
0x2000000000000008
0x2000000000000009
Adresse Big Endian Little Endian
f) Wie wird im Speicher an der Adresse 0x2000000000000008 die 64 Bit-Zahl
0x12345678 abgelegt im Falle einer Big-Endian- und einer Little-Endian-Maschine?
0x200000000000000F
0x200000000000000E
0x200000000000000D
0x200000000000000c
0x200000000000000B
0x200000000000000A
0x2000000000000008
0x2000000000000009
Adresse Big Endian Little Endian
238 6 MMIX-Prozessor
Speicherorganisation
T a) Was wird im Textsegment gespeichert?
T b) Was ist ein Interrupt?
T c) Nennen Sie ein Ereignis, bei dem ein Interrupt auftreten kann.
T d) Was sind Interruptvektoren?
T e) Was wird im Datensegment gespeichert?
6.3 Speicher 239
T f) Was wird im Poolsegment gespeichert?
Gegeben ist die nachfolgend abgebildete ASCII-Tabelle:
02.11.11 09:45American Standard Code for Information Interchange – Wikipedia
Page 3 of 11http://de.wikipedia.org/wiki/Ascii
boten auch Acht-Bit-Codes, in denen ein Byte für ein Zeichen stand, zu wenig Platz, um alleZeichen der menschlichen Schriftkultur gleichzeitig unterzubringen. Dadurch wurden mehrereverschiedene spezialisierte Erweiterungen notwendig. Daneben existieren vor allem für denostasiatischen Raum einige ASCII-kompatible Kodierungen, die entweder zwischen verschiedenenCodetabellen umschalten oder mehr als ein Byte für jedes Nicht-ASCII-Zeichen benötigen.[1]
Keine dieser Acht-Bit-Erweiterungen ist aber „ASCII“, denn das bezeichnet nur den einheitlichenSieben-Bit-Code.
Für die Kodierung lateinischer Zeichen wird fast nur noch im Großrechnerbereich eine zu ASCIIinkompatible Kodierung verwendet (EBCDIC).
Zusammensetzung
ASCII-Zeichentabelle, hexadezimale NummerierungCode …0 …1 …2 …3 …4 …5 …6 …7 …8 …9 …A …B …C …D …E …F0… NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI1… DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US2… SP ! " # $ % & ' ( ) * + , - . /3… 0 1 2 3 4 5 6 7 8 9 : ; < = > ?4… @ A B C D E F G H I J K L M N O5… P Q R S T U V W X Y Z [ \ ] ^ _6… ` a b c d e f g h i j k l m n o7… p q r s t u v w x y z { | } ~ DEL
Die ersten 32 ASCII-Zeichencodes (von 00 bis 1F) sind für Steuerzeichen (control character)reserviert; siehe dort für die Erklärung der Abkürzungen in obiger Tabelle. Das sind Zeichen, diekeine Schriftzeichen darstellen, sondern die zur Steuerung von solchen Geräten dienen (oderdienten), die den ASCII verwenden (etwa Drucker). Steuerzeichen sind beispielsweise derWagenrücklauf für den Zeilenumbruch oder Bell (die Glocke); ihre Definition ist historischbegründet.
Code 20 (SP) ist das Leerzeichen (engl. space oder blank), das in einem Text als Leer- undTrennzeichen zwischen Wörtern verwendet und auf der Tastatur durch die Leertaste erzeugt wird.
Die Codes 21 bis 7E stehen für druckbare Zeichen, die Buchstaben, Ziffern und Satzzeichenumfassen.
Code 7F (alle sieben Bits auf eins gesetzt) ist ein Sonderzeichen, das auch als Löschzeichenbezeichnet wird (DEL). Dieser Code wurde früher wie ein Steuerzeichen verwendet, um aufLochstreifen oder Lochkarten ein bereits gelochtes Zeichen nachträglich durch das Setzen allerBits, das heißt durch Auslochen aller sieben Markierungen, löschen zu können – einmalvorhandene Löcher kann man schließlich nicht mehr rückgängig machen. Bereiche ohne Löcher
g) Geben Sie den Inhalt des Poolsegments für das Programm ls an, das mit dem
Parameter -la aufgerufen wird (Aufruf: ls -la).
0x4000000000000020
0x4000000000000010
0x4000000000000038
0x4000000000000018
0x4000000000000028
0x4000000000000008
0x4000000000000030
0x4000000000000000
240 6 MMIX-Prozessor
T h) Geben Sie den Inhalt des Poolsegments für das Programm rm an, das mit dem
Parameter -rf und * aufgerufen wird (Aufruf: rm -rf *).
0x4000000000000020
0x4000000000000010
0x4000000000000038
0x4000000000000018
0x4000000000000028
0x4000000000000008
0x4000000000000030
0x4000000000000000
i) Wiewerden in der ProgrammierspracheC einemProgrammParameter übergeben?
j) Wie kann man in der Programmiersprache C auf die Parameter zugreifen?
6.3 Speicher 241
k) Wie kann man beim MMIX auf die Parameter zugreifen?
Virtueller Speicher
a) Wenn alle Programme an Adresse 0x100 beginnen bzw. alle Programme ihre
Daten ab Adresse 0x2000000000000000 im Speicher ablegen: Überschreiben
die verschiedenen Programme dann nicht gegenseitig ihre Daten? Ja/nein und
warum?
b) Was bedeutet virtueller Speicher?
c) Wozu ist virtueller Speicher gut?
242 6 MMIX-Prozessor
6.4 MMIX-ProgrammeMMIX-Programme bzw. Assembler-Programme für den MMIX-Prozessor sind Quelltext-
Dateien mit Befehlen für
• den MMIX-Prozessor; die vom MMIX unterstützen Befehle nennt man auch
‘‘Befehlssatz-Befehle’’
• den Loader; der Loader ist derjenige Teil des Betriebssystems, der auszufüh-
rende Programme vom der Festplatte/SSD in den Speicher lädt
• den Assemblierer; der Assemblierer, oft auch Assembler genannt, ist das
Computerprogramm, das MMIX-Quelltext in Binärdateien mit MMIX-Befehlen
und Loader-Anweisungen übersetzt
Aufbau
Nachfolgende Abbildung zeigt, wie MMIX-Programme (Quelltext) aus vier durch Leer-
zeichen und Tabulatoren voneinander getrennte Spalten aufgebaut sind.
Marke Befehl Operanden Kommentar
LOC Data_SegmentGREG @
SP GREG Pool_SegmentA OCTA 123456 A initialisieren
a IS $1 Name für $1
LOC #100 Beginne an 0x100Main LDO a,A A in Reg. a laden
Start SUB SP,SP,8STO a,:SP,0... ...
• In der ersten Spalte stehen Marken.
• Marken sind Namen, über die Speicherstellen (Befehle oder Daten)
angesprochen werden können.
• Bis auf die Marke Main (Programm-Beginn) sind Marken optional.
6.4 MMIX-Programme 243
• Enthält eine Zeile Befehle, jedoch keine Marke, dann muss die Zeile
mit einem Leerzeichen oder Tabulator beginnen. Anderenfalls würde
der Befehl als Marke interpretiert und die Operanden als Befehl, was
zu Fehlern führen würde.
• Beginnt eine Zeile mit einem Zeichen /2 {a ... z, A...Z, 0...9}, so wird
diese Zeile als Kommentar ignoriert.
• In der zweiten Spalte stehen Befehle, d.h. sowohl Befehle aus dem Befehlssatz
des MMIX-Prozessors, als auch Anweisungen für den Assembler oder Loader.
• In der dritten Spalte stehen die Operanden. Mehrere Operanden werden durch
Komma (ohne Leerzeichen) getrennt.
• In der vierten Spalte stehen Kommentare. Kommentare sind optional. Sie
können Leerzeichen enthalten.
Assembler- und Loader-Befehle
Der IS-Befehl
Der IS-Befehl ist eine Assemblierer-Anweisung, d.h. er wird von dem Assemblierungs-
Programm ausgeführt, das in Assembler-Sprache geschriebene Befehle in Maschi-
nensprache (Nuller und Einser) übersetzt. Der IS-Befehl dient dazu, Allzweck-Register
sinnvoll benennen zu können. Die Syntax des Befehls lautet:
Name IS Register
Name ist der neue Name, Register das entsprechende Register. Ein Beispiel für die
Anwendung des IS-Befehls lautet:
Seitenlaenge IS $3
Dieser Befehl veranlasst den Assemblierer dazu, im Quelltext nach den Zeichenketten
‘‘Seitenlaenge’’ zu suchen und diese durch die Zeichenkette ‘‘$3’’ zu ersetzen. Dieser
Schritt wird – wie der Präprozessor in C – vor der Übersetzung des Programms in
Maschinensprache ausgeführt.
Der GREG-Befehl
Der GREG-Befehl ist ein Loader-Befehl, d.h. er wird vom Loader beim Laden eines
auszuführenden Programms von der Festplatte/SSD in den Arbeitsspeicher ausgeführt.
Der GREG-Befehl reserviert das nächste freie globale Register (d.h. er verringert die in
rG stehende Zahl um den Wert 1). Wenn für den GREG-Befehl ein Parameter angegeben
244 6 MMIX-Prozessor
ist, wird das globale Register mit dem entsprechenden Wert initialisiert. Die Syntax des
GREG-Befehls lautet:
Name GREG Wert
Name ist der Wert, über den das neue globale Register ansprechbar sein soll (wie beim
IS-Befehl), Wert ist der Initialisierungs-Wert. Name und Wert sind optional.
Beispiel: Steht in Register rG der Wert 255, dann hat der Befehl
SP GREG #4000000000000000
folgende Auswirkungen:
• Der in rG abgespeicherte Wert wird von 255 auf 254 geändert.
• In Register 254 wird der Wert 0x4000000000000000 abgespeichert; beim MMIX-
Assemblierer werden hexadezimale Zahlen mit einer führenden Raute (‘‘#’’)
statt mit führendem ‘‘0x’’ gekennzeichnet.
• Register 254 kann auch über den Namen SP angesprochen werden.
Der GREG-Befehl wird insbesondere dazu verwendet, um vor der Programmausführung
Basis-Adressen in globalen Registern abzulegen.
Der LOC-Befehl
Der LOC-Befehl ist ein Loader-Befehl. ‘‘LOC’’ steht für ‘‘locate an address’’ und setzt
die Eingabemarke des Loaders auf die als Parameter angegebene Adresse. Der Befehl
teilt dem Loader beim Laden einer ausführbaren MMIX-Datei in den Arbeitsspeicher mit,
• ab welcher Adresse Befehlscode in den Speicher geschrieben oder
• ab welcher Speicher-Adresse Variable angelegt werden sollen.
Die Syntax des Befehls lautet:
LOC Adresse
Als Adresse kann entweder eine Zahl, oder ein Segmentname (z.B. Data_Segment)angegeben werden. Der Befehl
LOC #100
zeigt dem Loader beispielsweise an, dass die nachfolgenden Daten im Speicher ab
Adresse 0x100 abgelegt werden sollen.
6.4 MMIX-Programme 245
Die vom Loader aktuell betrachtete Adresse wird beim MMIX mit dem Zeichen @
bezeichnet. @ meint dabei ‘‘the place where we are at’’.
Die Befehle BYTE, WYDE, TETRA und OCTA
Die Befehle BYTE, WYDE, TETRA und OCTA sind Loader-Befehle, die Datenworte der
Größe 8 Bit (BYTE), 16 Bit (WYDE), 32 Bit (TETRA) und 64 Bit (OCTA) im Speicher
allozieren (anlegen) und diesen bei Angabe von Parametern auch initialisieren.
Die Syntax lautet:
Marke Befehl Wert
• Befehl ist einer der Anweisungen BYTE, WYDE, TETRA, OCTA,
• Marke ist der Name (auch ‘‘Marke’’ genannt), über den auf die Adresse der
allozierten Daten zugegriffen werden kann, und
• Wert der Zahlenwert, mit dem das Datenwort initialisiert werden soll; werden
mehrere Werte durch Komma (ohne Leerzeichen) getrennt, werden mehrere
Datenworte desselben Typs angelegt.
Beispiel: Die Befehle
LOC Data_SegmentVektor BYTE 1,2,3
reservieren im Speicher an Adresse 0x20000000000000000 drei Byte und initialisieren
diese mit den Werten 1, 2 und 3. Nachfolgende MMIX-Befehle können auf die Adresse
des ersten Byte (das Byte, in dem die ‘‘1’’ gespeichert ist) über die Marke Vektor
zugreifen.
Beim MMIX werden aus mehreren Byte zusammengesetzte Datenworte (Wyde, Tetra,
Octa) an Adressen ausgerichtet, die dem ganzzahligen Vielfachen ihrer Datenwort-
breite entsprechen (Alignment). Zur Einhaltung des Alignments werden ggf. Leer-Byte
eingefügt. Die Codierung der Datenworte folgt dem Big-Endian-Schema.
Mit jedem durch BYTE, WYDE, TETRA oder OCTA allozierten Datenwort wird die aktuelle
Adresse @ um die entsprechende Byteanzahl erhöht. Müssen aufgrund des Alignments
Leer-Byte eingefügt werden, so werden diese bei der Erhöhung ebenfalls berücksichtigt.
0×20 . . . O 0×01
- - - A 0×02
- - . 2 0×03
246 6 MMIX-Prozessor
Aufgaben
T a) Aus wievielen/welchen Spalten bestehen MMIX-Programme?
T b) Wie werden die Spalten im Programmcode getrennt?
T c) Wie muss man MMIX-Codezeilen schreiben, die keine Marke verwenden?
T d) Wie kann man beim MMIX-Assembler eine komplette Zeile auskommentieren?
T e) Werden alle vier Spalten eines MMIX-Programms für den Übersetzungsvorgang
herangezogen? Gehen Sie auf die einzelnen Spalten ein.
6.4 MMIX-Programme 247
f) Geben Sie Anweisungen an, mit denen Sie die Register 0, 1 und 2 durch die
Namen a, b und c ansprechbar machen.
T g) Geben Sie Anweisungen an, mit denen Sie die Register 1, 2 und 3 durch die
Namen ankathete, gegenkathete und hypothenuse ansprechbar machen.
h) Geben Sie die Anweisung an, mit denen Sie ein globales Register anlegen,
dieses über den Namen PI ansprechbar machen und mit 0x400921FB54442EEA
initialisieren.
T i) Geben Sie die Anweisung an, mit denen Sie ein globales Register anlegen und
dieses über den Namen A ansprechbar machen.
a IS $0
b Is $1
c Is $2
PI GREG # 40082171354442 EEA
248 6 MMIX-Prozessor
T j) Mit welchen Befehlen können Sie Worte der Länge 8, 16, 32 und 64 Bit im Speicher
reservieren?
T k) Was ist der Loader?
l) Geben Sie Befehle an, mit denen Sie an Speicheradresse #2000000000000000
vier Bytes reservieren, die über die Marken A, B, C und D angesprochen werden
können. A soll mit 1 und B mit 2 initialisiert werden. Fügen Sie auch einen
geeigneten Befehl zur Reservierung und Initialisierung eines globalen Registers mit
dem Wert 0x2000000000000000 ein.
place where we are at"
= ahtuelle A dresses
I"
GREG
↳OC # 200 . . .
0
A BYTE A
B BYTE 2
BYTE
BYTE
( GREG # 20 .. -
O )
6.4 MMIX-Programme 249
T m) Geben Sie Befehle an, mit denen Sie an Speicheradresse #2000000000000000
zwei 64 Bit Werte reservieren, die über die Marken Null, NaN und Inf angesprochen
werden können. Null soll mit der Gleitkommazahl 0.0 initialisiert werden, NaN
mit der Gleitkomma-Codierung ‘‘Not a Number’’ und Inf mit der Gleitkomma-
Codierung ‘‘unendlich’’. Fügen Sie auch einen geeigneten Befehl zur Reservierung
und Initialisierung eines globalen Registers mit dem Wert 0x2000000000000000
ein.
Betrachten Sie die folgenden Befehle:
LOC #2000000000000000X BYTEY WYDEZ OCTA
n) Geben Sie die Adressen an, an denen X und Y im Speicher abgelegt werden.
o) An welchen Adressen wird Z abgelegt?
X : 0720 . - .O O
Y : 0×20 .. .
02 - 0×20 . . . 03
2- : 0×20 . ..
08 - 0×20 . - -. OF
250 6 MMIX-Prozessor
Betrachten Sie die folgenden Befehle:
LOC #2000000000000000A WYDEB TETRAC BYTED OCTA
T p) Geben Sie die Adressen an, an denen A, B, C und D im Speicher abgelegt werden.
6.4 MMIX-Programme 251
q) Geben Sie Befehle an, die
• ein neues globales Register anlegen und dieses mit Speicheradresse
0x2000000000000000 initialisieren,
• an dieser Speicheradresse ein 64 Bit breites Datenwort anlegen, das mit
4 initialisiert wird und über die Marke N angesprochen werden kann,
• an den darauffolgenden Speicheradressen zwei 4-dimensionale Vektoren
wie folgt anlegen:
• Der erste Vektor soll über ADR_A1 ansprechbar sein und mit den
64 Bit-Zahlen [1, 2, 3, 4] initialisert werden;
• der zweite Vektor soll über ADR_A2 ansprechbar sein und mit den
64 Bit-Zahlen [10, 20, 30, 40] initialisiert werden.
LOC # 200 - - ..
O
GREG @N OCTA 4
ADR - An OCTA 1,43 , 4
ADR - AZ OCTA 1920,3440
252 6 MMIX-Prozessor
T r) Geben Sie Befehle an, die
• ein neues globales Register anlegen und dieses mit Speicheradresse
0x2000000000000000 initialisieren,
• an dieser Speicheradresse ein 64 Bit breites Datenwort anlegen, das mit
der Marke Erg angesprochen werden kann,
• an den darauffolgenden Speicheradressen zwei 3-dimensionale Vektoren
wie folgt anlegen:
• Der erste Vektor soll über V1 ansprechbar sein und mit den 32
Bit-Zahlen [100, 200, 300] initialisert werden;
• der zweite Vektor soll über V2 ansprechbar sein und mit den 32
Bit-Zahlen [10, 20, 30] initialisiert werden.
6.4 MMIX-Programme 253
Übersetzungsprozess
Nachfolgende Abbildung zeigt den Übersetzungsprozess, mit dem MMIX-Quelldateien
in MMIX-Objektdateien umgewandelt werden um anschließend vom MMIX-Simulator
ausgeführt werden zu können.
LOC Data_Segment GREG @A OCTA 3a IS $1
LOC #100Main LDO a,A ADD a,a,8 STO a,A
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx8D01FE0020010108AD01FE00xxxxxxxxxxxxxxxxxxxxxxxx
LOC Data_Segment GREG @A OCTA 3a IS $1
LOC #100Main LDO $1,$254,0 ADD $1,$1,8 STO $1,$254,0
Assembler(Präprozessor)
Assembler
Quelldatei *.mms
Binärdatei *.mmo
MMIX-Simulator
mmix -i *.mmo
mmixal *.mms
Loader-Anweisungen
MMIX-Befehle
Symboltabelle
MMIX-Quelldateien werden mit einem Texteditor erstellt. Die Quelldateien haben die
Endung mms (MMIX source). Mit einem Aufruf des Assemblierungsprogramms mmixal
254 6 MMIX-Prozessor
werden die Quelldateien in Objektdateien übersetzt. Der Assembler verarbeitet zunächst
die Assembler-Anweisungen (z.B. IS-Befehle) mit einem Präprozessor und löst Namen
und Marken auf. Anschließend übersetzt er die MMIX-Befehle (mit den aufgelösten
Marken) in entsprechende Binärwerte. Die durch Namen und Marken gegebenen An-
weisungen sind somit implizit in den MMIX-Befehlen enthalten (Nummer des Registers,
Speicheradresse, ...). Aus den Sprung-Marken erstellt der Assembler eine Symboltabel-
le, in der für jedes vorkommende Symbol die entsprechende Adresse eingetragen wird.
Auf diese Weise kann z.B. der Loader über die Symboltabelle die Adresse der Marke
Main ermitteln und zum Programmstart an diese Adresse verzweigen.
Befehlswort
Das Befehlswort beim MMIX ist für alle Befehle 32 Bit breit, d.h. die Länge des
Befehlsworts (in Byte) ist konstant. Dies ist ein typisches Merkmal für RISC-Prozessoren.
Durch die konstante Befehlswortbreite ist es sehr einfach, Befehle ‘‘im Voraus’’ aus dem
Befehlsspeicher zu laden: Da alle Befehle vier Byte breit sind, können durch Laden der
nächsten 4 · n Byte die nächsten n Befehle aus dem Speicher geladen werden.
Bei CISC-Prozessoren ist die Länge des Befehlsworts nicht konstant sondern abhängig
vom jeweiligen Befehl. Bei x86 sind Befehlsworte beispielsweise zwischen 1 und 15 Byte
lang.
Beim MMIX gliedert sich das 32 Bit breite Befehlswort in vier Byte, die Opcode, X, Y und
Z genannt werden.
OP X Y Z31 24 23 16 15 8 7 0
• Der Opcode ist eine 8 Bit breite Zahl die festlegt, um welchen Befehl es sich
handelt (Addieren, Subtrahieren, ...). Die Zuordnung Opcode $ Befehl wird
durch eine Tabelle (s.u.) spezifiziert.
• X ist (bis auf Speicherbefehle) der Ziel-Operand, d.h. eine 8 Bit breite Zahl,
die festlegt, in welches Register (0 bis 255 bei Allzweckregistern bzw. 0 bis
31 bei Spezialregistern) das Ergebnis der Operation abgelegt werden soll. Die
Codierung von X entspricht der Registernummer, d.h. ‘‘Register 1’’ wird als
X = 0000 00012 = 0x01 codiert.
• Y und Z sind die Quelloperanden, d.h. zwei 8 Bit breite Zahlen, die festlegen,
in welchen Registern die Quelloperanden stehen. Die Codierung entspricht der
von X.
6.4 MMIX-Programme 255
Spezialregister werden im Befehlswort wie folgt codiert:
x S(x) x S(x) x S(x) x S(x)
0x00 rB 0x08 rC 0x10 rQ 0x18 rW0x01 rD 0x09 rN 0x11 rU 0x19 rX0x02 rE 0x0A rO 0x12 rV 0x1A rY0x03 rH 0x0B rS 0x13 rG 0x1B rZ0x04 rJ 0x0C rI 0x14 rL 0x1C rWW0x05 rM 0x0D rT 0x15 rA 0x1D rXX0x06 rR 0x0E rTT 0x16 rF 0x1E rYY0x07 rBB 0x0F rK 0x17 rP 0x1F rZZ
Viele MMIX-Befehle verwenden sog. Direktoperanden (engl. immediate operands), d.h.
Operanden, die direkt im Befehlswort stehen. BeimMMIX sind folgende Direktoperanden
möglich:
• Z: Die Bits 7 ... 0 des Befehlsworts enthalten eine 8 Bit breite Zahl.
• Y: Die Bits 15 ... 8 des Befehlsworts enthalten eine 8 Bit breite Zahl.
• YZ: Die Bits 15 ... 0 des Befehlsworts enthalten eine 16 Bit breite Zahl.
• XYZ: Die Bits 23 ... 0 des Befehlsworts enthalten eine 24 Bit breite Zahl.
256 6 MMIX-Prozessor
Nachfolgende Tabelle übersetzt MMIX-Opcodes in diejenigen Zahlen, die im Befehlswort
in den Bits 31...24 abgelegt werden müssen.
! "#$%
!"#"$% &'()*+,-.%(*/%012'(*/%!&'(!)*+*,-(#.*-/!01234/*5!67*8434/*9!:;</!=*8>((!7'3,+4-=*7/*<!?'@*--*!A@*<(*BCBD!!
0x..0 0x..1 0x..2 0x..3 0x..4 0x..5 0x..6 0x..7
TRAP 5ν FCMP ν FUN ν FEQL ν FADD 4ν FIX 4ν FSUB 4ν FIXU 4ν
FMUL 4ν FCMPE 4ν FUNE ν FEQLE 4ν FDIV 40ν FSQRT 40ν FREM 4ν FINT 4ν
SETH ν SETMH ν SETML ν SETL ν INCH ν INCHM ν INCML ν INCL νORH ν ORMH ν ORML ν ORL ν ANDNH ν ANDNMH ν ANDNML ν ANDNL ν
POP 3ν RESUME 5ν SYNC ν SWYM ν GET ν TRIP 5ν0x..8 0x..9 0x..A 0x..B 0x..C 0x..D 0x..E 0x..F
SUB[I] ν
CSNP[I] νZSP[I] ν
SUBU[I] ν16ADDU[I] νNEGU[I] νSRU[I]ν
BOD[B] ν+πBEV[B] ν+πPBOD[B] 3ν-π
CMPU[I] νSLU[I] νBZ[B] ν+πBNZ[B] ν+πPBZ[B] 3ν-π
CSNZ[I] νZSZ[I] ν
ADD[I] ν
CSNN[I] νZSN[I] ν
ADDU[I] ν4ADDU[I] ν
PBNZ[B] 3ν-πCSZ[I] ν
0x0.. 0x0..FLOT[I] 4ν FLOTU[I] 4ν SFLOT[I] 4ν SFLOTU[I] 4ν
PUSHJ[B] ν GETA[B] ν PUT[I] ν[UN]SAVE 20µ+ν
XOR[I] νNXOR[I] νODIF[I] νMXOR[I] ν
STWU[I] µ+νSTOU[I] µ+νSTUNC[I] µ+νPUSHGO[I] 3ν
LDWU[I] µ+νLDOU[I] µ+νLDUNC[I] µ+νGO[I] 3ν
CSOD[I] νPBEV[B] 3ν-π
ZSEV[I] ν
CSEV[I] νZSOD[I] ν
NAND[I] νTDIF[I] νMOR[I] ν
STO[I] µ+νSTCO[I] µ+νSYNCID[I] νNOR[I] ν
LDO[I] µ+νCSWAP[I] 2µ+2νPREGO[I] νSTW[I] µ+ν
PBNP[B] 3ν-πCSP[I] ν
ZSNP[I] νLDW[I] µ+ν
BNP[B] ν+πPBP[B] 3ν-π
8ADDU[I] νNEG[I] νSR[I] νBP[B] ν+π
ORN[I] νANDN[I] νWDIF[I] νSADD[I] ν
STBU[I] µ+νSTTU[I] µ+νSTHT[I] µ+νPREST[I] ν
LDBU[I] µ+νLDTU[I] µ+νLDHT[I] µ+νPRELD[I] ν
ZSNZ[I] ν
BDIF[I] νMUX[I] ν
JMP[B] ν
STSF[I] µ+νSYNCD[I] νOR[I] νAND[I] ν
LDSF[I] µ+νLDVTS[I] νSTB[I] µ+νSTT[I] µ+ν
BNN[B] ν+πPBN[B] 3ν-πPBNN[B] 3ν-πCSN[I] ν
ZSNN[I] νLDB[I] µ+νLDT[I] µ+ν
2ADDU[I] νCMP[I] νSL[I] νBN[B] ν+π
0xC..
0xD..
0xE..
0xF..
0x8..
0x9..
0xA..
0xB..
0xD..
0xE..
0xF..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x9..
0xA..
0xB..
0xC..
0x5..
0x6..
0x7..
0x8..
0x1..
0x2..
0x3..
0x4..
MUL[I] 10ν MULU[I] 10ν DIV[I] 60ν DIVU[I] 60ν
!!!&'(!*<(B*!E;@@-*!0F!);B#G*<B9!/*(!1234/*(!*7B(2<;3,B!/*<!&422*-C*;-*!0H!@;(!IJ95! ;7!/*<!(;3,!/*<!)*#+*,-(34/*!@*+;7/*BD!!!&'(!C:*;B*!E;@@-*!/*(!1234/*(!*<=;@B!(;3,!:;*!+4-=BK!!
−! 6L)!0);B!E<D!"9!/*(!C:*;B*7!E;@@-*(!+! H5!:*77!(;3,!/*<!)*+*,-!;8!4@*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!+! I5!:*77!(;3,!/*<!)*+*,-!;8!M7B*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!!
!−! );B(!$5!I!M7/!H!/*(!C:*;B*7!E;@@-*(!*7B(2<*3,*7!/*<!%&'$("!0H!@;(!%95!;7!/*8!(;3,!/*<!)*+*,-(#34/*!@*+;7/*B!
![I]!@*/*MB*BK!N88*/;'B*#O'<;'7B*!/*(!)*+*,-(!
−! ;88*/;'B*!⇔!&;<*PB42*<'7/!−! ADD $1,$2,$3K!7;3,B!;88*/;'B*5!/'!/*<!"D!12*<'7/!*;7!Q*=;(B*<!;(B!M7/!P*;7*!R',-!−! ADD $1,$2,3K!;88*/;'B*5!/'!'-(!"D!12*<'7/!*;7*!R',-!'7=*=*@*7!;(B!M7/!P*;7!Q*=;(B*<!−! /*<! 1234/*! /*<! ;88*/;'B*#O'<;'7B*! *;7*(! )*+*,-(! ;(B! ;88*<! M8! I! ,S,*<! '-(! /;*! 7;3,B#;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!0(B*,B!;7!/*<!&422*-)&'$("!'-(4!<*3,B(9!
−! *;7*! ;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!:;</!T48!U((*8@-*<!'MB48'B;(3,!'7,'7/!/*(! +*,-*7/*7!&4--'<#R*;3,*7(! 0$9! *<P'77B5! :*(,'-@! ;8! V<4=<'88! 7;3,B! *W2-;C;B!ADDI! =*(3,<;*@*7! :*</*7!8M((!!!
Die Übersetzung erfolgt folgendermaßen:
• Befehl suchen
• Doppelzeile ermitteln, in der der Befehl steht
• An der Seite der Tabelle das obere Nibble (= die oberen 4 Bits) des Opcodes
ablesen, z.B. ADD) 0x2
• Prüfen, ob der Befehl im oberen oder im unteren Teil der Doppelzeile steht
• Steht der Befehl im oberen Teil der Doppelzeile, kann man das untere
Nibble (= die unteren 4 Bits) des Opcodes an der ersten Tabellenzeile
ablesen, z.B. ADD) 0x..0 oder 0x..1
• Steht der Befehl im unteren Teil der Doppelzeile, kann man das
0×200102030×21010203
n a
/qisten.rs/ZayU3.?fn7Ihe9aEiTe"
ADD $1 , $2,83 ← ADD $1.812,3
B =
↳ award
=
SprungZurich
,
d. h. Are
hiedrigeeA dresser
6.4 MMIX-Programme 257
untere Nibble (=die unteren 4 Bits) des Opcodes an der untersten
Tabellenzeile ablesen, z.B. 2ADDU) 0x..8 oder 0x..9
• Anschließend muss nur noch unterschieden werden, ob es sich um die linke
oder die rechte Variante des Befehls handelt, beispielsweise ob man in der
oberen Zeile 0x..0 oder 0x..1 auswählen muss oder ob man in der unteren
Zeile 0x..8 oder 0x..9 auswählen muss. Dazu wird der in der Tabelle nach dem
Befehlsnamen in Klammern stehende Buchstabe verwendet;
• I bedeutet immediate, d.h. Direktoperand; Beispiel: Bei ADD $1,$2,$3wird ADD mit 0x20 codiert, bei ADD $1,$2,3 mit 0x21
• B bedeutet backward, d.h. Rückwärtssprung; erhöht sich bei einem
Sprung die Adresse, wird der linke Zahlenwert verwendet (Vorwärts-
Sprung); verringert sich bei einem Sprung die Adresse, wird der rechte
Zahlenwert verwendet (Rückwerts-Sprung)
Aus der Tabelle lassen sich auch die von Donald Knuth für den MMIX-Simulator
spezifizierten Ausführungszeiten ermitteln:
• ⌫ entspricht der Dauer von 1 Takt
• µ ist die Anzahl der Takte für einen Speicherzugriff
• ⇡ bedeutet
• 2 · ⌫, wenn gesprungen wird, und
• 0 · ⌫, wenn nicht gesprungen wird.
258 6 MMIX-Prozessor
Aufgaben
T a) Wie breit (in Bit) ist das MMIX Befehlswort?
T b) Skizzieren Sie das MMIX Befehlswort und geben Sie den Inhalt jedes Bytes an.
T c) In welchen Byte des Befehlsworts wird im Allgemeinen Information über die
Quelloperanden bzw. über die Zieloperanden abgespeichert?
T d) Was ist ein Direktoperand?
e) Wieviele Taktzyklen benötigen die meisten Befehlen zur Ausführung?
f) Welcher Befehl benötigt die längste Zeit zur Ausführung, wenn man von Speicher-
befehlen absieht?
g) Wieviele Takte benötigt der BZ-Befehl, wenn gesprungen wird?
6.4 MMIX-Programme 259
h) Wieviele Takte benötigt der BZ-Befehl, wenn nicht gesprungen wird?
i) Wieviele Takte benötigt der PBZ-Befehl, wenn gesprungen wird?
j) Wieviele Takte benötigt der PBZ-Befehl, wenn nicht gesprungen wird?
k) Geben Sie das 32 Bit breite Befehlswort des Befehls ‘‘SL $1,$2,3’’ an.
T l) Geben Sie das 32 Bit breite Befehlswort des Befehls ‘‘SUB $5,$6,7’’ an.
260 6 MMIX-Prozessor
6.5 MMIX Befehle
Definitionen
Wort
wb ist ein Wort der Länge b Byte. wbx repräsentiert Bit Nr. x im Datenwort wb, wobei das
niederwertigste Bit in wb an Bitposition x = 0 liegt. wbx ...y meint Bits x ...y des Datenworts
wb.
Befehlswort
Sei ◆ ein 32 Bit breites MMIX Befehlswort.
• X = ◆23...16
• Y = ◆15...8
• Z = ◆7...0
• YZ = ◆15...0
• XY = ◆23...8
• XYZ = ◆23...0
Allzweckregister
• Der MMIX-Prozessor verfügt über 256 Allzweckregister, die mit 0, 1, ... 255
durchnummeriert werden.
• Zur Adressierung eines Allzweckregisters im Befehlswort wird die als vor-
zeichenlose 8 Bit breite Zahl codierte Registernummer verwendet. Beispiel:
Register 5 wird als 0x05 bzw. als Bitkombination 00000101 codiert.
• $x , 0 x 255 entspricht der Bitkombination, die in Register x gespeichert ist.
• $X ist die Bitkombination, die in dem durch Bits 23...16 des Befehlsworts
adressierten Register gespeichert ist. Beispiel: Befehlswort ist 0x12345678;
Bits 23...16 extrahieren ) 0x34 (= Bitkombination 00110100) = Dezimal 52 )Im Falle des Befehlsworts 0x12345678 meint $X den Wert, der in Register 52
gespeichert ist.
• $Y ist die Bitkombination, die in dem durch Bits 15...8 des Befehlsworts
adressierten Register gespeichert ist.
• $Z ist die Bitkombination, die in dem durch Bits 7...0 des Befehlsworts adres-
sierten Register gespeichert ist.
6.5 MMIX Befehle 261
Arbeitsspeicher
M ist der Arbeitsspeicher des MMIX Prozessors (M = memory).
• M1[x ] ist das an Adresse x gespeicherte Byte.
• M2[x ] ist das an Adresse x & (�2) gespeicherte Wyde.
• M4[x ] ist das an Adresse x & (�4) gespeicherte Tetra.
• M8[x ] ist das an Adresse x & (�8) gespeicherte Octa.
Die Symbole ◆, X, Y, Z, $X, $Y, $Z, $0, $1, ..., M1[...], M2[...], ... repräsentieren Bitmuster.
Ein Zahlenwert entsteht erst durch entsprechende Interpretation des Bitmusters (z.B.
vorzeichenlose Festkommazahl, ...).
Befehlszähler
BeimMMIX bedeutet das Zeichen @ ‘‘the place where we are at’’ und meint eine Adresse
im Speicher.
• Beim Loader bezieht sich @ auf die Adresse, an der ein Daten- oder Befehls-
worte im Speicher abgelegt werden soll.
• In Bezug auf die Befehlsausführung meint @ die Adresse des Befehls, der
gerade ausgeführt wird, also den Befehlszähler BZ (oder PC für engl. program
counter).
- Zeo - AAA - - - . 1102
r#
Me - . .100
# 111 . . .1000
262 6 MMIX-Prozessor
Operationen
• x y : Weise x den Wert y zu
• x , y : Ausdruck x ist äquivalent zum Ausdruck y
• x ) y : Wenn x , dann y
• x ||y : Logische operation x ODER y
• x = y : Vergleich ob x den gleichen Wert hat wie y ; liefert wahr (d.h. 1), wenn x
den selben Wert hat wie y , sonst falsch (d.h. 0)
• x ⌧ y : Schiebe x um y Stellen nach links; fülle frei werdende Bitstellen mit 0
auf
• x �u y : Schiebe x um y Bitstellen nach rechts; fülle frei werdende Bitstellen
mit 0 auf
• x �s y : Schiebe x um y Bitstellen nach rechts; fülle frei werdende Bitstellen mit
dem Wert des Vorzeichenbits (MSB) auf.
• x % y : Rest der Festkomma-Division x/y .
• ⇠ x : Invertiere alle Bits von x , d.h. berechne das 1er-Komplement
• x & y : Bitweise UND-Verknüpfung von x und y
• x | y : Bitweise ODER-Verknüpfung von x und y
• x ⌦ y : Bitweise XOR-Verknüpfung von x und y
Umwandlung Festkommazahl$ Gleitkommazahl
• f32(w4): Nimmt an, dass das vier Byte breite Datenwort w4 im 32 Bit IEEE 754
Gleitkommaformat codiert ist und gibt den entsprechenden Zahlenwert zurück
(z.B. 1,75).
• f 032(x): Codiert die Zahl x als 32 Bit breite Gleitkommazahl und gibt das
entsprechende 32 Bit breite Bitmuster zurück.
• f64(w8): Nimmt an, dass das acht Byte breite Datenwort w8 im 64 Bit IEEE 754
Gleitkommaformat codiert ist und gibt den entsprechenden Zahlenwert zurück
(z.B. 1,75).
• f 064(x): Codiert die Zahl x als 64 Bit breite Gleitkommazahl und gibt das
entsprechende 64 Bit breite Bitmuster zurück.
• r(x): Rundet eine reelle Zahl gemäß dem in Register rA ausgewählten Run-
dungsmodus auf eine ganze Zahl.
6.5 MMIX Befehle 263
(De-) Codierung von Festkommazahlen
• s(wb): Nimmt an, dass das b Byte breite Wort wb im 2er-Komplement codiert
ist und gibt den entsprechenden Wert zurück (z.B. 1, 0, -3)
• u(wb): Nimmt an, dass das b Byte breite Wort wb als vorzeichenlose Festkom-
mazahl codiert ist und gibt den entsprechenden Wert zurück (z.B. 0, 1)
• s 0b(x): Gibt das b Bit breite im 2er-Komplement codiert Bitmuster zurück das
dem Wert x entspricht.
• u0b(x): Gibt das b Bit breite Bitmuster (vorzeichenlose Codierung) zurück das
dem Wert x , x � 0, entspricht.
Zusammenfassen von in Registern gespeicherten Werten
Wenn $X das 64 Bit breite in Register X gespeicherte Bitmuster ist und $Y das 64 Bit breitein Register Y gespeicherte Bitmuster ist, dann ist $X$Y das 128 Bit breite Bitmuster das
aus der Aneinanderreihung der beiden Bitmuster $X und $Y entsteht. ($X$Y)127...64 = $Xund ($X$Y)63...0 = $Y.
Programm beenden
• TRAP 0,Halt,0 beendet ein MMIX-Programm und gibt die Kontrolle zurück an
das Betriebssystem.
Register-Register-Befehle
Hardware
Der MMIX ist eine Drei-Address- Register-Register-Maschine, d.h. er verarbeitet bis
zu zwei individuell spezifizierbare Quell-Operanden zu einem Zieloperand, wobei alle
Operanden in Registern stehen.
Auf die durch Y und Z adressierten Operanden wird beim MMIX nur lesend zugegriffen.
Auf X wird sowohl lesend als auch schreibend zugegriffen.
264 6 MMIX-Prozessor
a) Vervollständigen Sie nachfolgende Schaltung des Registerblocks (engl. register
file so, dass
• an den Ausgängen $X, $Y und $Z die durch X, Y und Z spezifizierten
Register automatisch ausgegeben werden und
• das am Eingang $X anliegende Datenwort im Falle einer positiven Flanke
am clk-Eingang in das durch X spezifizierte Register übernommen wird.
01
255
64
64
64
64
8
$064 64
$164 64
$25564 64
01
255
64
64
64
64
8
01
255
64
64
64
64
8
$X
$Y
$Z
clk
$X64
64
64
64
X8
Y8
Z8
f
64 Bit,
diein Register3 gespeichert
• sick
3 •
•
6.5 MMIX Befehle 265
T b) Vervollständigen Sie nachfolgende Schaltung des Rechenwerks (= ALU = Arith-
metic Logic Unit) so, dass mit der Steuerleitung op (operation) die Ergebnisse der
verschiedenen integrierten Hardware-Schaltungen an den Ausgang durchgeschal-
tet werden können.
FSUB
b
aa-b
FADD
ADD
SUBb
aa-b
MUL
a >>u bb
a
a >>s bb
a
a << bb
a
a | bb
a
64
64
64
266 6 MMIX-Prozessor
c) Entwickeln Sie einen MMIX-Prozessor, der Register-Register-Befehle mit 8 Bit
vorzeichenlosen Direktoperanden Z ausführen kann sowie vorzeichenlose 16 Bit
Direktoperanden YZ in Register X ablegen kann.
Befehls-Speicher
Adresse
Daten
Allzweck-Registerblock
Z
Y
X
$X
8
8
8 64
64$Z
$Y
$X6464
ALU
Arithmetische Befehle auf Festkommazahlen
Befehl Operanden Name/Aktion Definition
ADD
$X,$Y,$Z Add; signed, with overflow
$X s 064(s($Y) + s($Z))
(s($Y) + s($Z) < �263) ||(s($Y) + s($Z) � 263))
rA rA|u064(2
6)
$X,$Y,Z Add immediate; signed, with overflow
$X s 064(s($Y) + u(Z))
(s($Y) + u(Z) < �263) ||(s($Y) + u(Z) � 263))
rA rA|u064(2
6)
ADDU$X,$Y,$Z Add unsigned; no overflow $X u0
64(u($Y) + u($Z))
ADD $1,62 ,$3 : i
Betehlszahce -
0×100 0×20010203pfzFt€ooxr04" . steering
" " ?>
,
' '
l,
I
< svi
.÷¥÷-
I
64-Lt
+1¥i
32'
IME-
① -
Thelxlylzo 05¥'T
6.5 MMIX Befehle 267
$X,$Y,Z Add unsigned; no overflow $X u064(u($Y) + u(Z))
SUB
$X,$Y,$Z Subtract; signed, with overflow
$X s 064(s($Y)� s($Z))
(s($Y)� s($Z) < �263) ||(s($Y)� s($Z) � 263))
rA rA|u064(2
6)
$X,$Y,Z Subtract immed.; signed, with ovf.
$X s 064(s($Y)� u(Z))
(s($Y)� u(Z) < �263) ||(s($Y)� u(Z) � 263))
rA rA|u064(2
6)
SUBU$X,$Y,$Z Subtract uns.; no ovf. $X u0
64(u($Y)� u($Z))$X,$Y,Z Subtract uns. immed.; no ovf. $X u0
64(u($Y)� u(Z))
NEG
$X,Y,$Z Negate; signed, with overflow
$X s 064(u(Y)� s($Z))
u(Y)� s($Z) � 263 )rA rA|u0
64(26)
$X,Y,Z Negate immediate; signed $X s 064(u(Y)� u(Z))
NEGU$X,Y,$Z Negate unsigned; no overflow $X s 0
64(u(Y)� s($Z))$X,Y,Z Negate unsigned immedidate $X s 0
64(u(Y)� u(Z))
MUL
$X,$Y,$Z Multiply; signed, with overflow
$X s 064(s($Y) · s($Z))
(s($Y) · s($Z) < �263) ||(s($Y) · s($Z) � 263))
rA rA|u064(2
6)
$X,$Y,Z Multiply immed.; signed, with ovf.
$X s 064(s($Y) · u(Z))
(s($Y) · s($Z) < �263) ||(s($Y) · s($Z) � 263))
rA rA|u064(2
6)
MULU$X,$Y,$Z Mult. uns.; 128 bit result rH$X u0
128(u($Y) · u($Z))$X,$Y,Z Mult. uns. imm.; 128 bit result rH$X u0
128(u($Y) · u(Z))
DIV
$X,$Y,$Z
Divide; signed $X s 064(bs($Y)/s($Z)c)
(case $Z 6= 0) rR s 064( s($Y) % s($Z) )
Divide signed $X u064(0)
(case $Z = 0) rR $Y
$X,$Y,Z
Divide immediate; signed $X s 064(bs($Y)/s(Z)c)
(case Z 6= 0) rR s 064( s($Y) % u(Z) )
Divide immediate; signed $X u064(0)
*
127 6463 O 63 o 63 o
MULU : ← . * zuscibzlich :
RH $X $4 $Z Bei Divan - cho
° 127 6463 o 63wired Bit ice RA
DIVU : ← : anfrgeseftf$X RD$4
$Z
268 6 MMIX-Prozessor
(case Z = 0) rR $Y
DIVU
$X,$Y,$Z
Divide uns.; 128 bit $X u064( bu(rD$Y)/u($Z)c )
case u($Z) > u(rD) rR u064( u(rD$Y) % u($Z) )
Divide uns.; 128 bit dividend $X rDno ovf.; case u($Z) u(rD) rR $Y
$X,$Y,Z
Divide uns. immed.; 128 bit $X u064( bu(rD$Y)/u(Z)c )
no overflow; case u(Z) > u(rD) rR u064( u(rD$Y) % u(Z) )
Divide uns. immed.; 128 bit $X rDno ovf.; case u(Z) u(rD) rR $Y
Direktoperand in Register schreiben
Befehl Operanden Name/Aktion Definition
SETL $X,YZ Set to low wyde $X u064(u(YZ))
Der Assembler akzeptiert statt SETL auch SET, um Direktoperanden in ein Register zu
laden. Wird SET mit einem Register als zweiter Operand aufgerufen, wird der Befehl SET$X,$Y in den Befehl OR $X,$Y,0 übersetzt.
T a) In welchem Wertebereich können die Direktoperanden bei den Arithmetischen
Befehlen liegen?
T b) Kann mit dem ADD Befehl 3 + 5 in einer einzigen Codezeile berechnet werden?
T c) Wie kann man 5� 3 in einer einzigen Codezeile berechnen?
6.5 MMIX Befehle 269
T d) Was ist der Unterschied zwischen den Befehlen MUL und MULU?
T e) Geben Sie die MMIX-Befehle an, mit denen Sie x = a2 + 2 · a · b + b2 mit Fest-
kommazahlen berechnen. Nehmen Sie an, dass die Register a, b, und c bereits
initialiert wurden und das Ergebnis in Register x gespeichert werden soll. Benutzen
Sie Register buf1, buf2, ... für Zwischenergebnisse, falls notwendig.
270 6 MMIX-Prozessor
Gegeben ist der folgende Programmcode:
a IS $0b IS $1c IS $2d IS $3buf1 IS $4buf2 IS $5
LOC #100Main SETL b,1
SETL c,2SETL d,3
f) Geben Sie MMIX-Befehle an, mit denen Sie a = c·d�bb+c+d mit Festkommazahlen
berechnen.
MUL bnfl , c. d
SUB but , bufhb
ADD buf2 ,be
ADD but 21 bakedDIV acbufl , buf2
6.5 MMIX Befehle 271
Umwandlung Gleitkommazahl$ Festkommazahl
Befehl Operanden Name/Aktion Definition
FLOT$X,$Z Convert fixed to floating $X f 0
64( s($Z) )
$X,Z Conv. fixed to float. imm. $X f 064( u(Z) )
FLOTU$X,$Z Conv. uns. fixed to floating $X f 0
64( u($Z) )
$X,Z Conv. uns. fixed to float.
imm.
$X f 064( u(Z) )
FIX $X,$ZConvert floating to fixed
with overflow
$X s 064( r( f64($Z) ) )
f64($Z) < �263 ) rA rA|u064(2
5)
f64($Z) > 263�1) rA rA|u064(2
5)
FIXU $X,$ZConvert floating to fixed
without overflow$X s 0
64( r( f64($Z) ) )
a) Welche Aktion führt der Operator r() aus?
b) Geben Sie den Befehl an, mit dem Sie Register 0 die Gleitkommazahl 15,0
zuweisen.
c) Geben Sie den Befehl an, mit dem Sie eine Gleitkommazahl in Register 1 in eine
Festkommazahl umwandeln.
tandem art Test bouma -Werk
FLOT $0,15
FIX $1.
$1
272 6 MMIX-Prozessor
Arithmetische Befehle auf Gleitkommazahlen
Befehl Operanden Name/Aktion Definition
FADD $X,$Y,$Z Floating point add $X f 064( f64($Y) + f64($Z) )
FSUB $X,$Y,$Z Floating point subtract $X f 064( f64($Y)� f64($Z) )
FMUL $X,$Y,$Z Floating point multiplication $X f 064( f64($Y) · f64($Z) )
FDIV $X,$Y,$Z Floating point divide $X f 064( f64($Y)/f64($Z) )
FSQRT $X,$Z Square root $X f 064(
pf64($Z) )
a) Geben Sie MMIX-Befehle an, die ⇡ = 3.1415 in Register a ablegen.
b) Geben Sie MMIX-Befehle an, mit denen Sie x = a2 + 2 · a · b + b2 mit Gleitkomma-
Operationen berechnen. Nehmen Sie an, dass Register a und b mit Festkomma-
zahlen initialisiert wurden und zunächst in Gleitkommazahlen umgewandelt werden
müssen. Speichern Sie das Ergebnis als Gleitkommazahl in Register x. Benutzen
Sie buf1, buf2, ... als Pufferregister.
SET bnfl ,31415
F LOT bufrcbnfSET buf2 , 10000
F LOT buf2,buf2FDIV a. bufr , but 2
F LOT a. a
Thot bib
Four bull , a. a
FML buff, a. b
FLOT but 4,2FML bwfz , but 21544FMUL buf3 , bib
FADD Xcbufl , but 2
FADD tix , buts
6.5 MMIX Befehle 273
T c) Geben Sie MMIX-Befehle an, die e = 2,718281828 in Register b ablegen.
274 6 MMIX-Prozessor
Schiebe-Befehle
Befehl Operanden Name/Aktion Definition
SL
$X,$Y,$Z Shift left; with overflow
$X u064( u($Y⌧ u($Z)) )
u($Y) · 2u($Z) � 264 )rA rA|u0
64(25)
$X,$Y,Z Shift left immediate; with ovf.
$X u064( u($Y⌧ u(Z)) )
u($Y) · 2u(Z) � 264 )rA rA|u0
64(25)
SLU$X,$Y,$Z Shift left uns., no overflow $X u0
64( u($Y⌧ u($Z)) )
$X,$Y,Z Shift left uns. immed.; no ovf. $X u064( u($Y⌧ u(Z)) )
SR$X,$Y,$Z Shift right; fill with sign $X $Y�s u($Z)$X,$Y,Z Shift right imm.; fill with sign $X $Y�s u(Z)
SRU$X,$Y,$Z Shift right unsigned; fill with 0 $X $Y�u u($Z)$X,$Y,Z Shift right uns. imm.; fill w. 0 $X $Y�u u(Z)
6.5 MMIX Befehle 275
a) Wie unterscheiden sich der SR und der SRU Befehl?
b) In Register fpn ist eine 64 Bit Gleitkommazahl abgelegt.63 62 52 51 0
Inhalt Register fpn: s e f
Geben Sie die MMIX-Befehle an, mit denen Sie s, e und f aus Register fpn
extrahieren und in Register s, e und f ablegen.
° SR filet freiwerdenok Stellar unit alan
MSB auf° SRU filler fseiweoeenoee stellar unit O auf
S : U- - - - . .
.. O S
SRU S, fpn , 63
e : o . - --
- one
Iss'¥EfI¥:LSLU e
, fpu ,A AND e
, e. butSRU e
,e , 53
o- -
- -
O-I f
SLU f ,fpn.AZSRU La fill
276 6 MMIX-Prozessor
Logische Operationen auf Bit-Ebene
Befehl Operanden Name/Aktion Definition
AND$X,$Y,$Z Bitwise AND $X $Y& $Z$X,$Y,Z Bitwise AND immediate $X $Y& u0
64( u(Z) )
ANDN$X,$Y,$Z Bitwise AND NOT $X $Y& ⇠ $Z$X,$Y,Z Bitww AND NOT immed. $X $Y& ⇠ u0
64( u(Z) )
ANDNL $X,YZ Bitw. AND NOT low wyde $X $X& ⇠ u064( u(YZ) )
ANDNML $X,YZ Bw. AND NOT med. l. wd. $X $X& ⇠ ( u064( u(YZ) )⌧ 16)
ANDNMH $X,YZ Bw. AND NOT med. h. wd. $X $X& ⇠ ( u064( u(YZ) )⌧ 32)
ANDNH $X,YZ Bw. AND NOT high wyde $X $X& ⇠ ( u064( u(YZ) )⌧ 48)
NAND$X,$Y,$Z Bitwise NOT AND $X ⇠ ($Y& $Z)$X,$Y,Z Bitwise NOT AND immed. $X ⇠ ( $Y& u0
64( u(Z) ) )
OR$X,$Y,$Z Bitwise OR $X $Y | $Z$X,$Y,Z Bitwise OR immediate $X $Y | u0
64( u(Z) )
ORL $X,YZ Bitwise OR low wyde $X $X | u064( u(YZ) )
ORML $X,YZ Bitw. OR med. low wyde $X $X | ( u064( u(YZ) )⌧ 16)
ORMH $X,YZ Bitw. OR med. high wyde $X $X | ( u064( u(YZ) )⌧ 32)
ORH $X,YZ Bitwise OR high wyde $X $X | ( u064( u(YZ) )⌧ 48)
ORN$X,$Y,$Z Bitwise OR NOT $X $Y | ⇠ $Z$X,$Y,Z Bitwise OR NOT immediate $X $Y | ⇠ u0
64( u(Z) )
NOR$X,$Y,$Z Bitwise NOT OR $X ⇠ ($Y | $Z)$X,$Y,Z Bitwise NOT OR immediate $X ⇠ ($Y | u0
64( u(Z) ) )
XOR$X,$Y,$Z Bitwise XOR $X $Y⌦ $Z$X,$Y,Z Bitwise XOR immediate $X $Y⌦ u0
64( u(Z) )
NXOR$X,$Y,$Z Bitwise NOT XOR $X ⇠ ($Y⌦ $Z)$X,$Y,Z Bitw. NOT XOR immediate $X ⇠ ($Y⌦ u0
64( u(Z) ) )
63 4847 3231 1615 O
It MH ML L
X
X
x
6.5 MMIX Befehle 277
Bits löschen
a) Welche Befehle verwendet man typischerweise um einzelne Bits zu löschen?
b) Geben Sie an, wie Sie mit dem Befehl ANDNML Bit 21 in Register a löschen.
T c) Geben Sie an, wie Sie mit dem Befehl ANDN Bit 21 in Register a löschen.
d) Geben Sie an, wie Sie mit einem NAND und einem AND-Befehl Bit Nr. 21 löschen.
Bits setzen
a) Welche Befehle verwendet man typischerweise um Bits zu setzen?
UND - Befehle9%99%50
O O 20
%. . .
. ...Ton
.. . . .
on I 4111.45°
0×0020 µis . . .lt
0000000000200000 ANDNML a , # 20/ ( 23
. - .20
0010
OronIon or
-
0101SETbut, lStfubuf , buf ,21
NEG buff , 0,1Oder so :
SUBUbuf , bufz , buy } NAND bufibuf.by
AND a. a , buf
ODER - Befehle
278 6 MMIX-Prozessor
b) Geben Sie die Befehle, mit denen Sie in Register a Bit 20 mit einem OR-Befehl auf1 setzen.
T c) Geben Sie an, wie Sie in Register a Bit 20 mit einem ORML-Befehl auf 1 setzen.
XOR
a) Erklären Sie den Effekt einer XOR-Operation.
b) Was wird dem Ziel-Operanden einer XOR-Operation zugewiesen, wenn alle Bits
des einen Quell-Operanden gelöscht (0) sind?
c) Was wird dem Ziel-Operanden einer XOR-Operation zugewiesen, wenn alle Bits
des einen Quell-Operanden gesetzt (1) sind?
d) Geben Sie die Befehle an, mit denen Sie alle Bits in Register a invertieren.
SET buf ,A
SLU but , buf,20
OR a , buf ,a
63 3h 16 O
ORM La , # to
- .0000 000000010000
-0×0010
00
Eat :der under Quell - ope - and
die inverter ten Bits des condemn
Quell - operand
011001 NEG but ,0,1¥⑦ rerun
100110FOR a
, a. boy
# gift"
- r"
,d. U . ler . . . . . r
6.5 MMIX Befehle 279
Register-Speicher-Befehle
Der MMIX ist eine Load-Store-Architektur. Speicherzugriffe erfolgen damit nicht implizit,
sondern müssen explizit durch eigene Lade- und Speicherbefehle durchgeführt werden.
Da das Befehlswort des MMIX nur 32 Bit breit ist, kann es keine Speicheradressen
aufnehmen. Beim MMIX wird dieses Problem dadurch gelöst, dass bei Lade- und
Speicherbefehlen das durch das Befehlswort spezifizierte Y-Register eine Basisadresse
enthält und Z bzw. $Z einen Offset festlegt, der auf zur Basisadresse addiert wird
(Basisadressen werden häufig durch GREG-Befehle in globale Register geschrieben).
Das Additionsergebnis ist 64 Bit breit und wird als Adresse verwendet.
a) Erweitern Sie nachfolgende Prozessor-Schaltung um die Fähigkeit, Lade- und
Speicherzugriffe durchzuführen.
Befehls-Speicher
Adresse
Daten
Allzweck-Registerblock
Z
Y
X
$X
8
8
8 64
64$Z
$Y
$X6464
ALU
15…0 16
048
01
Add
BZ64 64
4
327…0
15…8
23…16
0
10
5664
Steuerung
31…24
8
* 2. B . Bgkcwgde,Tetra
. - .
Vorzcicheu Los I Uorzci cheer -
behaftef
u u
o a V
Zugriffs -
cue
Art*
> Dalen -
n FuyangDalen -
Ausg .
>
• s Adsesse
TDaleuspeicher
280 6 MMIX-Prozessor
Daten vom Speicher in ein Register laden
Befehl Operanden Name/Aktion Definition
LDB$X,$Y,$Z Load byte $X s 0
64(s(M1[u($Y) + u($Z)]))$X,$Y,Z Load byte immediate $X s 0
64(s(M1[u($Y) + u(Z)]))
LDBU$X,$Y,$Z Load byte unsigned $X u0
64(u(M1[u($Y) + u($Z)]))$X,$Y,Z Load byte uns. immed. $X u0
64(u(M1[u($Y) + u(Z)]))
LDW$X,$Y,$Z Load wyde $X s 0
64(s(M2[u($Y) + u($Z)]))$X,$Y,Z Load wyde immediate $X s 0
64(s(M2[u($Y) + u(Z)]))
LDWU$X,$Y,$Z Load wyde unsigned $X u0
64(u(M2[u($Y) + u($Z)]))$X,$Y,Z Load wyde uns. immed. $X u0
64(u(M2[u($Y) + u(Z)]))
LDT$X,$Y,$Z Load tetra $X s 0
64(s(M4[u($Y) + u($Z)]))$X,$Y,Z Load tetra immediate $X s 0
64(s(M4[u($Y) + u(Z)]))
LDTU$X,$Y,$Z Load tetra unsigned $X u0
64(u(M4[u($Y) + u($Z)]))$X,$Y,Z Load tetra uns. immed. $X u0
64(u(M4[u($Y) + u(Z)]))
LDO$X,$Y,$Z Load octa $X M8[u($Y) + u($Z)]$X,$Y,Z Load octa immediate $X M8[u($Y) + u(Z)]
LDOU$X,$Y,$Z Load octa unsigned $X M8[u($Y) + u($Z)]$X,$Y,Z Load octa uns. immed. $X M8[u($Y) + u(Z)]
6.5 MMIX Befehle 281
T a) Welche Wortgrößen kann der MMIX vom Speicher in Register laden?
T b) Was ist der Unterschied zwischen vorzeichenbehaftetem (signed) und vorzeichen-
losen (unsigned) Laden?
T c) Warum muss man zwischen vorzeichenlosem und vorzeichenbehaftetem Laden
unterscheiden?
T d) Wie unterscheiden sich die Namen der vorzeichenlosen und vorzeichenbehafteten
Ladebefehle?
282 6 MMIX-Prozessor
T e) Wie unterscheiden sich die Opcodes von vorzeichenlosen und vorzeichenbehaf-
teten Ladebefehlen?
f) Nehmen Sie an, dass die vorzeichenbehaftete 8 Bit breite Zahl -64 mit dem
LDB-Befehl in ein Allzweckregister geladen wurde und geben Sie alle Bits des
Allzweckregisters in hexadezimaler Notation aus.
g) Welcher Wert würde im Allzweckregister stehen, wenn die Zahl -64 versehentlich
mit einem LDBU-Befehl statt mit einem LDB-Befehl in das Allzweckregister geladen
worden wäre? Geben Sie den Wert in der Basis 10 an.
T h) Wie können die Ladebefehle 64 Bit breite Speicheradressen adressieren, obwohl
im Befehlswort nur 16 Bit zur Darstellung der Adresse verfügbar sind?
64 : 01000000
-64 : 10111 he A er = 1100 oooo = OXCO
Ox FFF 't FFFF FFFF FFCO
0×00000000 0000 OOCO = 192
6.5 MMIX Befehle 283
i) Vervollständigen Sie den nachfolgenden MMIX-Code um die Bereitstellung und
Initialisierung eines Basisregisters zur Adressierung von A, B und C.
LOC #2000000000000000
A BYTE 0B OCTA #FFFFC OCTA
LOC #100
Main LDO $0,B...
! "#$%
!"#"$% &'()*+,-.%(*/%012'(*/%!&'(!)*+*,-(#.*-/!01234/*5!67*8434/*9!:;</!=*8>((!7'3,+4-=*7/*<!?'@*--*!A@*<(*BCBD!!
0x..0 0x..1 0x..2 0x..3 0x..4 0x..5 0x..6 0x..7
TRAP 5ν FCMP ν FUN ν FEQL ν FADD 4ν FIX 4ν FSUB 4ν FIXU 4ν
FMUL 4ν FCMPE 4ν FUNE ν FEQLE 4ν FDIV 40ν FSQRT 40ν FREM 4ν FINT 4ν
SETH ν SETMH ν SETML ν SETL ν INCH ν INCHM ν INCML ν INCL νORH ν ORMH ν ORML ν ORL ν ANDNH ν ANDNMH ν ANDNML ν ANDNL ν
POP 3ν RESUME 5ν SYNC ν SWYM ν GET ν TRIP 5ν0x..8 0x..9 0x..A 0x..B 0x..C 0x..D 0x..E 0x..F
SUB[I] ν
CSNP[I] νZSP[I] ν
SUBU[I] ν16ADDU[I] νNEGU[I] νSRU[I]ν
BOD[B] ν+πBEV[B] ν+πPBOD[B] 3ν-π
CMPU[I] νSLU[I] νBZ[B] ν+πBNZ[B] ν+πPBZ[B] 3ν-π
CSNZ[I] νZSZ[I] ν
ADD[I] ν
CSNN[I] νZSN[I] ν
ADDU[I] ν4ADDU[I] ν
PBNZ[B] 3ν-πCSZ[I] ν
0x0.. 0x0..FLOT[I] 4ν FLOTU[I] 4ν SFLOT[I] 4ν SFLOTU[I] 4ν
PUSHJ[B] ν GETA[B] ν PUT[I] ν[UN]SAVE 20µ+ν
XOR[I] νNXOR[I] νODIF[I] νMXOR[I] ν
STWU[I] µ+νSTOU[I] µ+νSTUNC[I] µ+νPUSHGO[I] 3ν
LDWU[I] µ+νLDOU[I] µ+νLDUNC[I] µ+νGO[I] 3ν
CSOD[I] νPBEV[B] 3ν-π
ZSEV[I] ν
CSEV[I] νZSOD[I] ν
NAND[I] νTDIF[I] νMOR[I] ν
STO[I] µ+νSTCO[I] µ+νSYNCID[I] νNOR[I] ν
LDO[I] µ+νCSWAP[I] 2µ+2νPREGO[I] νSTW[I] µ+ν
PBNP[B] 3ν-πCSP[I] ν
ZSNP[I] νLDW[I] µ+ν
BNP[B] ν+πPBP[B] 3ν-π
8ADDU[I] νNEG[I] νSR[I] νBP[B] ν+π
ORN[I] νANDN[I] νWDIF[I] νSADD[I] ν
STBU[I] µ+νSTTU[I] µ+νSTHT[I] µ+νPREST[I] ν
LDBU[I] µ+νLDTU[I] µ+νLDHT[I] µ+νPRELD[I] ν
ZSNZ[I] ν
BDIF[I] νMUX[I] ν
JMP[B] ν
STSF[I] µ+νSYNCD[I] νOR[I] νAND[I] ν
LDSF[I] µ+νLDVTS[I] νSTB[I] µ+νSTT[I] µ+ν
BNN[B] ν+πPBN[B] 3ν-πPBNN[B] 3ν-πCSN[I] ν
ZSNN[I] νLDB[I] µ+νLDT[I] µ+ν
2ADDU[I] νCMP[I] νSL[I] νBN[B] ν+π
0xC..
0xD..
0xE..
0xF..
0x8..
0x9..
0xA..
0xB..
0xD..
0xE..
0xF..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x9..
0xA..
0xB..
0xC..
0x5..
0x6..
0x7..
0x8..
0x1..
0x2..
0x3..
0x4..
MUL[I] 10ν MULU[I] 10ν DIV[I] 60ν DIVU[I] 60ν
!!!&'(!*<(B*!E;@@-*!0F!);B#G*<B9!/*(!1234/*(!*7B(2<;3,B!/*<!&422*-C*;-*!0H!@;(!IJ95! ;7!/*<!(;3,!/*<!)*#+*,-(34/*!@*+;7/*BD!!!&'(!C:*;B*!E;@@-*!/*(!1234/*(!*<=;@B!(;3,!:;*!+4-=BK!!
−! 6L)!0);B!E<D!"9!/*(!C:*;B*7!E;@@-*(!+! H5!:*77!(;3,!/*<!)*+*,-!;8!4@*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!+! I5!:*77!(;3,!/*<!)*+*,-!;8!M7B*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!!
!−! );B(!$5!I!M7/!H!/*(!C:*;B*7!E;@@-*(!*7B(2<*3,*7!/*<!%&'$("!0H!@;(!%95!;7!/*8!(;3,!/*<!)*+*,-(#34/*!@*+;7/*B!
![I]!@*/*MB*BK!N88*/;'B*#O'<;'7B*!/*(!)*+*,-(!
−! ;88*/;'B*!⇔!&;<*PB42*<'7/!−! ADD $1,$2,$3K!7;3,B!;88*/;'B*5!/'!/*<!"D!12*<'7/!*;7!Q*=;(B*<!;(B!M7/!P*;7*!R',-!−! ADD $1,$2,3K!;88*/;'B*5!/'!'-(!"D!12*<'7/!*;7*!R',-!'7=*=*@*7!;(B!M7/!P*;7!Q*=;(B*<!−! /*<! 1234/*! /*<! ;88*/;'B*#O'<;'7B*! *;7*(! )*+*,-(! ;(B! ;88*<! M8! I! ,S,*<! '-(! /;*! 7;3,B#;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!0(B*,B!;7!/*<!&422*-)&'$("!'-(4!<*3,B(9!
−! *;7*! ;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!:;</!T48!U((*8@-*<!'MB48'B;(3,!'7,'7/!/*(! +*,-*7/*7!&4--'<#R*;3,*7(! 0$9! *<P'77B5! :*(,'-@! ;8! V<4=<'88! 7;3,B! *W2-;C;B!ADDI! =*(3,<;*@*7! :*</*7!8M((!!!
284 6 MMIX-Prozessor
Gegeben ist der nachfolgende MMIX-Programmcode:
LOC #2000000000000000GREG @ $254 @
a IS $1
X BYTE 0Y WYDE #FFFFZ OCTA
LOC #100
Main ... ...... ...
j) In welches Befehlswort würde der MMIX-Assembler LDB a,X übersetzen?
k) In welches Befehlswort würde der MMIX-Assembler LDT a,Y übersetzen?
l) In welches Befehlswort würde der MMIX-Assembler LDO a,Z übersetzen?
T m) Geben Sie alle 64 Bit des Registers $1 nach Ausführung des Befehls LDBU a,Y an.
T n) Geben Sie alle 64 Bit des Registers $1 nach Ausführung des Befehls LDB a,Y an.
$254 to
Tubercle
⇐
-
I.
.0×810100# 0×20 - - -
02
- =$2s#%0×89
AFEOZµ
0×20 . . .
08--8254+80×8501FE 08
--
6.5 MMIX Befehle 285
o) Tragen Sie in nachfolgende Tabelle den Speicherinhalt ein, der sich nach Aus-
führung der angegebenen MMIX-Befehle im Falle von Big- und Little-Endian-
Adressierung ergeben würde.
LOC Data_SegmentGREG @BYTE 1TETRA #23456789TETRA #ABCDEF01BYTE #77WYDE #0123
0x2000000000000000
0x2000000000000001
0x2000000000000002
0x2000000000000003
0x2000000000000004
0x2000000000000005
0x2000000000000006
0x2000000000000007
0x2000000000000008
0x2000000000000009
0x200000000000000A
0x200000000000000B
0x200000000000000C
0x200000000000000D
0x200000000000000E
0x200000000000000F
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Adresse Niederwert. vier Adress-Bits
Big Endian Little Endian
$254 ← 0×20 -- . O
0×01 0×012 I
-
I
? ?
? ?
Ox 23 Ox 8g
0×45 0×67
0×67 0×45
or 8g 0×23
OXAB Oxon
OX CD Ox Et
O X EF Ox CD
0×01 Ox AB
0×77 0×77? 2
C•
0×01 0×23
0×23 0×01
286 6 MMIX-Prozessor
p) Nehmen Sie die gezeigte Speicherbelegung an und geben Sie hexadezimal alle 64
Bit des Registers 0 nach Ausführung der folgenden Befehle an:
LDB $0,$254,0:
LDB $0,$254,4:
LDB $0,$254,9:
LDBU $0,$254,9:
LDT $0,$254,4:
LDT $0,$254,5:
LDT $0,$254,9:
LDTU $0,$254,9:
LDO $0,$254,0:
LDO $0,$254,1:
LDO $0,$254,12:
0800000000 0000 0001
0800000000 0000 0023
7- O
OX FFFF FF FF FF FF FF CD Ox CD : 11001101
0800000000 0000 00 CD
0×0000 00002345 6789
0×0000 00002345 6789
OXFFFFFFFF ABCD E For
0×00000000 ABCD Eton
0×01? ? ? ? ? ? 23456789
0×01? ? ? ? ? ? 23456789
Ox ABCD EFOA 77 ? ? 0123
6.5 MMIX Befehle 287
T q) Tragen Sie in nachfolgende Tabelle den Speicherinhalt ein, der sich nach Aus-
führung der angegebenen MMIX-Befehle im Falle von Big- und Little-Endian-
Adressierung ergeben würde.
LOC Data_SegmentGREG @ @ $254BYTE 1WYDE #1234OCTA #56789ABC
0x2000000000000000
0x2000000000000001
0x2000000000000002
0x2000000000000003
0x2000000000000004
0x2000000000000005
0x2000000000000006
0x2000000000000007
0x2000000000000008
0x2000000000000009
0x200000000000000A
0x200000000000000B
0x200000000000000C
0x200000000000000D
0x200000000000000E
0x200000000000000F
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
Adresse Niederwert. vier Adress-Bits
Big Endian Little Endian
288 6 MMIX-Prozessor
T r) Nehmen Sie die gezeigte Speicherbelegung an und geben Sie hexadezimal alle 64
Bit des Registers 0 nach Ausführung der folgenden Befehle an:
LDB $0,$254,3:
LDB $0,$254,14:
LDBU $0,$254,15:
LDT $0,$254,14:
LDTU $0,$254,15:
6.5 MMIX Befehle 289
Daten vom Register in den Speicher schreiben (speichern)
Befehl Operanden Name/Aktion Definition
STB
$X,$Y,$Z Store byte; with overflow
M1[u($Y) + u($Z)] ($X)7...0
s($X) � 27 ) rA rA | u064(2
6)
s($X) < �27 ) rA rA | u064(2
6)
$X,$Y,Z Store byte immed.; ovf.
M1[u($Y) + u(Z)] ($X)7...0
s($X) � 27 ) rA rA | u064(2
6)
s($X) < �27 ) rA rA | u064(2
6)
STBU$X,$Y,$Z Store byte unsigned M1[u($Y) + u($Z)] ($X)7...0
$X,$Y,Z Store byte uns. imm. M1[u($Y) + u(Z)] ($X)7...0
STW
$X,$Y,$Z Store wyde; with overflow
M2[u($Y) + u($Z)] ($X)15...0
s($X) � 215 ) rA rA | u064(2
6)
s($X) < �215 ) rA rA | u064(2
6)
$X,$Y,Z Store wyde immed.; ovf.
M2[u($Y) + u(Z)] ($X)15...0
s($X) � 215 ) rA rA | u064(2
6)
s($X) < �215 ) rA rA | u064(2
6)
STWU$X,$Y,$Z Store wyde unsigned M2[u($Y) + u($Z)] ($X)15...0
$X,$Y,Z Store wyde uns. imm. M2[u($Y) + u(Z)] ($X)15...0
STT
$X,$Y,$Z Store tetra; with overflow
M4[u($Y) + u($Z)] ($X)31...0
s($X) � 231 ) rA rA | u064(2
6)
s($X) < �231 ) rA rA | u064(2
6)
$X,$Y,Z Store tetra immed.; ovf.
M4[u($Y) + u(Z)] ($X)31...0
s($X) � 231 ) rA rA | u064(2
6)
s($X) < �231 ) rA rA | u064(2
6)
STTU$X,$Y,$Z Store tetra unsigned M4[u($Y) + u($Z)] ($X)31...0
$X,$Y,Z Store tetra uns. imm. M4[u($Y) + u(Z)] ($X)31...0
STO$X,$Y,$Z Store octa M8[u($Y) + u($Z)] $X$X,$Y,Z Store octa immediate M8[u($Y) + u(Z)] $X
STOU$X,$Y,$Z Store octa unsigned M8[u($Y) + u($Z)] $X$X,$Y,Z Store octa uns. imm. M8[u($Y) + u(Z)] $X
STCOX,$Y,$Z Store constant octabyte M8[u($Y) + u($Z)] u0
64( u(X) )
X,$Y,Z Store const. octa imm. M8[u($Y) + u(Z)] u064( u(X) )
STHT$X,$Y,$Z Store high tetra M4[u($Y) + u($Z)] ($X�u 32)
$X,$Y,Z Store high tetra imm. M4[u($Y) + u(Z)] ($X�u 32)
290 6 MMIX-Prozessor
Befehl Operanden Name/Aktion Definition
STSF$X,$Y,$Z Store short float M4[u($Y) + u($Z)] f �1
32 (f64($X))$X,$Y,Z Store short float imm. M4[u($Y) + u(Z)] f �1
32 (f64($X))
STUNC$X,$Y,$Z Store uncached M8[u($Y) + u($Z)] $X$X,$Y,Z Store uncached imm. M8[u($Y) + u(Z)] $X
T a) Wie unterscheidet sich die Verwendung von X, Y und Z bei Speicher-Befehle von
derjenigen aller anderen MMIX-Befehle?
T b) Was ist beim MMIX der Unterschied zwischen vorzeichenbehaftetem und vorzei-
chenlosem Speichern?
6.5 MMIX Befehle 291
In folgendem Programmcode wird XXX XXXXXXXX als Platzhalter für einen einzelnen
Befehl verwendet:
LOC Data_SegmentGREG @
A OCTA #FFFF FFFF FFFF FFFFB TETRA #8765 4321
LOC #100Main LDTU $0,B
XXX XXXXXXXXTRAP 0,Halt,0
c) Geben Sie für das oben gezeigte Programm den Inhalt des 64 Bit breiten Wortes
an, welches durch die Marke A adressiert wird, wenn XXX XXXXXXXX durch folgende
Befehle ersetzt wird:
STB $0,A:
STTU $0,A:
STT $0,$254,6:
T d) Geben Sie für das oben gezeigte Programm den Inhalt des 64 Bit breiten Wortes
an, welches durch die Marke A adressiert wird, wenn XXX XXXXXXXX durch folgende
Befehle ersetzt wird:
STW $0,A:
STWU $0,A:
STT $0,A:
STO $0,A:
STB $0,$254,5:
STW $0,$254,1:
ST0 $0,$254,5:
0×20 . . . o
" " "
yoxzo. .
not
I $254 C- 0×20 - . .O
cI I I
$0 ←
0×0000000087654321*2--2
0×21 FF FF FF FFFF FFFF
0×8765 4321 FFFFFFFF
OXFFFF FFFF 87654321
292 6 MMIX-Prozessor
e) Geben Sie hexadezimal das 32 Bit breite Befehlswort des Befehls STBU $0,A an,
wenn dieser in obigem Programmcode den Platzhalter XXX XXXXXXXX ersetzt.
T f) Geben Sie die Befehle an, mit denen Sie
• an Adresse 0x2000 0000 0000 0000 ein 64 Bit breites Datum anlegen,
• dieses Datum über die Marke Data ansprechbar machen und
• das Datenwort mit 0x1234 5678 initialisieren;
• an Adresse 0x100 ein Programm beginnen und
• das an Adresse Data gespeicherte Datenwort in Register 1 einlesen,
• Bits 7 ... 0 des Registers 1 an Adresse Data schreiben,
• Bits 7 ... 0 des Registers 1 an Adresse 0x2000 0000 0000 0002 schreiben,
• Bits 31 ... 0 des Registers 1 an Adresse 0x2000 0000 0000 000A schreiben.
Basis
qtr$254
° X A 3 00 EEoffOffset o
I ans Ta Selle
6.5 MMIX Befehle 293
Gegeben ist der folgende Programmcode:
LOC Data_SegementGREG @
Label OCTA #1234 5678
LOC #100Main LDO $0,Label
STB $0,LabelLDA $2,LabelSTB $0,$2,2STT $0,$2,10
T g) Zeichnen Sie byteweise den Inhalt des Speichers von Adresse 0x20 ... 00 bis
0x20 ... 00F, der sich nach Ausführung des o.g. Programms ergibt.
294 6 MMIX-Prozessor
Adressen in ein Register laden
Befehl Operanden Name/Aktion Definition
LDA$X,$Y,$Z Get address (absolute) $X u0
64(u($Y) + u($Z))$X,$Y,Z Get address immed. (absolute) $X u0
64(u($Y) + u(Z))
GETA $X,YZ Get address (relativ) $X u064(u(@) + 4 · s(YZ))
! "#$%
!"#"$% &'()*+,-.%(*/%012'(*/%!&'(!)*+*,-(#.*-/!01234/*5!67*8434/*9!:;</!=*8>((!7'3,+4-=*7/*<!?'@*--*!A@*<(*BCBD!!
0x..0 0x..1 0x..2 0x..3 0x..4 0x..5 0x..6 0x..7
TRAP 5ν FCMP ν FUN ν FEQL ν FADD 4ν FIX 4ν FSUB 4ν FIXU 4ν
FMUL 4ν FCMPE 4ν FUNE ν FEQLE 4ν FDIV 40ν FSQRT 40ν FREM 4ν FINT 4ν
SETH ν SETMH ν SETML ν SETL ν INCH ν INCHM ν INCML ν INCL νORH ν ORMH ν ORML ν ORL ν ANDNH ν ANDNMH ν ANDNML ν ANDNL ν
POP 3ν RESUME 5ν SYNC ν SWYM ν GET ν TRIP 5ν0x..8 0x..9 0x..A 0x..B 0x..C 0x..D 0x..E 0x..F
SUB[I] ν
CSNP[I] νZSP[I] ν
SUBU[I] ν16ADDU[I] νNEGU[I] νSRU[I]ν
BOD[B] ν+πBEV[B] ν+πPBOD[B] 3ν-π
CMPU[I] νSLU[I] νBZ[B] ν+πBNZ[B] ν+πPBZ[B] 3ν-π
CSNZ[I] νZSZ[I] ν
ADD[I] ν
CSNN[I] νZSN[I] ν
ADDU[I] ν4ADDU[I] ν
PBNZ[B] 3ν-πCSZ[I] ν
0x0.. 0x0..FLOT[I] 4ν FLOTU[I] 4ν SFLOT[I] 4ν SFLOTU[I] 4ν
PUSHJ[B] ν GETA[B] ν PUT[I] ν[UN]SAVE 20µ+ν
XOR[I] νNXOR[I] νODIF[I] νMXOR[I] ν
STWU[I] µ+νSTOU[I] µ+νSTUNC[I] µ+νPUSHGO[I] 3ν
LDWU[I] µ+νLDOU[I] µ+νLDUNC[I] µ+νGO[I] 3ν
CSOD[I] νPBEV[B] 3ν-π
ZSEV[I] ν
CSEV[I] νZSOD[I] ν
NAND[I] νTDIF[I] νMOR[I] ν
STO[I] µ+νSTCO[I] µ+νSYNCID[I] νNOR[I] ν
LDO[I] µ+νCSWAP[I] 2µ+2νPREGO[I] νSTW[I] µ+ν
PBNP[B] 3ν-πCSP[I] ν
ZSNP[I] νLDW[I] µ+ν
BNP[B] ν+πPBP[B] 3ν-π
8ADDU[I] νNEG[I] νSR[I] νBP[B] ν+π
ORN[I] νANDN[I] νWDIF[I] νSADD[I] ν
STBU[I] µ+νSTTU[I] µ+νSTHT[I] µ+νPREST[I] ν
LDBU[I] µ+νLDTU[I] µ+νLDHT[I] µ+νPRELD[I] ν
ZSNZ[I] ν
BDIF[I] νMUX[I] ν
JMP[B] ν
STSF[I] µ+νSYNCD[I] νOR[I] νAND[I] ν
LDSF[I] µ+νLDVTS[I] νSTB[I] µ+νSTT[I] µ+ν
BNN[B] ν+πPBN[B] 3ν-πPBNN[B] 3ν-πCSN[I] ν
ZSNN[I] νLDB[I] µ+νLDT[I] µ+ν
2ADDU[I] νCMP[I] νSL[I] νBN[B] ν+π
0xC..
0xD..
0xE..
0xF..
0x8..
0x9..
0xA..
0xB..
0xD..
0xE..
0xF..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x9..
0xA..
0xB..
0xC..
0x5..
0x6..
0x7..
0x8..
0x1..
0x2..
0x3..
0x4..
MUL[I] 10ν MULU[I] 10ν DIV[I] 60ν DIVU[I] 60ν
!!!&'(!*<(B*!E;@@-*!0F!);B#G*<B9!/*(!1234/*(!*7B(2<;3,B!/*<!&422*-C*;-*!0H!@;(!IJ95! ;7!/*<!(;3,!/*<!)*#+*,-(34/*!@*+;7/*BD!!!&'(!C:*;B*!E;@@-*!/*(!1234/*(!*<=;@B!(;3,!:;*!+4-=BK!!
−! 6L)!0);B!E<D!"9!/*(!C:*;B*7!E;@@-*(!+! H5!:*77!(;3,!/*<!)*+*,-!;8!4@*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!+! I5!:*77!(;3,!/*<!)*+*,-!;8!M7B*<*7!?*;-!/*<!&422*-!"#$"!@*+;7/*B!!
!−! );B(!$5!I!M7/!H!/*(!C:*;B*7!E;@@-*(!*7B(2<*3,*7!/*<!%&'$("!0H!@;(!%95!;7!/*8!(;3,!/*<!)*+*,-(#34/*!@*+;7/*B!
![I]!@*/*MB*BK!N88*/;'B*#O'<;'7B*!/*(!)*+*,-(!
−! ;88*/;'B*!⇔!&;<*PB42*<'7/!−! ADD $1,$2,$3K!7;3,B!;88*/;'B*5!/'!/*<!"D!12*<'7/!*;7!Q*=;(B*<!;(B!M7/!P*;7*!R',-!−! ADD $1,$2,3K!;88*/;'B*5!/'!'-(!"D!12*<'7/!*;7*!R',-!'7=*=*@*7!;(B!M7/!P*;7!Q*=;(B*<!−! /*<! 1234/*! /*<! ;88*/;'B*#O'<;'7B*! *;7*(! )*+*,-(! ;(B! ;88*<! M8! I! ,S,*<! '-(! /;*! 7;3,B#;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!0(B*,B!;7!/*<!&422*-)&'$("!'-(4!<*3,B(9!
−! *;7*! ;88*/;'B*#O'<;'7B*!/*(!)*+*,-(!:;</!T48!U((*8@-*<!'MB48'B;(3,!'7,'7/!/*(! +*,-*7/*7!&4--'<#R*;3,*7(! 0$9! *<P'77B5! :*(,'-@! ;8! V<4=<'88! 7;3,B! *W2-;C;B!ADDI! =*(3,<;*@*7! :*</*7!8M((!!!
a) Was ist der Unterschied zwischen dem Befehl LDA und den Ladebefehlen LDB, ... ?
Behrle since immer
4 Byte breitO
!LDA $0 , A Befhlszirhkr INutall der Behrle
LDA : Basis register ist All z weak register $4
offset ist At oder Z
GETA : Basis register ist der Belches taller
Offset ist vorzcichenbehafhet YE
6.5 MMIX Befehle 295
Nehmen Sie die folgenden Befehle an:
LOC Data_SegmentGREG @ $254 @
A BYTE #12
LOC #100Main LDA $0,A
TRAP 0,Halt,0
b) Der Assembler übersetzt den Befehl LDA $0,A in 0x2300FE00. Warum?
Gegeben sind die folgenden Befehle:
LOC Data_SegmentGREG @
A BYTE #12
LOC #100Main LDA $0,A
GETA $0,MainTRAP 0,Halt,0
c) In welches 32 Bit breite Befehlswort wird der Befehl GETA $0,Main übersetzt?
Bunsis register
I ,offset
↳ aus Tarbell e
ADDU : 0×23Basisregister wud offset werden our A does se
rt
A dresses-
0×100
0×1040×108
O X F
500FFF F
in
- A im 2e - Kamp I.
296 6 MMIX-Prozessor
Zugriff auf Spezialregister
Befehl Operanden Name/Aktion Definition
GET $X,Z Get value of special purpose register $X S(Z)
PUTX,$Z Put value to special purpose register S(X) $ZX,Z Put immed. value to spec. purp. reg. S(X) u0
64(u(Z))
T a) Tragen Sie in nachfolgender Befehlssequenz Befehle zur Berechnung der Fest-
kommadivisioni dividend/divisor ein und speichern Sie das Ergebnis an der
Marke Quotient und den Divisionsrest an der Marke Remainder ab.
LOC Data_SegmentGREG @
Dividend OCTA 7Divisor OCTA 3Quotient OCTARemainder OCTA
dividend IS $0divisor IS $1quotient IS $2remainder IS $3
LOC #100Main LDO dividend,Dividend
LDO divisor,Divisor
TRAP 0,Halt,0
6.5 MMIX Befehle 297
Gegeben ist das Format des Spezialregisters rA.
0 0 R1 R0 D V W I O U Z X D V W I O U Z X
Interrupt Enable (Freischalten) Interrupt Event (Auftreten)
Gleitkommazahl ungenau (z.B. 1.0 / 3.0)Gleitkomma-Division durch 0Gleitkomma-UnterlaufGleitkomma-ÜberlaufUnerlaubte Gleitkomma- operation, z.B. sqrt(-1.0)Überlauf bei Wandlung Gleit- komma- in FestkommazahlFestkomma-ÜberlaufFestkomma-Division durch 0
00: Nächster Wert (standard)01: Abrunden (Richtung 0)10: Aufrunden (Richtung +∞)11: Abrunden (Richtung -∞)
nicht verwendet
Gleitkomma-Rundungsmodus
b) Geben Sie den MMIX-Code an, mit dem Sie den Gleitkomma-Rundungsmodus
auf ‘‘aufrunden’’ setzen.
c) Ändern Sie das Interrupt-Enable Bit ‘‘integer overflow’’ (0) 1, 1) 0) .
NO
GET $0,
RASET $1
, # FFFF
AND $0, $0 ,
$1 } Round Rl Crahan
SET $1,1SLU $1 , $1 , tf } Rr setter
OR $0 , $0.511PUT RA
, $0
GET $0,
RA
SET $1 , # 4000
for $0 , $0,81PUT RA
, $0
298 6 MMIX-Prozessor
Verzweigungsbefehle
Unbedingte Verzweigung
Befehl Operanden Name/Aktion Definition
JMP XYZ Jump @ u064( u(@) + 4 · s(XYZ) )
Bedingte Verzweigungen
Befehl Operanden Name/Aktion Definition
BZ $X,YZ Branch if zero s($X) = 0) @ u064( u(@) + 4 · s(YZ) )
PBZ $X,YZ Probable br. if zero s($X) = 0) @ u064( u(@) + 4 · s(YZ) )
BNZ $X,YZ Branch if nonzero s($X) 6= 0) @ u064( u(@) + 4 · s(YZ) )
PBNZ $X,YZ Prob. br. if nonzero s($X) 6= 0) @ u064( u(@) + 4 · s(YZ) )
BN $X,YZ Branch if negative s($X) < 0) @ u064( u(@) + 4 · s(YZ) )
PBN $X,YZ Prob. br. if negative s($X) < 0) @ u064( u(@) + 4 · s(YZ) )
BNN $X,YZ Branch if nonneg. s($X) � 0) @ u064( u(@) + 4 · s(YZ) )
PBNN $X,YZ Prob. br. if nonneg. s($X) � 0) @ u064( u(@) + 4 · s(YZ) )
BP $X,YZ Branch if positive s($X) > 0) @ u064( u(@) + 4 · s(YZ) )
PBP $X,YZ Prob. br. if positive s($X) > 0) @ u064( u(@) + 4 · s(YZ) )
BNP $X,YZ Branch if nonpositive s($X) 0) @ u064( u(@) + 4 · s(YZ) )
PBNP $X,YZ Prob. br. if nonpos. s($X) 0) @ u064( u(@) + 4 · s(YZ) )
BEV $X,YZ Branch if even s($X) %2 = 0) @ u064( u(@)+4·s(YZ) )
PBEV $X,YZ Prob. branch if even s($X) %2 = 0) @ u064( u(@)+4·s(YZ) )
BOD $X,YZ Branch if odd s($X) %2 = 1) @ u064( u(@)+4·s(YZ) )
PBOD $X,YZ Prob. branch if odd s($X) %2 = 1) @ u064( u(@)+4·s(YZ) )
SprungSpraywww.rsdreiuwchwahrscheiwcidr
while Caso ) do{ E
- - .
- ,
] I while Caso ) ;
6.5 MMIX Befehle 299
Betrachten Sie die folgenden Befehle:
LOC Data_SegmentGREG @
A OCTA 1000
a IS $1b IS $2
LOC #100Main LDB a,AStart SUB a,a,1
OR a,a,0BZ a,EndJMP Start
End TRAP 0,0,0
a) Bestimmen Sie das 32 Bit breite Befehlswort des Befehls ‘‘JMP Start’’.
b) Bestimmen Sie das 32 Bit breite Befehlswort des Befehls ‘‘BZ a,End’’.
+26% FOX
FFFFFD
OX F A FFFFFD
OX
42010002
300 6 MMIX-Prozessor
c) Benutzen Sie MMIX Verzweigungs-Befehle um folgenden C-Code zu implemen-
tieren:
C-Code: if(a == 0){
a = 1;}
MMIX-Code:
d) Benutzen Sie MMIX Verzweigungs-Befehle um folgenden C-Code zu implemen-
tieren:
C-code: int a;
...
if(a <= 0){
a = 1;}else{
a = 2;}
MMIX-Code:
(v
BNZ a,
Ende
SET a. A
Ende
,.
BP a,
Else
SET a , A
JMP EndElse SET a
. 2
End
6.5 MMIX Befehle 301
T e) Geben Sie den MMIX-Code an, der nachfolgenden C-Code implementiert:
C-Code: int a, b;
...
if(a > 0 && b < 0){
a = 1;}else if(a > 0 || b == 0){
a = 2;}else{
a = 3;}
MMIX-Code:
302 6 MMIX-Prozessor
Befehle für Funktionsaufrufe
Befehl Operanden Name/Aktion Definition
GO$X,$Y,$Z Go to location
$X u064( u(@) + 4) );
@ u064( u($Y)+u($Z) )
$X,$Y,Z Go to location immediate$X u0
64( u(@) + 4) );
@ u064( u($Y) + u(Z) )
T a) Was ist der Haupt-Unterschied zwischen dem JMP-Befehl und dem GO-Befehl?
T b) Wo speichern GO-Befehle die Rücksprungadresse ab?
T c) Was ist die ‘‘Rücksprungadresse’’?
T d) Wenn GO Absolute Adressierung verwendet: Wie wird die Abolute Adresse (64 Bit)
im 32 Bit breiten Befehlswort abgelegt?
e) Geben Sie den Befehl an, mit dem Sie die Funktion fkt aufrufen und die Rück-
sprungadresse in Register 0 ablegen.
BfmFEIarmy gaugesix
GO $0 , fat
6.5 MMIX Befehle 303
Namensräume - der PREFIX-Befehl
Der PREFIX-Befehl ist ein Assembler-Befehl. Er wird verwendet, um in einem Pro-
gramm vorkommenden Namen vom Assembler-Präprozessor durch Voranstellen einer
Zeichenkette automatisiert ändern zu lassen. Dazu wird der PREFIX-Befehl mit der
voranzustellenden Zeichenkette als Operand aufgerufen.
PREFIX Zeichenkette
Ab dieser Anweisung setzt der Assembler-Präprozessor vor jeden Namen die angege-
bene Zeichenkette. Hat beispielsweise die Zeichenkette den Wert ‘‘abc:’’, dann wird ein
Name ‘‘def’’ in ‘‘abc:def’’ geändert.
Fügt man vor jede Funktion einen PREFIX-Befehl mit dem Funktionsnamen als Zeichen-
kette ein, erzeugt man automatisch für jede Funktion einen eigenen Namensraum. Eine
Variable i in der Funktion fkt bekommt dann den (globalen) Namen fkti und eine Variable
i in der Funktion fkt2 den Namen fkt2i. Auf diese Weise kann der Assembler beide
Variable als unterschiedliche Variable erkennen und es kommt zu keinem Konflikt, wenn
der Assembler beispielsweise i sowohl durch $1 ersetzen soll (für die Funktion fkt1) als
auch durch $2 (für die Funktion fkt2).
Um den Funktionsnamen besser vom Variablennamen abgrenzen zu können, bietet es
sich an, an die Prefix-Zeichenkette noch ein markantes Zeichen anzuhängen, beispiels-
weise einen Bindestrich oder einen Doppelpunkt.
Um einen Namensraum zu beenden, d.h. um den Assembler-Präprozessor anzuweisen,
vorkommenden Namen die Zeichenkette nicht mehr voranzustellen, wird der PREFIX-
Befehl mit einem Doppelpunkt als Operand aufgerufen.
PREFIX :
Will man innerhalb eines Namensraums verhindern, dass der Assembler-Präprozessor
einen Namen ändert, schreibt man vor den betreffenden Namen einen Doppelpunkt,
z.B. ‘‘:def’’ statt ‘‘def’’. Auf diese Weise kann man auf globale Namen wie z.B. den
Stackpointer SP zugreifen.
a) Geben Sie die Anweisung an, mit denen Sie den Namensraum ‘‘Main:’’ eröffnen
und in diesem Namensraum die globale Marke ‘‘Main’’ definieren.
PREFIX chain :
304 6 MMIX-Prozessor
T b) Wie kann man einen Namensraum beenden, d.h. wie kann man den Assembler
anweisen, Marken/Namen nicht mehr umzuwandeln?
T c) Wie kann man – innerhalb eines Namensraums – verhindern, dass der Assembler
einer bestimmten Marke bzw. einem bestimmten Namen die im PREFIX-Befehlangegebene Zeichenkette voranstellt?
T d) Wozu dient der PREFIX-Befehl?
T e) Welche Auswirkung hat der Befehl PREFIX mein_prefix auf darauf folgendeMMIX-
Anweisungen?
PREFIX :
: var Uariableuuacnen se Gen
6.5 MMIX Befehle 305
T f) Geben Sie die Anweisungen an, mit denen Sie den Namensraum ‘‘Fkt:’’ eröffnen
und die globale Marke ‘‘Fkt’’ anlegen.
Funktionsaufrufe
Mit Funktionen werden logisch zusammengehörige Befehle zur Bereitstellung einer
Gesamt-Funktionalität zusammengefasst und durch Funktionsaufrufe von beliebigen
Stellen im Programm abrufbar. Durch diese Struktur gebende Maßnahme werden
Programme übersichtlicher und kürzer:
• Übersichtlicher, da der Programm-Code die Zerlegung eines großen Problems
in kleinere Probleme durch Funktionsaufrufe widerspiegelt, und
• kürzer, da eine Funktionalität (viele Befehle) nur einmal aus Befehlen zusam-
mengesetzt werden muss und durch Sprünge in die Funktion (wenige Befehle)
beliebig oft verwendet werden kann.
Beispiel: Email-Adresse von Personen aus einer csv-Datei (csv = comma separated
values =Werte durch Komma getrennt) extrahieren und jeder Person ein Email schreiben:
• Inhalt csv-Datei:
Anger,Andrea,03638491,andrea.anger@mytum.de\nBernegger,Bernhard,03785930,berni@mytum.de\nClausewitz,Carl,03758291,clausecarl@mytum.de\nDietrich,Daniel,03687204,dadi@mytum.de\nEichenholz,Emil,03890284,eichi@mytum.de\n
• Aufruf einer Funktion, welche den Namen der csv-Datei als Parameter überge-
ben bekommt und den Inhalt der Datei in den String s einliest.
s = file_read(“datei.csv”)
• Nach diesem Aufruf liegt der Dateiinhalt als zusammengehörige Zeichenkette s
im Speicher vor.
s = "Anger,Andrea,3638491,andrea.anger@mytum.de\nBernegger,Bernhard,03785930,berni@mytum.de\nClausewitz,Carl,03758291,clausecarl@mytum.de\nDietrich,Daniel,03687204,dadi@mytum.de\nEichenholz,Emil,890284,eichi@mytum.de\n\0"
PREFIX FAE :
: FEE
306 6 MMIX-Prozessor
• Aufruf einer Funktion, welche den String s sowie das Zeichen \n als Parameter
übergeben bekommt, den String an den Zeichen \n in Teil-Stings s1, s2, ...
auftrennt und als Ergebnis ein Array dieser Teil-Strings zurückliefert.
s = string_split(s, “\n”)
• Der String liegt jetzt im Speicher in Form eines Arrays vor.
a = ["Anger,Andrea,03638491,andrea.anger@mytum.de", "Bernegger,Bernhard,03785930,berni@mytum.de", "Clausewitz,Carl,03758291,clausecarl@mytum.de", "Dietrich,Daniel,03687204,dadi@mytum.de", "Eichenholz,Emil,03890284,eichi@mytum.de"]
s1 = a[0]
…s2 = a[1]
• Für jeden Teilstring si : Aufruf einer Funktion, welche den String si und das
Komma-Zeichen als Parameter übergeben bekommt, den String an den Kom-
mas in Teilstrings sij auftrennt und als Ergebnis ein Array von Zeigern auf die
Teil-Strings zurückliefert.
for(i = 0; i < size(a); i++)a[i] = string_split(a[i], ",")
• Variable a enthält nun ein Array aus Arrays, deren Komponenten die Teilstrings
sij sind.
a = [["Anger","Andrea","03638491","andrea.anger@mytum.de"],["Bernegger","Bernhard","03785930","berni@mytum.de"],["Clausewitz","Carl","03758291","clausecarl@mytum.de"],["Dietrich","Daniel","03687204","dadi@mytum.de"],["Eichenholz","Emil","03890284","eichi@mytum.de"]]
s11 = a[0][0] s12 = a[0][1] s13 = a[0][2]
s51 = a[4][0] s44 = a[3][3]
s14 = a[0][3]
• Für jede Email-Adresse: Aufruf einer Funktion, die als Parameter die Email-
Adresse und den Email-Text bekommt und den Email-Text an die angegebene
Email-Adresse verschickt.
for(i = 0; i < size(a); i++)email(a[i][3], text)
6.5 MMIX Befehle 307
Wert-Übergabe und Referenz-Übergabe
Es gibt viele Möglichkeiten, Funktionen Parameter zu übergeben. Prinzipiell unterschei-
det man zwischen der Übergabe von Werten und der Übergabe von Referenzen.
• Bei der Wert-Übergabe (engl. call by value) wird der Funktion direkt der zu
verarbeitende Wert übergeben, z.B. eine Festkommazahl.
• Bei der Referenz-Übergabe (engl. call by reference) wird der Funktion die
Adresse des zu verarbeitenden Werts übergeben, z.B. die Adresse, an der eine
Festkommazahl im Speicher steht.
In beiden Fällen wird bei der Parameterübergabe eine lokale Kopie erstellt.
• Bei der Wert-Übergabe wird eine Kopie des Werts erstellt. Ändert die Funktion
die ihr übergebene Variable, so hat das keinen Einfluss auf den Wert der
Original-Variable.
• Bei der Referenz-Übergabe wird eine Adresse übergeben und somit eine Kopie
der Adresse erstellt. Auch wenn es sich nur um eine Kopie der Adresse handelt –
die kopierte Adresse zeigt auf dieselbe Speicherstelle wie die originale Adresse.
Damit kann die Funktion Änderungen an den Werten durchführen, die an der
übergebenen Speicheradresse stehen – und der Funktionsaufrufer kann auf
diese Änderungen zugreifen.
Funktionsaufrufer:
Funktion:
Wert
Wert
Adresse
Adresse
wird
kop
iert
wird
kop
iert zeigt auf
zeigt auf
wird kopiert
wird kopiert
Diese Variable steht hier im Speicher
Wert-Übergabe Referenz-Übergabe
ruft
auf
Speicher
308 6 MMIX-Prozessor
Aufrufkonventionen
Eine Aufrufkonvention (engl. calling convention) legt fest, wie einer Funktion Parameter
übergeben werden und wie der Rückgabewert zurückgegeben wird. Damit spezifiziert
eine Aufrufkonvention u.a. Antworten auf Fragen wie:
• Werden alle Parameter auf dem Stack übergeben oder werden die ersten n
Parameter in Registern übergeben und die restlichen auf dem Stack?
• Welche Register werden zur Parameterübergabe verwendet?
• In welcher Reihenfolge werden die Parameter auf dem Stack bzw. in den
Registern abgelegt?
• Werden Gleitkommazahlen in anderen Registern übergeben als Festkomma-
zahlen? In welchen?
• Wer bereinigt den Stack: Der Funktionsaufrufer oder die Funktion?
• Wie wird der Rückgabewert zurückgegeben: Auf dem Stack oder in einem
Register? In welchem?
Da unterschiedliche Prozessorarchitekturen unterschiedliche Register haben (Anzahl,
Funktion, ...) und sich auch bezüglich der Verwendung des Stacks unterscheiden
können, sind Aufrufkonventionen architekturabhängig. Funktionen können auf einer Pro-
zessorarchitektur in vielfältiger Art und Weise aufgerufen werden. Somit gibt es für jede
Prozessorarchitektur in der Regel auch mehrere mögliche Aufrufkonventionen. Bei der
Programmierung in Hochsprache ist das Einhalten der gewünschten Aufrufkonvention
Aufgabe des Compilers.
Parameterübergabe auf dem Stack beim MMIX
Der Stack ist ein Bereich im Speicher des Prozessors, in dem Funktionsparameter,
Rücksprungadressen und lokale Variable nacheinander aufgerufender Funktionen auf-
einandergestapelt (engl. stack = Stapel) werden. Beim MMIX kann der Stack am Ende
des Datensegments aufgebaut werden, beginnend an Adresse 0x3FF...F8 in Richtung
niedrigerer Adressen wachsend. Der Stack wird immer über den sog. Stackpointer
angesprochen. Der Stackpointer wird realisiert durch ein Register, in dem die Adresse
der auf dem Stack ganz oben liegenden Daten abgelegt ist. Viele Prozessoren ver-
wenden ein spezielles Stackpointer-Register. Beim MMIX verwenden wir ein globales
Allzweckregister als Stackpointer.
6.5 MMIX Befehle 309
Beim MMIX kann die Verwendung eines Stacks wie folgt umgesetzt werden:
• Beim Start eines Programmes wird mit der Anweisung
SP GREG #4000000000000000
ein globales Register angelegt, mit 0x4000000000000000 initialisiert und über
die Marke SP ansprechbar gemacht. Über diese Marke wird der Stackpointer
dann zukünftig angesprochen.
0x40000000000000000x3FFFFFFFFFFFFFF8
SP
8 Byte
Der Stackpointer zeigt jetzt auf den Beginn des Pool-Segments.
• Beim Aufruf einer Funktion mit n Parametern wird vom aktuellen Wert des
Stackpointers n · 8 subtrahiert. Der Stackpointer zeigt dann auf eine niedrigere
Adresse, d.h. er wandert ‘‘nach oben’’. Im Falle n = 3 wird 3 · 8 subtrahiert.
SUB :SP,:SP,3*8
Der Stackpointer zeigt dann auf Adresse 0x3FFFFFFFFFFFFFE8.
0x40000000000000000x3FFFFFFFFFFFFFF8
SP0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
310 6 MMIX-Prozessor
• Anschließend werden die Parametermittels Stackpointer auf den Stack kopiert.
STO a,:SP,0STO b,:SP,1*8STO c,:SP,2*8
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8
SP
3. Parameter für Fkt2. Parameter für Fkt0x3FFFFFFFFFFFFFF0
0x3FFFFFFFFFFFFFE8
• Nachdem die Parameter auf den Stack kopiert sind, wird mit dem GO-Befehl
in die Funktion gesprungen. Dazu wird die Einsprungs-Marke der Funktion
angegeben, z.B. ‘‘Fkt’’. Als Register zur Speicherung der Rücksprungadresse
sollte ein Register angegeben werden, das keine Daten enthält, die noch
benötigt werden. Es bietet sich an, die Rücksprungadresse immer in demselben
Register abzulegen, beispielsweise in Register 0.
GO $0,:Fkt
6.5 MMIX Befehle 311
• Als Aufrufkonvention legen wir fest, dass die aufgerufene Funktion sicherstellen
muss, dass sie keine vom Funktionsaufrufer in Registern gespeicherten Daten
überschreibt. Da die Funktion die vom Funktionsaufrufer verwendeten Register
nicht zwingend kennt (z.B. Bibliotheksfunktion), sichert sie alle von ihr selbst
verwendeten Register auf den Stack. Die Funktion kann die Register dann
verwenden, muss aber unmittelbar vor dem Rücksprung zum Funktionsaufrufer
die alten Werte wieder vom Stack in die entsprechenden Register zurück
kopieren. Verwendet die Funktion beispielsweise die Register 1 und 2, so
sichert sie diese auf den Stack.
SUB :SP,:SP,2*8STO $1,:SP,0STO $2,:SP,1*8
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8
SP
3. Parameter für Fkt2. Parameter für Fkt0x3FFFFFFFFFFFFFF0
0x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
• Sind die Register auf den Stack gesichert, lädt die Funktion die für sie bestimm-
ten Parameter vom Stack und verarbeitet sie.
LDO $1,:SP,2*8 Parameter 1LDO $2,:SP,3*8 Parameter 2... ...LDO $2,:SP,4*8 Parameter 3... ...
312 6 MMIX-Prozessor
• Ruft die Funktion Fkt selbst eine andere Funktion Fkt2 auf, so sichert sie
zunächst die Rücksprungadresse auf den Stack, kopiert die der Funktion Fkt2zu übergebenden Parameter auf den Stack und ruft dann Funktion Fkt2 auf.
SUB :SP,:SP,2*8STO $0,:SP,1*8 RücksprungadresseSTO $1,:SP,0 Parameter für Fkt2GO $0,:Fkt2
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 3. Parameter für Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Parameter für Fkt2Sicherung $0 Fkt
SP0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
6.5 MMIX Befehle 313
• Die Funktion Fkt2 sichert nun ihrerseits die von ihr verwendeten Register auf
den Stack, lädt den ihr übergebenen Parameter vom Stack und führt damit
Berechnungen durch.
SUB :SP,:SP,2*8STO $1,:SP,0 Sicherung $1STO $2,:SP,1*8 Sicherung $2LDO $2,:SP,2*8 Parameter laden... ...
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 3. Parameter für Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Parameter für Fkt2Sicherung $0 Fkt
SP
0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8Fat 2
-FUE
314 6 MMIX-Prozessor
• Hat Fkt2 ihre Berechnungen abgeschlossen, legt Sie den Rückgabewert an
der Stelle auf dem Stack ab, an der ihr der Parameter übergeben wurde. Sind
mehrere Parameter übergeben worden, wird der Rückgabewert an die Stelle
desjenigen Parameters mit der höchsten Adresse geschrieben. Wurde kein
Parameter übergeben, so muss vor der Sicherung der Register auf dem Stack
Platz freigehalten werden.
STO $2,:SP,2*8 Rückgabewert
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 3. Parameter für Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Rückgabewert von Fkt2Sicherung $0 Fkt
SP
0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8
6.5 MMIX Befehle 315
• Nach dem Ablegen des Rückgabewerts auf dem Stack muss die Funktion Fkt2die auf den Stack gesicherten Register wieder herstellen. Anschließend muss
der Stackpointer so angepasst werden, dass er auf den Rückgabewert zeigt, so
dass er vom Funktionsaufrufer ausgelesen werden kann, ohne die Anzahl der
von Fkt2 auf den Stack gesicherten Register zu kennen. Anschließend springt
die Funktion Fkt2 zurück zum Funktionsaufrufer. Als Rücksprungadresse dient
Register 0 mit dem Offset 0. Für den GO-Befehl muss wieder ein Register
zur Speicherung der Rücksprungadresse angegeben werden, auch wenn nicht
an das Ende der Funktion Fkt2 zurückgesprungen wird. Da der in Register 0
enthaltene Wert nach dem Rücksprung nicht mehr benötigt wird, kann Register
0 auchwieder zur Abspeicherung dieser Rücksprungadresse verwendet werden
(1. Parameter des GO-Befehls).
LDO $1,:SP,0LDO $2,:SP,1*8ADD :SP,:SP,2*8GO $0,$0,0
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 3. Parameter für Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Rückgabewert von Fkt2Sicherung $0 Fkt
SP0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8
Auf die Werte oberhalb des Stackpointers wird nicht mehr zugegriffen. Sie
werden aber nicht explizit gelöscht/überschrieben.
316 6 MMIX-Prozessor
• Die Funktion Fkt kann nun das ihr von Fkt2 übergebene Ergebnis vom Stack
auslesen und mit ihren Berechnungen fortfahren. Nach dem Auslesen des
Rückgabewerts von Fkt2 addiert die Funktion Fkt noch den Wert 8 zum
Stackpointer. Damit zeigt der Stackpointer auf dieselbe Stelle wie vor dem
Aufruf von Fkt2. Der Aufruf von Fkt2 ist damit offiziell abgeschlossen.
LDO $1,:SP,0ADD :SP,:SP,8
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 3. Parameter für Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Rückgabewert von Fkt2Sicherung $0 FktSP 0x3FFFFFFFFFFFFFD0
0x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8
6.5 MMIX Befehle 317
• Die Funktion Fkt kann nun das Ergebnis von Fkt2 für ihre weiteren Berech-
nungen verwenden. Hat die Funktion Fkt ihre Berechnungen abgeschlossen,
kopiert sie ihren Rückgabewert auf den Stack, stellt die von ihr gesicherten Re-
gister wieder her, passt den Stackpointer so an, dass er auf den Rückgabewert
zeigt und kehrt schließlich zum Funktionsaufrufer zurück.
... ...STO $1,:SP,5*8LDO $0,:SP,0LDO $1,:SP,1*8LDO $2,:SP,2*8ADD :SP,:SP,5*8GO $0,$0,0
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 Rückgabewert von Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Rückgabewert von Fkt2Sicherung $0 Fkt
SP
0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8
318 6 MMIX-Prozessor
• Der Funktionsaufrufer kann nun das Ergebnis der Funktion Fkt über den
Stackpointer auslesen und danach den Stackpointer wieder anpassen, so dass
er auf die selbe Stelle zeigt wie vor dem Aufruf der Funktion Fkt.
LDO $1,:SP,0ADD :SP,:SP,8
1. Parameter für Fkt
0x40000000000000000x3FFFFFFFFFFFFFF8 Rückgabewert von Fkt
2. Parameter für Fkt0x3FFFFFFFFFFFFFF00x3FFFFFFFFFFFFFE8
Sicherung $1 FktSicherung $2 Fkt0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
Rückgabewert von Fkt2Sicherung $0 Fkt
SP
0x3FFFFFFFFFFFFFD00x3FFFFFFFFFFFFFC8
Sicherung $1 Fkt 2Sicherung $2 Fkt 20x3FFFFFFFFFFFFFC0
0x3FFFFFFFFFFFFFB8
6.5 MMIX Befehle 319
Aufgaben
a) Geben Sie den Befehl an, mit dem Sie den Stackpointer als globales Register an-
legen, mit 0x4000000000000000 initialisieren und über die Marke SP ansprechbar
machen.
b) Geben Sie die Befehle an, mit denen der Funktionsaufrufer aus dem Namensraum
Main: heraus Register 3 und 4 als Parameter auf dem Stack ablegt und danach
die global definierte Funktion Str aufruft. Die Rücksprungadresse soll in Register
0 abgelegt werden.
c) Geben Sie die Befehle an, mit denen Sie den Namensraum Str: anlegen, dann die
Funktion Str beginnen und die Register 0, 1 und 2 auf den Stack sichern.
SP GREG # 4000000000000000
SUB ISP,
:sP, 2*8
STO $3,
: SP, 0*8
STO $4.
'
. Smh # 8
Go $0 , :Str
PREFIX Str :
: Str SUB : SP,
:SD,
3*8
STO $0,
:SB0
STO $1 , :SRr*8STO $2
, :SR,
2*8
320 6 MMIX-Prozessor
d) Tragen Sie in nachfolgende Abbildung die auf dem Stack gespeicherten Werte ein
und geben Sie die Position des Stackpointers an.
0x4000000000000000
0x3FFFFFFFFFFFFFF8
0x3FFFFFFFFFFFFFF0
0x3FFFFFFFFFFFFFE8
0x3FFFFFFFFFFFFFE0
0x3FFFFFFFFFFFFFD8
0x3FFFFFFFFFFFFFD0
e) Geben Sie die Befehle an, mit denen Sie die übergebenen Parameter in die Register
1 und 2 einlesen.
f) Geben Sie die Befehle an, mit denen Sie den Wert aus Register 1 als Ergebnis
auf dem Stack ablegen, die auf den Stack gesicherten Register wieder herstel-
len, den Stackpointer anpassen und zurück zum Funktionsaufrufer springen. Die
Rücksprungadresse steht in Register 0 und soll auch wieder dort abgelegt werden.TYsicherungso
✓Sickening $1
Sickening $2→ parameter $3
##Parameters
Ergebuis $1
→ →
LDO $1 ,:SP
,3*8
LDO $2,
:S #4*8
STO $1 ,: SP
,4*8
LDO $0, : SP
,O
LDO $1.
: smh # 8LDO $2 ,
:sP,
2*8
ADD :,
:SP,
4*8
GO $0690
6.5 MMIX Befehle 321
g) Geben Sie die Befehle an, mit denen Sie den Namensraum Str: wieder beenden.
h) Geben Sie die Befehle an, mit denen der Funktionaufrufer das Ergebnis vom Stack
in das Register 1 einliest und den Stackpointer anpasst.
PREFIX :
LD O $1,
: SP,
0
ADD '
- Spc : SP, 8
322 6 MMIX-Prozessor
T i) Was ist der Stack?
T j) Wo beginnt der Stack und in welche Richtung wächst er?
T k) Was ist der Stack-Pointer?
T l) Wie werden Daten adressiert, die auf dem Stack liegen?
6.5 MMIX Befehle 323
T m) Welche Operationen muss man ausführen um die Werte zweier Register (acht Byte
breite Datenworte) auf dem Stack abzulegen?
T n) Wie wird der Stack bei Funktionsaufrufen verwendet?
324 6 MMIX-Prozessor
T o) Geben Sie den Befehl an mit dem Sie für den Stack-Pointer ein globales Register
reservieren und dieses mit 0x4000 00000000 0000 initialisieren.
T p) Warum initialisieren wir den Stack-Pointer mit 0x4000 00000000 0000, d.h. mit
dem Beginn des Poolsegments, und nicht mit dem Ende des Datensegments?
T q) Geben Sie die MMIX-Befehle an, mit denen Sie Register $1 und $2 auf den Stack
schreiben und dann die Funktion fkt aufrufen. Nehmen Sie an, dass Ihr Code im
Namensraum Main: steht und fkt im Namensraum Fkt: unter dem Namen :fktangelegt wurde. Sichern Sie die Rücksprungadresse in Register 0.
6.5 MMIX Befehle 325
Nehmen Sie an, dass Sie eine Funktion im Namensraum Fkt: implementieren.
T r) Geben Sie die MMIX-Befehle an, mit denen Sie die Register 0, 1, 2 und 3 auf den
Stack sichern und anschließend zwei acht Byte breite Parameter vom Stack in die
Register 1 und 2 einlesen.
T s) Zeichnen Sie, wie der Stack nach diesen Operationen aussieht.
326 6 MMIX-Prozessor
T t) Im Hauptprogramm wurden die Parameter in die Register 1 und 2 geschrieben.
Im Unterprogramm wurden Register 1 und 2 dann auf den Stack gesichert und
dann dieselben Werte wieder vom Stack in Register 1 und 2 geladen, obwohl
sich die Werte von Register 1 und 2 in der Zwischenzeit nicht geändert hatten.
Warum haben wir und diesen Schritt nicht gespart sondern dieselben Werte, die
in Registern 1 und 2 waren, nochmal reingeschrieben?
T u) Warum speichert man die Rücksprungadresse auf dem Stack?
T v) Was würde passieren, wenn der Stack so groß wird, dass er mit den Daten
zusammenstößt, die am Beginn des Datensegments liegen?
6.5 MMIX Befehle 327
T w) Geben Sie die MMIX-Befehle an, mit denen Sie den Inhalt von Register 3 als
Ergebnis auf dem Stack ablegen, dann die Register 0, 1, 2 und 3 wiederherstellen
und anschließend zurück zum Funktionsaufrufer springen.
T x) Nehmen Sie an, Sie sind wieder im Hauptprogramm. Geben Sie die Befehle an mit
denen Sie das Ergebnis der Funktion vom Stack in das Register 1 einlesen.
T y) Warum muss der Stack-Pointer angepasst werden nachdem das Ergebnis vom
Stack geladen wurde?
328 6 MMIX-Prozessor
Beispielprogramm: Quadratische Gleichung
In dieser Übung schreiben Sie ein MMIX Programm zur Lösung der Quadratischen
Gleichung a · x2 + b · x + c = 0 mit der Formel x1,2 = �b±p
b2�4·a·c2·a zu lösen. Die Variable
a, b und c sind als Festkommazahlen gegeben; das Ergebnis soll als Gleitkommazahl
angegeben werden.
a) Geben Sie den MMIX Befehl an, mit dem Sie den Stack-Pointer anlegen und über
die Marke SP ansprechbar machen.
Zunächst soll das Hauptprogramm implementiert werden.
b) Geben Sie den MMIX-Befehl an, mit dem Sie den Namensraum Main: eröffnen.
c) Reservieren Sie an Adresse 0x2000 0000 0000 0000 die 64 Bit breiten SpeicherworteA, B, C, X1 und X2 und initialisieren Sie A mit 2, B mit 4 und C mit 8.
d) Geben Sie den Befehl an, mit dem Sie Register 1 durch buf ansprechbar machen.
SP GREG # 4000000000000000
PREFIX Main :
LOC # 2000000000000000
GREG @
A OCHA 2
B OCTA 4
C OCTA 8LDO $413
xn octa d+2 OCTA $253 -18
buf IS $1
6.5 MMIX Befehle 329
e) Beginnen Sie das Hauptprogramm, legen Sie A, B und C auf dem Stack ab und
rufen Sie dann die global definierte Funktion QuadGleich auf. Speichern Sie dabei
die Rücksprungadresse in Register $0.
f) Geben Sie den MMIX Code an, mit dem Sie die Ergebnisse x1 und x2 der Funktion
vom Stack auslesen und im Arbeitsspeicher an den Marken X1 bzw. X2 ablegen.
g) Geben Sie die Anweisungen an, mit denen Sie das Programm und den Namens-
raum Main: beenden.
icllaiu SUB ish, :Sp
,3*8
LDO but ,A
STO barf ,:SP,0
LDO but ,B
STO buf , :SB8CDO but , C
STO but ,:SRl6
GO $0,
: Quad Gleich
LDO but , ISROSTO buffsLDO buf ,
is, 8
STO but ,XZ
TRAP O,
: Halt ,0
PREFIX :
330 6 MMIX-Prozessor
Im Folgenden soll die Funktion QuadGleich implementiert werden, von der folgender
Programm-Code bereits gegeben ist:
PREFIX QuadGleich:
a IS $1b IS $2c IS $3x1 IS $4x2 IS $5disk IS $6buf1 IS $7buf2 IS $8
Der Funktion QuadGleich werden die Parameter a, b und c wie folgt auf dem Stack
übergeben:SP! a
b
c
h) Geben Sie an der Marke :QuadGleich die Befehle an, mit denen Sie die verwende-
ten Register auf den Stack sichern und die Parameter a, b und c dann vom Stack
in die Register a, b und c einlesen.
:QuadGleich
SUB ISP,
'
- SP, 8*8
STO a , :Sp , O
STO b, :SPie#8
STO c, :SP
, 2*8
STO M, :SP , 3*8
STO X2i.SK 4*8
STO disk,
:SP, 5*8
STO buff: SR 6*8
STO buf2 ,:sPc7H8
LDO a,
:SP,
8*8LDO bi : SP
, 9*8LDO c , :sp ,
10*8
6.5 MMIX Befehle 331
i) Geben Sie den MMIX-Befehlscode an, der
• im Fall a = 0 das Ergebnis x = �c/b berechnet, dieses dann sowohl in
x1 und x2 speichert und dann an die Marke Speichern springt, und
• im Fall a 6= 0 an die Marke Anicht0 springt.
j) Geben Sie an Marke Anicht0 den MMIX Code an, mit dem Sie die Diskriminante
b2� 4 · a · c mittels Festkomma-Arithmetik berechnen und das Ergebnis in Register
disk ablegen.
Anicht0
BNZ a,
Aniceto
NEG C, O
, C
F LOT C, c
FLOT bib
FD IV Xl,C
,b
SET x2 ,xd
JMP Speicher