Rechnerstrukturen Sommersemester 2005 10. Übung Abgabe: 06./07.07.05 in den Übungsgruppen Bei Fragen und Problemen können Sie uns per E-mail unter den folgenden Adressen erreichen: Tutoren : {christian,katrin,tina,andreas,franzi,julie,tobias}@i4.informatik.rwth-aachen.de Martin Mink : [email protected] Ralf Wienzek : [email protected] Aufgabe 1 (Präsenzaufgabe): Von-Neumann-Rechner Folgende Abbildung zeigt die Struktur einer CPU und ihre Verbindung zum RAM-Speicher. Für eine Speicheradresse a bezeichne RAM[a] die zugehörige Speicherzelle bzw. deren Inhalt. CPU Datenprozessor MR L A Befehlsprozessor Decodierer Steuerwerk ALU IR MBR MAR PC Adressbus Datenbus RAM-Speicher Adresse a 0 ... 000000 0 ... 000001 0 ... 000010 0 ... 000011 0 ... 000100 0 ... 000101 0 ... 000110 0 ... 000111 0 ... 001000 0 ... 001001 0 ... 001010 0 ... 001011 0 ... 001100 0 ... 001101 0 ... 001110 0 ... 001111 .. . Inhalt RAM[a] Zur Vereinfachung werden MR und L im Folgenden vernachlässigt: statt MR L A wird nur ein Register Akku verwendet. Nehmen Sie an, dass diesem Rechner die in der folgenden Tabelle durch ihre Operationscodes identifizierten Befehle/Operationen zur Verfügung stehen: Operationscode 0 1 2 3 4 5 6 7 8 9 10 11 Wirkung(en) der Operation PC ← PC + 1 RAM[RAM[PC + 1]] ← MBR PC ← PC + 2 MBR ← RAM[RAM[PC + 1]] PC ← PC + 2 MBR ← RAM[PC + 1] PC ← PC + 2 MBR ← Akku PC ← PC + 1 Akku ← MBR PC ← PC + 1 Akku ← Akku + MBR PC ← PC + 1 Akku ← Akku − MBR PC ← PC + 1 Akku ← Akku · MBR PC ← PC + 1 Akku ← Akku ÷ MBR PC ← PC + 1 PC ← RAM[PC + 1] Falls Akku = 0: PC ← RAM[PC + 1] Falls Akku 6= 0: PC ← PC + 2 Der Rechner kenne nur ganze Zahlen. Dementsprechend steht ÷ für die ganzzahlige Division (z.B. 26 ÷ 7 = 3). 1 Rechnerstrukturen Sommersemester 2005 a) Beschreiben Sie, wozu die Operationen mit den Operationscodes 1, 2, 3, 10, 11 dienen. Wie könnte eine passende Bezeichnung lauten? (0) (1) In nebenstehender Speicherbelegungstabelle ist zu jeder Dualzahl (mit denen reale Rechner arbeiten) auch die entsprechende Dezimalzahl (klein und in Klammern) angegeben. In Ihren Lösungen brauchen Sie nur Dezimalzahlen anzugeben. Zur Vereinfachung sei angenommen, dass die CPU bei jeder Befehlsverarbeitung nur die folgenden Zuweisungen“ ” durchführt (in dieser Reihenfolge): (2) (3) (4) (5) (6) (7) (8) (9) (10) IR ← RAM[PC] Wirkung(en) der Operation IR ( PC-Änderung zuletzt ! ) (11) (12) (13) (14) b) Protokollieren Sie den Inhalt der Register Akku, MBR, IR und PC nach jeder Befehlsverarbeitung bis PC den Wert 25 enthält, wobei zu Anfang alle Register 0 enthalten und der Speicher wie nebenstehend gefüllt ist. (15) (16) (17) (18) (19) c) Betrachten Sie nun den nebenstehenden Speicherinhalt von Adresse 0 bis Adresse 21 (einschließlich) und interpretieren Sie ihn als ein Programm. Was wird durch dieses Programm berechnet? (20) (21) (22) (23) (24) Adresse a 0 . . . 000000 0 . . . 000001 0 . . . 000010 0 . . . 000011 0 . . . 000100 0 . . . 000101 0 . . . 000110 0 . . . 000111 0 . . . 001000 0 . . . 001001 0 . . . 001010 0 . . . 001011 0 . . . 001100 0 . . . 001101 0 . . . 001110 0 . . . 001111 0 . . . 010000 0 . . . 010001 0 . . . 010010 0 . . . 010011 0 . . . 010100 0 . . . 010101 0 . . . 010110 0 . . . 010111 0 . . . 011000 .. . Inhalt RAM[a] 0 . . . 00000010 (2) 0 . . . 00010110 (22) 0 . . . 00000101 (5) 0 . . . 00000010 (2) 0 . . . 00010111 (23) 0 . . . 00000111 (7) 0 . . . 00000100 (4) 0 . . . 00000001 (1) 0 . . . 00011000 (24) 0 . . . 00001011 (11) 0 . . . 00011001 (25) 0 . . . 00000011 (3) 0 . . . 01100100 (100) 0 . . . 00000101 (5) 0 . . . 00000010 (2) 0 . . . 00011000 (24) 0 . . . 00001001 (9) 0 . . . 00000100 (4) 0 . . . 00000001 (1) 0 . . . 00011000 (24) 0 . . . 00001010 (10) 0 . . . 00011001 (25) 0 . . . 00001011 (11) 0 . . . 00000100 (4) 0 . . . 00000000 (0) .. . Aufgabe 2 (13 Punkte): Mikroprogrammierung Betrachten Sie den folgenden sehr einfachen Prozessor, der nur die vier unten angegebenen (Makro-)Instruktionen verarbeiten kann. Seine Bauteile sind mit Steuerleitungen versehen und wie in der linken Abbildung skizziert über einen internen Bus miteinander verbunden (die Abbildungen finden Sie auch in größerer Form auf der Homepage zur Vorlesung). PC: program counter; pcincr: PC increase; MAR: memory address register; ACC: accumulator; acceq0: ACC equals zero; IR: instruction register; MDR: memory data register; ALU: arithmetic logic(al) unit 2 Rechnerstrukturen Sommersemester 2005 Instruktionen und Opcodes: • load: (code 00) lädt einen Wert aus dem Speicher in den Akku • add: (code 01) addiert einen Speicherwert zum Akkuinhalt und schreibt das Ergebnis in den Akku • store: (code 10) schreibt den Inhalt des Akku in den Speicher • brz: (branch on zero, code 11) springt zur angegebenen Adresse, falls der Inhalt des Akku Null ist a) Ihre Aufgabe besteht in der Programmierung des Steuerwerks, d.h. die Signale (ACC in, ACC out, aluadd, IR in, IR out, MAR in, MDR in, MDR out, PC in, PC out, pcincr, read, TEMP out, write) der Schaltung müssen der Bedeutung der Instruktionen entsprechend durch ein Mikroprogramm angesteuert werden. Dabei gehen wir davon aus, dass die Signale ‘read’ und ‘write’ auf der in MAR enthaltenen Adresse arbeiten und die Daten in das/aus dem MDR geschrieben werden (ohne dass zusätzliche MAR/MDR-Signale gegeben werden müssen). Des Weiteren bezieht sich das Signal IR out nur auf den Adressteil des IR-Registers. Tragen Sie die fehlenden Signale in die angegebenen Zeilen (...) ein. T0 bis T7 zählt dabei die Taktschritte, die zur Abarbeitung einer Makroinstruktion notwendig sind. Schritte T0-T3 (alle Instruktionen): T0: PC out, MAR in T1: read, pcincr T2: MDR out, IR in T3: branch-via-table (‘decode’) T4-T6 für load (opcode 00): T4: ... T5: ... T6: ... T4-T6 für store (opcode 10): T4: ... T5: ... T6: ... T4-T7 für add (opcode 01): T4: ... T5: ... T6: ... T7: ... T4-T5 für brz (opcode 11): T4: if (acceq0) then {...} T5: reset to T0 b) Setzen Sie die fehlenden Bits in den Zeilen 0101 bis 1110 des control store. Geben Sie auch die Zuordnung der Zeilen des control store zu den Zeitschritten der Befehle an. c) Statt als Bitmatrix können die Signale auch direkt als Schaltfunktionen implementiert werden. Nehmen Sie an, dass in diesem Fall auf die control store address verzichtet wird. Stattdessen werden die Schritte der Mikrobefehle durch die Taktschritte T0 bis T7 adressiert. Geben Sie die Booleschen Funktionen für die Signale ‘aluadd’ faluadd (o1 , o0 ,t2 ,t1 ,t0 ) und ‘ACC out’ fACC out (o1 , o0 ,t2 ,t1 ,t0 ) in disjunktiver Form an, wobei (o1 o0 ) den aktuellen opcode und (t2 t1t0 )2 den aktuellen Taktschritt bezeichnen. Aufgabe 3 (12 Punkte + 15 Bonuspunkte = 27 Punkte): MMIX – Sortieralgorithmen Betrachten Sie die nebenstehende Implementierung des bekannten Bubblesort-Algorithmus. Die Notation ist an die Programmiersprache C angelehnt. Als ersten Eingabeparameter (OCTA *array) erwartet die Funktion einen Zeiger auf das zu sortierende Array, was gleichbedeutend mit der Speicheradresse des ersten Array-Eintrags ist. Die Funktion hat keinen Rückgabewert. Stattdessen wird das Array so überschrieben, dass die Einträge beim Verlassen der Funktion aufsteigend sortiert sind. Durch bubbleSort( zahlen, 5 ) würde beispielsweise das Array zahlen im Beispiel sortiert werden. OCTA [] zahlen = {200 ,120 ,12 ,5 ,128}; void bubbleSort ( OCTA * array , OCTA num ) { OCTA last , pairs ,j , tmp ; last = num -1; while( last >= 0 ) { pairs = last -1; last = -1; for (j =0; j <= pairs ; j ++) { if ( array [j] > array [j +1] { tmp = array [j ]; array [j] = array [j +1]; array [j +1] = tmp ; last = j; } } } } 3 Rechnerstrukturen Sommersemester 2005 Die Parameterübergabe der im Folgenden zu implementierenden Unterprogramme soll über den Registerstack erfolgen, d.h. die Unterprogramme sollen durch PUSHJ aufgerufen und mittels POP verlassen werden. a) (@) Schreiben Sie ein Unterprogramm printArray, das die Einträge eines Arrays von positiven OCTAs auf dem Bildschirm ausgibt. Die Zahlen sollen durch Leerzeichen getrennt auf einer Zeile ausgegeben werden. Das Unterprogramm erwartet zwei Parameter: die Adresse des ersten Array-Eintrags und die Anzahl der Array-Einträge. Tipp: Zur Ausgabe einer einzelnen Zahl können Sie eine für die Verwendung des Registerstacks abgewandelte Version des Unterprogramms aus der Aufgabe 5a der 8. Übung verwenden. b) (@) Implementieren Sie den oben angegebenen Bubblesort-Algorithmus als MMIX-Unterprogramm. Schreiben Sie zusätzlich ein Hauptprogramm, das zunächst das ungeordnete Array auf dem Bildschirm ausgibt, dann BubbleSort aufruft und anschließend das (geordnete) Array erneut ausgibt. Für die korrekte Bearbeitung der folgenden Aufgabenteile können Sie 15 Bonuspunkte erzielen. Ein weiterer sehr bekannter Sortieralgorithmus ist Quicksort, der ebenfalls in MMIX implementiert werden soll. Im Vergleich zu Bubblesort soll die Quicksort-Implementierung mit beliebigen Vergleichsfunktionen arbeiten können. Eine Referenz auf diese Funktion soll neben der Adresse des Arrays und der Anzahl der Elemente als dritter Funktionsparameter übergeben werden. Dabei wird vereinbart, dass die Vergleichsfunktion zwei Parameter erwartet und ihr Rückgabewert genau dann ungleich Null ist, wenn die Vergleichsbedingung erfüllt ist. Im Folgenden ist eine mögliche Implementierung von Quicksort angegeben, die in MMIX umgesetzt werden soll. Ein Aufruf könnte beispielsweise durch quicksort( zahlen, 5, comp ) geschehen. 1 2 3 4 5 6 7 8 9 10 11 12 13 OCTA[] zahlen = {200 ,120 ,12 ,5 ,128}; OCTA comp( OCTA a , OCTA b ) { return a <b; } inline void swap ( OCTA * array , OCTA a , OCTA b ) { OCTA tmp ; tmp = array [a ]; array [a ]= array [b ]; array [b ]= tmp ; } 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void quicksort ( OCTA * array , OCTA num , OCTA (* comp )(OCTA,OCTA) ){ OCTA i ,j ,v; if(num >1){ v= array [num -1]; i = -1; j=num -1; while(1){ while( comp ( array [++ i],v )); while(! comp ( array [--j],v )); if(i >= j) break; swap ( array ,i ,j); } swap( array ,i ,num -1); quicksort ( array ,i , comp ); quicksort (&( array [i +1]) , num -i -1 , comp ); } } Der reservierte Begriff inline ändert die Bedeutung des Programms nicht, bewirkt jedoch, dass bei Aufruf von swap kein Funktionsaufruf erzeugt wird, sondern die in swap definierten Befehle direkt an die Stelle des Aufrufs eingefügt werden. Dies macht die erzeugte Objektdatei zwar größer, es wird jedoch der durch einen Unterprogrammaufruf erzeugte Overhead eingespart, was sich positiv auf die Laufzeit auswirkt. Der Ausdruck ++i erhöht die Variable i um eins und ergibt den resultierenden Wert. Analoges gilt für --j. Der Ausdruck &(array[i+1]) bezeichnet die Speicheradresse des Elementes array[i+1]. c) (@) Auf der Homepage zur Vorlesung finden Sie das Gerüst qSort.mms, das zur Umsetzung des Algorithmus in MMIX benutzt werden soll. Ersetzen Sie die mit ... markierten Stellen im Gerüst so, dass sich daraus eine Implementierung des Quicksort-Algorithmus ergibt. d) Wieso wird zum Aufruf der Funktion comp der Befehl PUSHGO und nicht PUSHJ verwendet? e) Die Funktion quicksort ruft sich selbst zweimal rekursiv auf. Wieso genügt dazu eine Benutzung des Befehls PUSHJ? f) Warum ist es Ihrer Meinung nach sinnvoll oder nicht sinnvoll, eine Assemblersprache zu erlernen? 4