Technische Informatik I - HS 18

Ähnliche Dokumente
Technische Informatik I Übung 3: Assembler

Technische Informatik 1 Übung 2 Assembler (Rechenübung) Georgia Giannopoulou (ggeorgia@tik.ee.ethz.ch) 22./23. Oktober 2015

Übungsblatt 10 (Block C 2) (16 Punkte)

Unterprogramme. Unterprogramme

Lösungsvorschlag zur 3. Übung

Übungsblatt 10 (Block C 2) (16 Punkte)

Grundlagen zur Assemblerprogrammierung unter SPIM im Sommersemester Lorenz Schauer Mobile & Verteilte Systeme

Computersysteme. Stacks Anwendung in der Assembler-Programmierung

Unterstützung von Jump Tables

3AA. Prozeduren und Rekursion Prof. Dr. Wolfgang P. Kowalk Universität Oldenburg WS 2005/2006

Vorlesung Rechnerarchitektur

5.GTypische Anwendungsfälle

Programmiersprachen Einführung in C

Tutorium Rechnerorganisation

Technische Informatik 1 Übung 2 Assembler (Computerübung) Matthias Meyer

Weitere Arithmetik. Grundlagen der Rechnerarchitektur Assembler 33

Lösungsvorschlag Serie 2 Rekursion

Übung Praktische Informatik II

Institut für Informatik Prof. Dr. D. Hogrefe Dipl.-Inf. R. Soltwisch, Dipl.-Inform. M. Ebner, Prof. Dr. D. Hogrefe Informatik II - SS 04.

Heute nur MIPS-Praxis (4 Aufgaben)

Erste Java-Programme (Scopes und Rekursion)

Offenbar hängt das Ergebnis nur von der Summe der beiden Argumente ab...

Objektorientierte Programmierung (ZQ1u2B)

######################### Zeichenkette auswerten ###################################

Informatik für Schüler, Foliensatz 18 Rekursion

Technische Informatik 1 Übung 5: Eingabe/Ausgabe (Computerübung) Georgia Giannopoulou, ETZ G & 18.

Technische Informatik I - HS 18

Speicher und Adressraum

Technische Informatik 1 - HS 2017

Technische Informatik II Rechnerarchitektur

Technische Informatik I - HS 18

Lösungsvorschlag 9. Übung Technische Grundlagen der Informatik II Sommersemester 2009

Das Kontrollfluss-Diagramm für Ò ¼ µ:

Technische Informatik 1 Übung 6 Pipelining (Rechenübung) Andreas Tretter 24./25. November 2016

Darstellung von Instruktionen. Grundlagen der Rechnerarchitektur Assembler 21

Grundlagen der Programmierung WS 15/16 (Vorlesung von Prof. Bothe)

Notwendigkeit für andere Instruktionsformate

Datenstrukturen, Alignment Stack Prozeduraufruf, Parameterübergabe und -rückgabe (Calling Conventions) Leaf procedures

Technische Informatik I - HS 18

Assembler Unterprogramme

OOP Aufgabenblatt 7 6. Dezember 2013

Beispiel: A[300] = h + A[300]

Beispielhafte Prüfungsaufgaben zur Vorlesung TI I, gestellt im Frühjahr 2009

Praktikum Technische Informatik

Vorkurs Informatik WiSe 17/18

RO-Tutorien 15 und 16

Computer-Systeme Teil 11: Routinen

Klassenvariablen, Klassenmethoden

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2017/18. Vorbereitende Aufgaben

Informatik II Übung 05. Benjamin Hepp 3 April 2017

Einführung in die Systemprogrammierung

Technische Informatik 1 - HS 2017

Arithmetik, Register und Speicherzugriff. Grundlagen der Rechnerarchitektur Assembler 9

Technische Informatik II Rechnerarchitektur

Rekursion. L. Piepmeyer: Funktionale Programmierung - Rekursion

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2016/17. Vorbereitende Aufgaben

Technische Informatik 1 - HS 2017

3. Basiskonzepte von Java

Klausur zur Vorlesung Grundlagen der Rechnerarchitektur SS 2013

Programmierung für Mathematik HS11

4. Mikroprogrammierung (Firmware)

Lösungsvorschlag 10. Übung Technische Grundlagen der Informatik II Sommersemester 2009

Schnittstellen, Stack und Queue

C++ Teil 5. Sven Groß. 12. Nov IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Einführung in die Systemprogrammierung

32 Bit Konstanten und Adressierung. Grundlagen der Rechnerarchitektur Assembler 78

Einführung. Saalübung Informatik II SS Einführung. Einführung

Programmierung für Mathematik (HS13)

11. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Mathematische Rekursion. Rekursion in Java: Genauso! Unendliche Rekursion. n!

U23 Assembler Workshop

