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
© Copyright 2024 ExpyDoc