6.5 MMIX Befehle 265 T a) Welche Wortgrößen kann der MMIX vom

6.5 MMIX Befehle
T
a)
265
Welche Wortgrößen kann der MMIX vom Speicher in Register laden?
Die MMIX-Ladebefehle unterstützen Wortbreiten von 8, 16, 32 und 64 Bit.
T
b) Was ist der Unterschied zwischen vorzeichenbehaftetem (signed) und vorzeichenlosen (unsigned) Laden?
• Vorzeichenbehaftet: Wenn die Breite des zu ladenden Datenwort kleiner
ist als die Registerwortbreite (d.h. 8, 16 oder 32 Bit breites Datenwort in
64 Bit breites Register laden), werden die oberen Bits des Registers mit
dem MSB (Most Significant Bit) des zu ladenden Wortes aufgefüllt.
• Vorzeichenlos: Wenn die Breite des zu ladenden Datenworts kleiner ist
als die Registerwortbreite, werden die oberen Bits des Registers mit 0
aufgefüllt.
T
c)
Warum muss man zwischen vorzeichenlosem und vorzeichenbehaftetem Laden
unterscheiden?
Vor vorzeichenlosen Zahlen hat man implizit unendlich viele 0-er stehen, vor
vorzeichenbehafteten Zahlen entweder unendlich viele 0-er (positive Zahl) oder
unendlich viele 1-er (negative Zahl). Wenn man vor eine vorzeichenbehaftete,
negative Zahl 0-er schreibt (was bei den vorzeichenlosen Ladebefehlen der Fall
wäre) würde aus der negativen Zahl plötzlich eine andere (falsche) positive Zahl
werden (! Fehler).
T
d) Wie unterscheiden sich die Namen der vorzeichenlosen und vorzeichenbehafteten
Ladebefehle?
Bei vorzeichenlosen Ladebefehlen wird ein zusätzliches U an den Namen angefügt.
266
T
e)
6 MMIX-Prozessor
Wie unterscheiden sich die Opcodes von vorzeichenlosen und vorzeichenbehafteten Ladebefehlen?
Opcode vorzeichenlos = Opcode vorzeichenbehaftet + 2
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.
64 als positive Festkommazahl: 0100 0000
1er-Komplement: 1011 1111
2er-Komplement: 1100 0000
Hexadezimal: 0xC0
Auf 64 Bit aufgefüllt: 0xFFFFFFFFFFFFFFC0
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.
0xC0 = 128 + 64 = 192
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?
Von den 16 Bit (Y und Z) werden 8 Bit (Y) verwendet um ein Allzweckregister zu
adressieren, das eine 64 Bit breite Basisadresse enthält. Mit den anderen 8 Bit (Z)
wird der Offset bestimmt, der zur Basisadresse hinzuaddiert wird. Abhängig vom
Opcode des Ladebefehls ist dieser Offset entweder
• der Wert eines Allzweckregisters, das mit Z adressiert wird, oder
• der Direktoperand u(Z).
6.5 MMIX Befehle
i)
267
Vervollständigen Sie den nachfolgenden MMIX-Code um die Bereitstellung und
Initialisierung eines Basisregisters zur Adressierung von A, B und C.
A
B
C
Main
LOC
#2000000000000000
GREG
@
BYTE
OCTA
OCTA
0
#FFFF
LOC
#100
LDO
$0,B
!"#"$% &'()*+,-.%(*/%012'(*/%
...
!
&'(!)*+*,-(#.*-/!01234/*5!67*8434/*9!:;</!=*8>((!7'3,+4-=*7/*<!?'@*--*!A@*<(*BCBD!
!
0x..0
0x0..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x8..
0x9..
0xA..
0xB..
0xC..
0xD..
0xE..
0xF..
0x..1
TRAP 5ν
FCMP ν
FLOT[I] 4ν
FMUL 4ν
FCMPE 4ν
MUL[I] 10ν
ADD[I] ν
2ADDU[I] ν
CMP[I] ν
SL[I] ν
BN[B] ν+π
BNN[B] ν+π
PBN[B] 3ν-π
PBNN[B] 3ν-π
CSN[I] ν
CSNN[I] ν
ZSN[I] ν
ZSNN[I] ν
LDB[I] µ+ν
LDT[I] µ+ν
LDSF[I] µ+ν
LDVTS[I] ν
STB[I] µ+ν
STT[I] µ+ν
STSF[I] µ+ν
SYNCD[I] ν
OR[I] ν
AND[I] ν
BDIF[I] ν
MUX[I] ν
SETH ν
SETMH ν
ORH ν
ORMH ν
JMP[B] ν
POP 3ν
RESUME 5ν
0x..8
0x..9
0x..2
0x..3
FUN ν
FEQL ν
FLOTU[I] 4ν
FUNE ν
FEQLE 4ν
MULU[I] 10ν
ADDU[I] ν
4ADDU[I] ν
CMPU[I] ν
SLU[I] ν
BZ[B] ν+π
BNZ[B] ν+π
PBZ[B] 3ν-π
PBNZ[B] 3ν-π
CSZ[I] ν
CSNZ[I] ν
ZSZ[I] ν
ZSNZ[I] ν
LDBU[I] µ+ν
LDTU[I] µ+ν
LDHT[I] µ+ν
PRELD[I] ν
STBU[I] µ+ν
STTU[I] µ+ν
STHT[I] µ+ν
PREST[I] ν
ORN[I] ν
ANDN[I] ν
WDIF[I] ν
SADD[I] ν
SETML ν
SETL ν
ORML ν
ORL ν
PUSHJ[B] ν
[UN]SAVE 20µ+ν
0x..A
0x..B
0x..4
0x..5
0x..6
0x..7
FADD 4ν
FIX 4ν
FSUB 4ν
FIXU 4ν
SFLOT[I] 4ν
SFLOTU[I] 4ν
FDIV 40ν FSQRT 40ν FREM 4ν
FINT 4ν
DIV[I] 60ν
DIVU[I] 60ν
SUBU[I] ν
SUB[I] ν
8ADDU[I] ν
16ADDU[I] ν
NEG[I] ν
NEGU[I] ν
SR[I] ν
SRU[I]ν
BP[B] ν+π
BOD[B] ν+π
BNP[B] ν+π
BEV[B] ν+π
PBP[B] 3ν-π
PBOD[B] 3ν-π
PBNP[B] 3ν-π
PBEV[B] 3ν-π
CSP[I] ν
CSOD[I] ν
CSNP[I] ν
CSEV[I] ν
ZSP[I] ν
ZSOD[I] ν
ZSNP[I] ν
ZSEV[I] ν
LDW[I] µ+ν
LDWU[I] µ+ν
LDO[I] µ+ν
LDOU[I] µ+ν
CSWAP[I] 2µ+2ν
LDUNC[I] µ+ν
PREGO[I] ν
GO[I] 3ν
STW[I] µ+ν
STWU[I] µ+ν
STO[I] µ+ν
STOU[I] µ+ν
STCO[I] µ+ν
STUNC[I] µ+ν
SYNCID[I] ν
PUSHGO[I] 3ν
NOR[I] ν
XOR[I] ν
NAND[I] ν
NXOR[I] ν
TDIF[I] ν
ODIF[I] ν
MOR[I] ν
MXOR[I] ν
INCH ν
INCHM ν
INCML ν
INCL ν
ANDNH ν
ANDNMH ν ANDNML ν
ANDNL ν
GETA[B] ν
PUT[I] ν
SYNC ν
SWYM ν
GET ν
TRIP 5ν
0x..C
0x..D
0x..E
0x..F
0x0..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x8..
0x9..
0xA..
0xB..
0xC..
0xD..
0xE..
0xF..
!
!
!
&'(!*<(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!!
268
6 MMIX-Prozessor
Gegeben ist der nachfolgende MMIX-Programmcode:
LOC
GREG
#2000000000000000
@
a
IS
$1
X
Y
Z
BYTE
TETRA
OCTA
0
#FFFF
LOC
#100
...
...
...
...
Main
j)
@
$254
In welches Befehlswort würde der MMIX-Assembler LDB a,X übersetzen?
0x8101FE00.
k)
In welches Befehlswort würde der MMIX-Assembler LDT a,Y übersetzen?
0x8901FE04.
l)
In welches Befehlswort würde der MMIX-Assembler LDO a,Z übersetzen?
0x8D01FE08.
T
m) Geben Sie alle 64 Bit des Registers $1 nach Ausführung des Befehls LDBU a,Y an.
0x00000000000000FF
T
n)
Geben Sie alle 64 Bit des Registers $1 nach Ausführung des Befehls LDB a,Y an.
0xFFFFFFFFFFFFFFFF
6.5 MMIX Befehle
269
o) Tragen Sie in nachfolgende Tabelle den Speicherinhalt ein, der sich nach Ausführung der angegebenen MMIX-Befehle im Falle von Big- und Little-EndianAdressierung ergeben würde.
LOC
GREG
BYTE
TETRA
TETRA
BYTE
WYDE
Adresse
Data_Segment
@
1
#23456789
#ABCDEF01
#77
#0123
Niederwert. vier Adress-Bits
Big Endian
Little Endian
0x2000000000000000
0000
0x01
0x01
0x2000000000000001
0001
?
?
0x2000000000000002
0010
?
?
0x2000000000000003
0011
?
?
0x2000000000000004
0100
0x23
0x89
0x2000000000000005
0101
0x45
0x67
0x2000000000000006
0110
0x67
0x45
0x2000000000000007
0111
0x89
0x23
0x2000000000000008
1000
0xAB
0x01
0x2000000000000009
1001
0xCD
0xEF
0x200000000000000A
1010
0xEF
0xCD
0x200000000000000B
1011
0x01
0xAB
0x200000000000000C
1100
0x77
0x77
0x200000000000000D
1101
?
?
0x200000000000000E
1110
0x01
0x23
0x200000000000000F
1111
0x23
0x01
270
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:
0x0000 0000 0000 0001
LDB $0,$254,4:
0x0000 0000 0000 0023
LDB $0,$254,9:
0xFFFF FFFF FFFF FFCD
LDBU $0,$254,9:
0x0000 0000 0000 00CD
LDT $0,$254,4:
0x0000 0000 2345 6789
LDT $0,$254,5:
0x0000 0000 2345 6789
LDT $0,$254,9:
0xFFFF FFFF ABCD EF01
LDTU $0,$254,9:
0x0000 0000 ABCD EF01
LDO $0,$254,0:
0x???? ???? 2345 6789
LDO $0,$254,1:
0x???? ???? 2345 6789
LDO $0,$254,12:
0xABCD EF01 77?? 0123
6.5 MMIX Befehle
T
271
q) Tragen Sie in nachfolgende Tabelle den Speicherinhalt ein, der sich nach Ausführung der angegebenen MMIX-Befehle im Falle von Big- und Little-EndianAdressierung ergeben würde.
LOC
GREG
BYTE
WYDE
OCTA
Adresse
Data_Segment
@
1
#1234
#56789ABC
Niederwert. vier Adress-Bits
@
Big Endian
$254
Little Endian
0x2000000000000000
0000
0x01
0x01
0x2000000000000001
0001
?
?
0x2000000000000002
0010
0x12
0x34
0x2000000000000003
0011
0x34
0x12
0x2000000000000004
0100
?
?
0x2000000000000005
0101
?
?
0x2000000000000006
0110
?
?
0x2000000000000007
0111
?
?
0x2000000000000008
1000
0x00
0xBC
0x2000000000000009
1001
0x00
0x9A
0x200000000000000A
1010
0x00
0x78
0x200000000000000B
1011
0x00
0x56
0x200000000000000C
1100
0x56
0x00
0x200000000000000D
1101
0x78
0x00
0x200000000000000E
1110
0x9A
0x00
0x200000000000000F
1111
0xBC
0x00
272
T
r)
6 MMIX-Prozessor
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:
0x0000 0000 0000 0034
LDB $0,$254,14:
0xFFFF FFFF FFFF FF9A
LDBU $0,$254,15:
0x0x0000 0000 0000 00BC
LDT $0,$254,14:
0x0000 0000 5678 9ABC
LDTU $0,$254,15:
0x0000 0000 567 9ABC
6.5 MMIX Befehle
273
Daten vom Register in den Speicher schreiben (speichern)
Befehl Operanden Name/Aktion
$X,$Y,$Z
Store byte; with overflow
$X,$Y,Z
Store byte immed.; ovf.
$X,$Y,$Z
$X,$Y,Z
Store byte unsigned
Store byte uns. imm.
STB
STBU
$X,$Y,$Z
Store wyde; with overflow
$X,$Y,Z
Store wyde immed.; ovf.
$X,$Y,$Z
$X,$Y,Z
Store wyde unsigned
Store wyde uns. imm.
STW
STWU
Definition
M1 [u($Y) + u($Z)]
($X)7...0
7
0 (26 )
s($X) 2 ) rA
rA | u64
0 (26 )
s($X) < 27 ) rA
rA | u64
M1 [u($Y) + u(Z)]
($X)7...0
7
0 (26 )
s($X) 2 ) rA
rA | u64
0 (26 )
s($X) < 27 ) rA
rA | u64
M1 [u($Y) + u($Z)]
M1 [u($Y) + u(Z)]
($X)7...0
($X)7...0
M2 [u($Y) + u($Z)]
s($X) 215 ) rA
s($X) < 215 ) rA
M2 [u($Y) + u(Z)]
s($X) 215 ) rA
s($X) < 215 ) rA
($X)15...0
0 (26 )
rA | u64
0 (26 )
rA | u64
($X)15...0
0 (26 )
rA | u64
0 (26 )
rA | u64
M2 [u($Y) + u($Z)]
M2 [u($Y) + u(Z)]
($X)15...0
($X)15...0
M4 [u($Y) + u($Z)]
s($X) 231 ) rA
s($X) < 231 ) rA
M4 [u($Y) + u(Z)]
s($X) 231 ) rA
s($X) < 231 ) rA
($X)31...0
0 (26 )
rA | u64
0 (26 )
rA | u64
($X)31...0
0 (26 )
rA | u64
0 (26 )
rA | u64
M4 [u($Y) + u($Z)]
M4 [u($Y) + u(Z)]
($X)31...0
($X)31...0
$X,$Y,$Z
Store tetra; with overflow
$X,$Y,Z
Store tetra immed.; ovf.
STTU
$X,$Y,$Z
$X,$Y,Z
Store byte unsigned
Store byte uns. imm.
STO
$X,$Y,$Z
$X,$Y,Z
Store octa
Store octa immediate
M8 [u($Y) + u($Z)]
M8 [u($Y) + u(Z)]
$X
$X
STOU
$X,$Y,$Z
$X,$Y,Z
Store octa unsigned
Store octa uns. imm.
M8 [u($Y) + u($Z)]
M8 [u($Y) + u(Z)]
$X
$X
STCO
X,$Y,$Z
X,$Y,Z
Store constant octabyte
Store const. octa imm.
STHT
$X,$Y,$Z
$X,$Y,Z
Store high tetra
Store high tetra imm.
STT
M8 [u($Y) + u($Z)]
M8 [u($Y) + u(Z)]
M4 [u($Y) + u($Z)]
M4 [u($Y) + u(Z)]
0 ( u(X) )
u64
0 ( u(X) )
u64
($X
($X
u
u
32)
32)
274
6 MMIX-Prozessor
Befehl Operanden Name/Aktion
T
STSF
$X,$Y,$Z
$X,$Y,Z
Store short float
Store short float imm.
STUNC
$X,$Y,$Z
$X,$Y,Z
Store uncached
Store uncached imm.
a)
Definition
M4 [u($Y) + u($Z)]
M4 [u($Y) + u(Z)]
f32 1 (f64 ($X))
f32 1 (f64 ($X))
M8 [u($Y) + u($Z)]
M8 [u($Y) + u(Z)]
$X
$X
Wie unterscheidet sich die Verwendung von X, Y und Z bei Speicher-Befehle von
derjenigen aller anderen MMIX-Befehle?
Die Speicher-Befehle des MMIX verwenden Y und Z als Ziel und X als Quelle. Alle
anderen MMIX-Befehle verwenden Y und Z als Quelle und X als Ziel.
T
b) Was ist beim MMIX der Unterschied zwischen vorzeichenbehaftetem und vorzeichenlosem Speichern?
• Die vorzeichenbehafteten Speicherbefehle zeigen einen FestkommaÜberlauf an, wenn die abgespeicherten Werte
• bei STB kleiner als -128 oder größer als 127,
• bei STW kleiner als -32.768 oder größer als 32.767,
• bei STT kleiner als 2,147,483,648 oder größer als 2,147,483,647
sind.
• Die vorzeichenlosen Speicherbefehle erzeugen keinen Überlauf.
• STO und STOU sind äquivalent.
6.5 MMIX Befehle
275
In folgendem Programmcode wird XXX XXXXXXXX als Platzhalter für einen einzelnen
Befehl verwendet:
A
B
Main
c)
T
LOC
GREG
OCTA
TETRA
Data_Segment
@
#FFFF FFFF FFFF FFFF
#8765 4321
LOC
LDTU
XXX
TRAP
#100
$0,B
XXXXXXXX
0,Halt,0
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:
0x21FF FFFF FFFF FFFF
STTU $0,A:
0x8765 4321 FFFF FFFF
STT $0,$254,6:
0xFFFF FFFF 8765 4321
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:
0x4321 FFFF FFFF FFFF
STWU $0,A:
0x4321 FFFF FFFF FFFF
STT $0,A:
0x8765 4321 FFFF FFFF
STO $0,A:
0x0000 0000 8765 4321
STB $0,$254,5:
0xFFFF FFFF FF21 FFFF
STW $0,$254,1:
0x4321 FFFF FFFF FFFF
ST0 $0,$254,5:
0x0000 0000 8765 4321
276
e)
6 MMIX-Prozessor
Geben Sie hexadezimal das 32 Bit breite Befehlswort des Befehls STBU $0,A an,
wenn dieser in obigem Programmcode den Platzhalter XXX XXXXXXXX ersetzt.
0xA300FE00.
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.
Data
Main
LOC
GREG
OCTA
Data_Segement
@
#1234 5678
LOC
LDO
STB
LDA
STB
STT
#100
$1,Data
$1,Data
$2,Data
$1,$2,2
$1,$2,#A
6.5 MMIX Befehle
277
Gegeben ist der folgende Programmcode:
Label
Main
T
LOC
GREG
OCTA
Data_Segement
@
#1234 5678
LOC
LDO
STB
LDA
STB
STT
#100
$0,Label
$0,Label
$2,Label
$0,$2,2
$0,$2,10
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.
0x2000 0000 0000 0000
0x2000 0000 0000 0001
0x2000 0000 0000 0002
0x2000 0000 0000 0003
0x2000 0000 0000 0004
0x2000 0000 0000 0005
0x2000 0000 0000 0006
0x2000 0000 0000 0007
0x2000 0000 0000 0008
0x2000 0000 0000 0009
0x2000 0000 0000 000A
0x2000 0000 0000 000B
0x2000 0000 0000 000C
0x2000 0000 0000 000D
0x2000 0000 0000 000E
0x2000 0000 0000 000F
$0:
0000 0000 1234 5678
$2:
2000 0000 0000 0000
0x78
0x00
0x78
0x00
0x12
0x34
0x56
0x78
0x12
0x34
0x56
0x78
?
?
?
?
278
6 MMIX-Prozessor
Adressen in ein Register laden
Befehl Operanden Name/Aktion
Definition
LDA
$X,$Y,$Z
$X,$Y,Z
Get address (absolute)
Get address immed. (absolute)
GETA
$X,YZ
Get address (relativ)
$X
$X
$X
0 (u($Y) + u($Z))
u64
0 (u($Y) + u(Z))
u64
0 (u(@) + 4 · s(YZ))
u64
!"#"$% &'()*+,-.%(*/%012'(*/%
!
&'(!)*+*,-(#.*-/!01234/*5!67*8434/*9!:;</!=*8>((!7'3,+4-=*7/*<!?'@*--*!A@*<(*BCBD!
!
0x..0
0x0..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x8..
0x9..
0xA..
0xB..
0xC..
0xD..
0xE..
0xF..
0x..1
TRAP 5ν
FCMP ν
FLOT[I] 4ν
FMUL 4ν
FCMPE 4ν
MUL[I] 10ν
ADD[I] ν
2ADDU[I] ν
CMP[I] ν
SL[I] ν
BN[B] ν+π
BNN[B] ν+π
PBN[B] 3ν-π
PBNN[B] 3ν-π
CSN[I] ν
CSNN[I] ν
ZSN[I] ν
ZSNN[I] ν
LDB[I] µ+ν
LDT[I] µ+ν
LDSF[I] µ+ν
LDVTS[I] ν
STB[I] µ+ν
STT[I] µ+ν
STSF[I] µ+ν
SYNCD[I] ν
OR[I] ν
AND[I] ν
BDIF[I] ν
MUX[I] ν
SETH ν
SETMH ν
ORH ν
ORMH ν
JMP[B] ν
POP 3ν
RESUME 5ν
0x..8
0x..9
0x..2
0x..3
FUN ν
FEQL ν
FLOTU[I] 4ν
FUNE ν
FEQLE 4ν
MULU[I] 10ν
ADDU[I] ν
4ADDU[I] ν
CMPU[I] ν
SLU[I] ν
BZ[B] ν+π
BNZ[B] ν+π
PBZ[B] 3ν-π
PBNZ[B] 3ν-π
CSZ[I] ν
CSNZ[I] ν
ZSZ[I] ν
ZSNZ[I] ν
LDBU[I] µ+ν
LDTU[I] µ+ν
LDHT[I] µ+ν
PRELD[I] ν
STBU[I] µ+ν
STTU[I] µ+ν
STHT[I] µ+ν
PREST[I] ν
ORN[I] ν
ANDN[I] ν
WDIF[I] ν
SADD[I] ν
SETML ν
SETL ν
ORML ν
ORL ν
PUSHJ[B] ν
[UN]SAVE 20µ+ν
0x..A
0x..B
0x..4
0x..5
0x..6
0x..7
FADD 4ν
FIX 4ν
FSUB 4ν
FIXU 4ν
SFLOT[I] 4ν
SFLOTU[I] 4ν
FDIV 40ν FSQRT 40ν FREM 4ν
FINT 4ν
DIV[I] 60ν
DIVU[I] 60ν
SUBU[I] ν
SUB[I] ν
8ADDU[I] ν
16ADDU[I] ν
NEG[I] ν
NEGU[I] ν
SR[I] ν
SRU[I]ν
BP[B] ν+π
BOD[B] ν+π
BNP[B] ν+π
BEV[B] ν+π
PBP[B] 3ν-π
PBOD[B] 3ν-π
PBNP[B] 3ν-π
PBEV[B] 3ν-π
CSP[I] ν
CSOD[I] ν
CSNP[I] ν
CSEV[I] ν
ZSP[I] ν
ZSOD[I] ν
ZSNP[I] ν
ZSEV[I] ν
LDW[I] µ+ν
LDWU[I] µ+ν
LDO[I] µ+ν
LDOU[I] µ+ν
CSWAP[I] 2µ+2ν
LDUNC[I] µ+ν
PREGO[I] ν
GO[I] 3ν
STW[I] µ+ν
STWU[I] µ+ν
STO[I] µ+ν
STOU[I] µ+ν
STCO[I] µ+ν
STUNC[I] µ+ν
SYNCID[I] ν
PUSHGO[I] 3ν
NOR[I] ν
XOR[I] ν
NAND[I] ν
NXOR[I] ν
TDIF[I] ν
ODIF[I] ν
MOR[I] ν
MXOR[I] ν
INCH ν
INCHM ν
INCML ν
INCL ν
ANDNH ν
ANDNMH ν ANDNML ν
ANDNL ν
GETA[B] ν
PUT[I] ν
SYNC ν
SWYM ν
GET ν
TRIP 5ν
0x..C
0x..D
0x..E
0x..F
0x0..
0x1..
0x2..
0x3..
0x4..
0x5..
0x6..
0x7..
0x8..
0x9..
0xA..
0xB..
0xC..
0xD..
0xE..
0xF..
!
!
!
&'(!*<(B*!E;@@-*!0F!);B#G*<B9!/*(!1234/*(!*7B(2<;3,B!/*<!&422*-C*;-*!0H!@;(!IJ95!;7!/*<!(;3,!/*<!)*#
+*,-(34/*!@*+;7/*BD!
!
a)! Was ist der Unterschied zwischen dem Befehl LDA und den Ladebefehlen LDB, ... ?
&'(!C:*;B*!E;@@-*!/*(!1234/*(!*<=;@B!(;3,!:;*!+4-=BK!
!
Die Ladebefehle LDB, ... laden Datenworte vom Speicher in ein Register. Der Befehl
−! 6L)!0);B!E<D!"9!/*(!C:*;B*7!E;@@-*(!
LDA+!lädt
eine Adresse in ein Register.
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/!
6.5 MMIX Befehle
279
Nehmen Sie die folgenden Befehle an:
A
Main
LOC
GREG
BYTE
Data_Segment
@
#12
LOC
LDA
TRAP
#100
$0,A
0,Halt,0
$254
@
b) In welches hexadezimale Befehlswort wird der Befehl LDA $0,A übersetzt? Warum?
0x2300FE00. Der Assembler löst die Marke A in $254 + 0 auf und ersetzt den
Befehl LDA $0,A durch ADDUI $0,$254,0. Der Befehl ADDUI addiert den Wert im
Basisregister 254 und den Offset 0 und speichert das Ergebnis in Register 0. Damit
enthält Register 0 dann die Adresse der Marke A.
Gegeben sind die folgenden Befehle:
A
Main
c)
LOC
GREG
BYTE
Data_Segment
@
#12
LOC
LDA
GETA
TRAP
#100
$0,A
$0,Main
0,Halt,0
In welches 32 Bit breite Befehlswort wird der Befehl GETA $0,Main übersetzt?
0xF500FFFF
280
6 MMIX-Prozessor
Zugriff auf Spezialregister
Befehl Operanden Name/Aktion
T
Definition
GET
$X,Z
Get value of special purpose register
$X
PUT
X,$Z
X,Z
Put value to special purpose register
Put immed. value to spec. purp. reg.
S(X)
$Z
0
S(X)
u64 (u(Z))
a)
S(Z)
Tragen Sie in nachfolgender Befehlssequenz Befehle zur Berechnung der Festkommadivisioni dividend/divisor ein und speichern Sie das Ergebnis an der
Marke Quotient und den Divisionsrest an der Marke Remainder ab.
Dividend
Divisor
Quotient
Remainder
LOC
GREG
OCTA
OCTA
OCTA
OCTA
Data_Segment
@
7
3
dividend
divisor
quotient
remainder
IS
IS
IS
IS
$0
$1
$2
$3
Main
LOC
LDO
LDO
#100
dividend,Dividend
divisor,Divisor
DIV
GET
STO
STO
quotient,dividend,divisor
remainder,rR
quotient,Quotient
remainder,Remainder
TRAP
0,Halt,0
6.5 MMIX Befehle
281
Gegeben ist das Format des Spezialregisters rA.
Interrupt Enable (Freischalten)
0
0 R1 R0 D
V W
I
O U
Z
X
Interrupt Event (Auftreten)
D
V W
I
O U
Z
X
Gleitkommazahl ungenau
(z.B. 1.0 / 3.0)
Gleitkomma-Division durch 0
Gleitkomma-Unterlauf
Gleitkomma-Überlauf
Unerlaubte Gleitkommaoperation, z.B. sqrt(-1.0)
Überlauf bei Wandlung Gleitkomma- in Festkommazahl
Festkomma-Überlauf
Festkomma-Division durch 0
nicht verwendet
Gleitkomma-Rundungsmodus
00: Nächster Wert (standard)
01: Abrunden (Richtung 0)
10: Aufrunden (Richtung +∞)
11: Abrunden (Richtung -∞)
b) Geben Sie den MMIX-Code an, mit dem Sie den Gleitkomma-Rundungsmodus
auf ‘‘aufrunden’’ setzen.
Bits die geändert werden müssen: 17, 16
GET
ANDNML
ORML
PUT
c)
$0,rA
$0,3
$0,2
rA,$0
Ändern Sie das Interrupt-Enable Bit ‘‘integer overflow’’ (0 ) 1, 1 ) 0) .
GET
SET
XOR
PUT
$0,rA
$1,#4000
$0,$0,$1
rA,$0
282
6 MMIX-Prozessor
Verzweigungsbefehle
Unbedingte Verzweigung
Befehl Operanden Name/Aktion
JMP
XYZ
Definition
@
Jump
0 ( u(@) + 4 · s(XYZ) )
u64
Bedingte Verzweigungen
Befehl Operanden Name/Aktion
Definition
BZ
$X,YZ
Branch if zero
s($X) = 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
PBZ
$X,YZ
Probable br. if zero
s($X) = 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
BNZ
$X,YZ
Branch if nonzero
s($X) 6= 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
PBNZ
$X,YZ
Prob. br. if nonzero
s($X) 6= 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
BN
$X,YZ
Branch if negative
s($X) < 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
PBN
$X,YZ
Prob. br. if negative
s($X) < 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
BNN
$X,YZ
Branch if nonneg.
s($X)
0)@
0 ( u(@) + 4 · s(YZ) )
u64
PBNN
$X,YZ
Prob. br. if nonneg.
s($X)
0)@
0 ( u(@) + 4 · s(YZ) )
u64
BP
$X,YZ
Branch if positive
s($X) > 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
PBP
$X,YZ
Prob. br. if positive
s($X) > 0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
BNP
$X,YZ
Branch if nonpositive
s($X)  0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
PBNP
$X,YZ
Prob. br. if nonpos.
s($X)  0 ) @
0 ( u(@) + 4 · s(YZ) )
u64
BEV
$X,YZ
Branch if even
s($X) % 2 = 0 ) @
0 ( u(@)+4·s(YZ) )
u64
PBEV
$X,YZ
Prob. branch if even
s($X) % 2 = 0 ) @
0 ( u(@)+4·s(YZ) )
u64
BOD
$X,YZ
Branch if odd
s($X) % 2 = 1 ) @
0 ( u(@)+4·s(YZ) )
u64
PBOD
$X,YZ
Prob. branch if odd
s($X) % 2 = 1 ) @
0 ( u(@)+4·s(YZ) )
u64
6.5 MMIX Befehle
283
Betrachten Sie die folgenden Befehle:
A
LOC
GREG
OCTA
Data_Segment
@
1000
a
b
IS
IS
$1
$2
LOC
LDB
SUB
OR
BZ
JMP
TRAP
#100
a,A
a,a,1
a,a,0
a,End
Start
0,0,0
Main
Start
End
a)
Bestimmen Sie das 32 Bit breite Befehlswort des Befehls ‘‘JMP Start’’.
0xF1FFFFFD. (3 Befehle zurückspringen; FFFD ist -3 im 2er-Komplement)
T
b) Bestimmen Sie das 32 Bit breite Befehlswort des Befehls ‘‘BZ a,End’’.
0x42010002 (2 Befehle vorwärts springen)
284
c)
6 MMIX-Prozessor
Benutzen Sie MMIX Verzweigungs-Befehle um folgenden C-Code zu implementieren:
C-Code:
if(a == 0)
{
a = 1;
}
MMIX-Code:
End
BNZ
SET
...
a,End
a,1
...
d) Benutzen Sie MMIX Verzweigungs-Befehle um folgenden C-Code zu implementieren:
C-code:
int a;
...
if(a <= 0)
{
a = 1;
}
else
{
a = 2;
}
MMIX-Code:
Pos
End
BP
SET
JMP
SET
...
a,Pos
a,1
End
a,2
...
6.5 MMIX Befehle
T
e)
285
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:
L1
L2
End
BNP
BNN
SET
JMP
BP
BZ
SET
JMP
SET
...
a,L1
b,L1
a,1
End
a,L2
b,L2
a,3
End
a,2
...
286
6 MMIX-Prozessor
Befehle für Funktionsaufrufe
Befehl Operanden Name/Aktion
Definition
Go to location
$X,$Y,Z
Go to location immediate
GO
T
a)
0 ( u(@) + 4) );
u64
0 ( u($Y) + u($Z) )
@
u64
0 ( u(@) + 4) );
$X
u64
0 ( u($Y) + u(Z) )
@
u64
$X
$X,$Y,$Z
Was ist der Haupt-Unterschied zwischen dem JMP-Befehl und dem GO-Befehl?
• JMP benutzt Relative Adressierung, während GO Absolute Adressierung
verwendet.
• GO speichert die Rücksprungadresse ab, JMP nicht.
T
b) Wo speichern GO-Befehle die Rücksprungadresse ab?
Die Rücksprungadresse wird in Register X abgelegt.
T
c)
Was ist die ‘‘Rücksprungadresse’’?
Die Rücksprungadresse ist die Adresse des nächsten Befehlsworts. Wenn GO an
einer durch vier teilbaren Adresse a steht, dann ist die Rücksprungadresse a + 4.
T
d) Wenn GO Absolute Adressierung verwendet: Wie wird die Abolute Adresse (64 Bit)
im 32 Bit breiten Befehlswort abgelegt?
Genauso wie es allgemein bei Marken gemacht wird: Der Assembler transformiert
die Adresse der Marke in eine Basisadresse, die in Register Y gespeichert wird,
und einem Offset, der in Register Z oder im Direktoperanden Z gespeichert wird.
e)
Geben Sie den Befehl an, mit dem Sie die Funktion fkt aufrufen und die Rücksprungadresse in Register 0 ablegen.
GO
$0,fkt
6.5 MMIX Befehle
287
Namensräume - der PREFIX-Befehl
Der PREFIX-Befehl ist ein Assembler-Befehl. Er wird verwendet, um in einem Programm 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 angegebene 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 Zeichenkette 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, beispielsweise 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 PREFIXBefehl 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.
:Main
PREFIX
...
Main:
288
6 MMIX-Prozessor
b) Wie kann man einen Namensraum beenden, d.h. wie kann man den Assembler
anweisen, Marken/Namen nicht mehr umzuwandeln?
Wird PREFIX mit dem Operanden ‘‘:’’ aufgerufen, wird der zugehörige Namensraum
geschlossen.
c)
Wie kann man – innerhalb eines Namensraums – verhindern, dass der Assembler
einer bestimmten Marke bzw. einem bestimmten Namen die im PREFIX-Befehl
angegebene Zeichenkette voranstellt?
Man muss vor die Marke bzw. vor den Namen einen Doppelpunkt schreiben, z.B.
‘‘:SP’’ statt ‘‘SP’’.
T
d) Wozu dient der PREFIX-Befehl?
Der PREFIX-Befehl dient zur Generierung von Namensräumen.
• Kommt ein Name im selben Namensraum vor, beschreibt er die selbe
Variable/Funktion.
• Kommt ein Name in unterschiedlichen Namensräumen vor, beschreibt er
unterschiedliche Variable/Funktionen.
Hat jede Funktion einen eigenen Namensraum, kann man dieselben Variablennamen in unterschiedlichen Funktionen verwenden, ohne dass damit auf dieselben
Variablen zugegriffen wird.
T
e)
Welche Auswirkung hat der Befehl PREFIX mein_prefix auf darauf folgende MMIXAnweisungen?
Nach der Anweisung PREFIX myprefix wird jeder Marke bzw. jedem Registernamen die Zeichenkette mein_prefix vorangestellt. Gibt es z.B. eine Marke/einen
Registernamen yy, so wird dieser in mein_prefixyy umgewandelt. Dabei handelt es
sich um eine reine Textersetzung.
6.5 MMIX Befehle
T
f)
289
Geben Sie die Anweisungen an, mit denen Sie den Namensraum ‘‘Fkt:’’ eröffnen
und die globale Marke ‘‘Fkt’’ anlegen.
:Fkt
PREFIX
...
Fkt:
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 zusammengesetzt 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:
• Aufruf einer Funktion, welche den Namen der csv-Datei als Parameter übergeben bekommt und den Inhalt der Datei in den String s einliest.
• 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 von Zeigern auf die Teil-Strings zurückliefert.
• Für jeden Teilstring si : Aufruf einer Funktion, welche den String si und das
Komma-Zeichen als Parameter übergeben bekommt, den String an den Kommas in Teilstrings sij auftrennt und als Ergebnis ein Array von Zeigern auf die
Teil-Strings zurückliefert.
• Auswahl des Teil-Strings sij , in dem die EMail-Adresse gespeichert ist.
• Für jede Email-Adresse sij : Aufruf einer Funktion, die als Parameter die EmailAdresse und den Email-Text bekommt und den Email-Text an die angegebene
Email-Adresse verschickt.
290
6 MMIX-Prozessor
Wert-Übergabe und Referenz-Übergabe
Es gibt viele Möglichkeiten, Funktionen Parameter zu übergeben. Prinzipiell unterscheidet 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.
Wert-Übergabe
wird kopiert
wird kopiert
Adresse
Wert
zeigt auf
f
zeigt au
Adresse
Diese Variable steht hier im Speicher
wird kopiert
Funktion:
Wert
Speicher
wird kopiert
ruft auf
Funktionsaufrufer:
Referenz-Übergabe