Informatik Rechnerinterne Vorgänge: Programmstrukt. (Lsg.) Gierhardt

12. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Lernziele. Mathematische Rekursion. Rekursion in Java: Genauso! n! =

Übungspaket 22 Rekursive Funktionsaufrufe

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Assembler Programmierung Motivation. Informatik II SS 2004 Teil 4: Assembler Programmierung. Assembler vs. Maschinensprache

1 pulsierender Speicher

Übung zur Vorlesung EidP (WS 2018/19) Blatt 4

Programmieren in C. Rekursive Strukturen. Prof. Dr. Nikolaus Wulff

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Rechnern netze und Organisatio on

9. Rekursion. 1 falls n 1 n (n 1)!, andernfalls. Experiment: Die Türme von Hanoi. Links Mitte Rechts. Mathematische Rekursion

Technische Informatik 1 Übung 7 Pipelining (Rechenübung) Balz Maag 22./23. November 2018

Technische Informatik 1 - HS 2016

Matrikelnummer:

Grundlagen der Informatik III Wintersemester 2010/ Vorlesung Dr.-Ing. Wolfgang Heenes

= 7 (In Binärdarstellung: = 0111; Unterlauf) = -8 (In Binärdarstellung: = 1000; Überlauf)

Informatik I (D-ITET)

4 Rekursionen. 4.1 Erstes Beispiel

Grundbegriffe der Informatik

Mikrocontroller-Programmierung

6 Speicherorganisation

Vorkurs Informatik WiSe 16/17

Methoden. Gerd Bohlender. Einstieg in die Informatik mit Java, Vorlesung vom

Aufruf des Compilers in der Kommandozeile und Ausführung des Programms:

Rechnerstrukturen Wintersemester 2002/03. Maschinensprache Opcode, Operanden, Adressierung Für Menschen schwer verdauliche Folgen von 0 und 1

Software Entwicklung 1. Rekursion. Beispiel: Fibonacci-Folge I. Motivation. Annette Bieniusa / Arnd Poetzsch-Heffter

Transkript:

Institut für Technische Informatik und Kommunikationsnetze Prof. L. Thiele Technische Informatik I - HS 18 Musterlösung zu Übung 3 Datum : 25.-26. Oktober 2018 Aufgabe 1: Wurzelverfahren nach Heron Das babylonische Verfahren zum Wurzelziehen, das von Heron überliefert wurde, berechnet die Quadratwurzel x der Zahl a durch iterative Anwendung der Rechenvorschrift x n+1 = 1 (x n + a ) 2 xn mit x 0 = a. Gegeben sei folgender Assemblercode zur Berechnung der Quadratwurzel von 2 nach dem Heron-Verfahren (10 Iterationsschritte) mit zwei Implementierungsvarianten für die Subroutine heron. Anmerkungen zum Assemblercode: Bei den Registern f0, f2, f4, f12 und f20 handelt es sich um Register für Fliesskommazahlen. f 12 ist das Argument der Subroutine, f 0 enthält den Rückgabewert der Subroutine. Spezielle Register der MIPS CPU PC: Program Counter. Zeigt auf die Instruktion, welche gerade ausgeführt wird. Die nächste Instruktion befindet sich an der Stelle Reg[PC] + 4 (Alle Instruktionen sind 32 Bit lang). RA: Return Address. Nach der Ausführung von JAL, enthält das Register RA die Adresse der Folge- Instruktion von JAL, also Reg[PC] + 4. Nach der Ausführung von JR in der aufgerufenen Subroutine, wird der Inhalt des Registers RA wieder in das PC-Register geladen. Dies ermöglicht den Rücksprung zur Folge-Instruktion von JAL. FP: Frame Pointer. Zeigt auf das erste Argument einer Subroutine. SP: Stack Pointer. Zeigt auf das letzte besetzte Wort auf dem Stack. Der Assemblercode ist hinsichtlich Fliesskommaoperationen und Verwaltung des Stacks vereinfacht dargestellt. Die Verwaltung des Frames, sowie das Speichern und Rückspeichern von fp sind durch ersetzt. Hauptprogramm main: li $f12, 2.0e0 # $f12 := 2 li $a1, 10 # $a1 := 10 jal heron # Jump and Link to heron ($ra := $pc + 4) 1

Implementierung 1 heron: move $f2, $f12 # $f2 := $f12 move $t1, $zero # $t1 := 0 (Register $zero ist immer Null) ble $a1, $zero, Label3 # if ($a1 <= $zero) then goto Label3 li $f4, 5.0e-1 # $f4 := 0.5 Label5: div $f0, $f12, $f2 # $f0 := $f12 / $f2 add $f0, $f2, $f0 # $f0 := $f0 + $f2 mul $f0, $f0, $f4 # $f0 := $f0 * $f4??? # ==> Hier fehlt eine Zeile slt $t0, $t1, $a1 # if ($t1 < $a1) then $t0 := 1 # else $t0 := 0 move $f2, $f0 # $f2 := $f0 bne $t0, $zero, Label5 # if ($t0!= $zero) then goto Label5 Label3: move $f0, $f2 # $f0 := $f2 jr $ra # Jump to address in Register $ra (=> return) Implementierung 2 heron: # Frameverwaltung inkl. Aenderung des SP # $ra und $f20 werden im Stack gespeichert move $f20, $f12 # $f20 := $f12 bgt $a1, $zero, Label2 # if ($a1 > $zero) then goto Label2 move $f0, $f20 # $f0 := $f20 j Label4 # jump to Label4 Label2: move $f12, $f20 # $f12 := $f20 addi $a1, $a1, -1 # $a1 := $a1-1 jal heron # Jump and Link to heron div $f2, $f20, $f0 # $f2 := $f20 / $f0 add $f2, $f2, $f0 # $f2 := $f2 + $f0 li $f0, 5.0e-1 # $f0 := 0.5 mul $f2, $f2, $f0 # $f2 := $f2 * $f0 move $f0, $f2 Label4: # $ra und $f20 werden aus dem Stack geladen # Ruecksetzen des SP jr $ra # Jump to address in Register $ra (=> return) 2

(a) Implementierung 1 ist unvollständig. Was fehlt? Ergänzen Sie das Assemblerprogramm, indem Sie an der mit??? markierten Stelle eine Zeile einfügen. Es fehlt die Inkrementierung in der Schleife. addi $t1, $t1, 1 oder addi $a1, $a1, -1 (b) Geben Sie zu Implementierung 2 ein möglichst kompaktes Programm in C oder Java an, das den wesentlichen Programmablauf in Implementierung 2 widerspiegelt. float heron(float a, int n) { if (n > 0) { float prev_res = heron(a, n-1); return (0.5 * (prev_res + a / prev_res)); else return a; void main() { float sqrt2 = heron(2,10); (c) Wo liegt der prinzipielle Unterschied zwischen der (vervollständigten) Implementierung 1 und Implementierung 2? Welche von beiden ist schneller? Implementierung 1: Schleife. Implementierung 2: Rekursion. Die Schleife ist schneller als die Rekursion, da weniger Instruktionen ausgeführt werden und der Aufbau des Stacks weniger aufwändig ist. Aufgabe 2: Fibonacci-Zahlen Die folgende rekursive Rechenvorschrift ermöglicht Ihnen, die Fibonnacci-Zahlen zu berechnen: F ib(n) = F ib(n 1) + F ib(n 2) F ib(1) = F ib(2) = 1 Diese soll nun in Assembler implementiert werden. Dazu wird Schrittweise der Ablauf eines Funktionsaufrufes durchgegangen (vgl. Vorlesungsfolien). Um Ihnen die Arbeit etwas zu vereinfachen, ist der erste Teil des Assembler-Programms vorgegeben: 3

.data in_string: out_string:.asciiz "Bitte geben Sie eine ganze Zahl ein:\n".asciiz "Die Fibonacci-Zahl lautet:\n".text start: puts in_string # Ausgabe des Strings geti $s0 # Einlesen der Eingabe in s0 # Schritt 1: nicht noetig, da ungenutzt move $a0, $s0 # Schritt 2: Das Argument fuer die # Fib Subroutine wird in a0 gespeichert jal Fib # Schritt 3: Sprung zur Fib Subroutine move $s1, $v0 # Schritt 11: Hole das Resultat aus v0 # Schritt 12: nicht noetig puts out_string # Ausgabe des Strings puti $s1 # Ausgabe der Fibonnacci-Zahl done Es ist empfehlenswert die Subroutine Fib in drei Teile aufzuspalten: Vorbereitungsphase: In diesem Teil werden die notwendigen Vorbereitungen getroffen, damit der Stack sauber aufgebaut wird. Hier sollte auch die Rekursionsbedingung stehen: if (n > 2) then rekursion else abbauphase Rekursion: Hier erfolgt der eigentliche Aufruf von F ib(n 1) und F ib(n 2). Hier steht auch die entsprechende Rekursionsgleichung. Abbauphase: Hier wird einerseits der Stack wieder abgebaut und andererseits das Resultat in das Register v0 gespeichert damit es vom aufrufenden Programm genutzt werden kann. # Subroutine Fib # Eingabe: Integer n, auf dem Stack # Ausgabe: Fib(n), ebenfalls auf dem Stack Fib: # Vorbereitungsphase: sw $ra, 4($sp) # Schritt 5: # Da wir mit mehrfach verschachtelten # Subroutinen arbeiten, muessen wir # die Return Adresse ra auf dem # Stack sichern. bgt,, rekursion # Rekursionsbedingung und Sprung zur # Rekursionsphase j abbauphase # Zur Abbauphase springen rekursion: 4

jal Fib # Fib(n-1) jal Fib # Fib(n-2) abbauphase: jr $ra # Schritt 10: Ruecksprung Tipps: Gehen Sie am besten wie folgt vor: (a) Schreiben Sie die Routine kurz in C oder Java auf und bringen Sie ihren Code mit dem gegebenen Assembler-Skelett in Beziehung. (b) Überlegen Sie, welche Register sie benötigen, und welche Register gesichert werden müssen. Zeichnen Sie auf, wie Ihr Stack aussehen muss. Vergessen Sie nicht, Stack-Pointer und Frame-Pointer nachzuführen und beachten Sie die Verwaltung der Rücksprungadressen. (c) Implementieren Sie die Frameverwaltung. Kontrollieren Sie, dass alle gesicherten Variablen am Ende der Funktion wiederhergestellt sind. Achten Sie insbesondere darauf, dass der Stack-Pointer wieder den gleichen Wert hat. (d) Implementieren Sie schliesslich den Basisfall und die rekursiven Aufrufe. (a) Der folgende C Code implementiert die Routine. int Fib(int n) { int result; if (n <= 2) { result = 1; else { int n1 = Fib(n-1); int n2 = Fib(n-2); result = n1 + n2; return result; (b) Die folgende Tabelle ziegt, welche Register gesichert werden müssen. Variable Zu sichern? n ja result nein n1 ja n2 nein (c) & (d) Der folgende Code zeigt die nötigen Schritte für Frameverwaltung, Basisfall und rekursive Aufrufe.

.data in_string: out_string:.asciiz "Bitte geben Sie eine ganze Zahl ein:\n".asciiz "Die Fibonacci-Zahl lautet:\n".text start: puts in_string # Ausgabe des Strings geti $s0 # Einlesen der Eingabe in s0 # Schritt 1: nicht noetig move $a0, $s0 # Schritt 2: Das Argument fuer die # Fib Subroutine wird in a0 gespeichert jal Fib # Schritt 3: Sprung zur Fib Subroutine move $s1, $v0 # Schritt 11: Hole das Resultat aus v0 # Schritt 12: nicht noetig puts out_string # Ausgabe des Strings puti $s1 # Ausgabe der Fibonnacci-Zahl done # Subroutine Fib # Eingabe: Integer n, in a0 # Ausbage: Fib(n), in v0 Fib: # Vorbereitungsphase: addi $sp, $sp, -12 # Schritt 4: Stack Pointer herabsetzen sw $a0, 8($sp) # Schritt 5: # Das Argument von Fib im Stack sichern sw $ra, 4($sp) # 5: Da wir mit mehrfach verschachtelten # Subroutinen arbeiten, muessen wir # die Return Adresse ra auf dem # Stack sichern. sw $fp, 0($sp) # 5: Alten Frame Pointer auf Stack retten addi $fp, $sp, 8 # Schritt 6: Neuen Frame Pointer setzen # (zeigt auf den Rahmenanfang & # in diesem Fall auf das Argument) move $t0, $a0 # Das Argument von Fib in t0 laden li $t1, 2 bgt $t0, $t1, rekursion # if n > 2 then goto $rekursion li $t0, 1 # else fib(2) = fib(1) = 1 j abbauphase # Zur Abbauphase springen rekursion: addi $sp, $sp, -4 # Stack Pointer herabsetzen. Wir wollen # einen weiteren Wert speichern 6

addi $a0, $t0, -1 # Argument fuer Fib(n-1) # a0 = n-1 jal Fib # Fib(n-1) sw $v0, 0($sp) # Resultat von Fib(n-1) auf dem # Stack speichern lw $t0, 0($fp) # Argument von Fib wieder holen # t0 = n addi $a0, $t0, -2 # Argument fuer Fib(n-2) # a0 = n-2 jal Fib # Fib(n-2) move $t0, $v0 # Resultat von Fib(n-2) aus v0 # holen und in t0 laden lw $t1, 0($sp) # Resultat von Fib(n-1) vom Stack # holen und in t1 laden add $t0, $t0, $t1 # t0 = Fib(n-2) + Fib(n-1) addi $sp, $sp, 4 # Stack Pointer heraufsetzen abbauphase: # Im Register t0 liegt das Resultat move $v0, $t0 # Schritt 7: Resultat sichern lw $fp, 0($sp) # Schritt 8: Alten Frame Pointer holen # und gleich in fp laden lw $ra, 4($sp) # 8: Return Adresse vom Stack holen addi $sp, $sp, 12 # Schritt 9: Stack Pointer heraufsetzen jr $ra # Schritt 10: Ruecksprung 7