Technische Informatik I Übung 3: Assembler

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

Technische Informatik I - HS 18

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

Unterprogramme. Unterprogramme

Vorlesung Rechnerarchitektur

Computersysteme. Stacks Anwendung in der Assembler-Programmierung

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

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

Lösungsvorschlag zur 3. Übung

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

5.GTypische Anwendungsfälle

Objektorientierte Programmierung (ZQ1u2B)

Tutorium Rechnerorganisation

Unterstützung von Jump Tables

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

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

Assembler Unterprogramme

Weitere Arithmetik. Grundlagen der Rechnerarchitektur Assembler 33

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

Praktikum Technische Informatik

Informatik I (D-ITET)

Lösungsvorschlag Serie 2 Rekursion

UE Algorithmen und Datenstrukturen 1 UE Praktische Informatik 1. Übung 7. Entrekursivierung

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

Speicher und Adressraum

U23 Assembler Workshop

Vorkurs Informatik WiSe 17/18

Stack, Stackpointer, Unterprogramm HP: 0 * 1 * 2 * 3 CAL UP1 4 * 5 * 6 CAL UP2 7 *... UP1: 30 * 33 RET UP2: 40 * 41 CAL UP1 42 * 43 RET

To know recursion, you must first know recursion. Borchers: Programmierung für Alle (Java), WS 06/07 Kapitel 17 1

Adressierungsarten des 6809 (Forts.)

Heute nur MIPS-Praxis (4 Aufgaben)

3. Basiskonzepte von Java

Programmieren 1 C Überblick

6 Speicherorganisation

6 Speicherorganisation

EINI WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

U23 Assembler Workshop

Vorkurs Informatik WiSe 16/17

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

Technische Informatik II Rechnerarchitektur

Technische Informatik II Rechnerarchitektur

RO-Tutorien 15 und 16

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

Vorlesung: Rechnerstrukturen, Teil 2 (Modul IP7)

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

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

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

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

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

Programmiersprachen Einführung in C

Mathematische Rekursion

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

Vorlesung Programmieren

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

Mikrocomputertechnik. Unterprogramm

Elementare Konzepte von

Karlsruher Institut für Technologie

Klassenvariablen, Klassenmethoden

Übung Praktische Informatik II

Technische Informatik 1 - Übung 3 3. & 4. November Philipp Miedl

C++ - Kontrollstrukturen Teil 2

Kapitel 7: Rekursion. Inhalt. Rekursion: Technik Rekursion vs. Iteration

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

Erste Java-Programme (Scopes und Rekursion)

II.3.1 Rekursive Algorithmen - 1 -

Vorlesung Programmieren

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

Informatik I (D-MAVT)

Kodieren von Anweisungen im Binärformat für Maschinen quasi natürlich, zumindest effizient. Für Menschen hingegen ist Binärformat schwierig

Technische Informatik 1

Informatik II Übung 4 Gruppe 7

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

Technische Informatik 1 - HS 2017

Exploit-Entwicklung mit Python

Übung zu Betriebssysteme

28. März Name:. Vorname. Matr.-Nr:. Studiengang

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Informatik für Schüler, Foliensatz 18 Rekursion

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Algorithmen & Programmierung. Rekursive Funktionen (1)

Selbststudium Informationssysteme - H1102 Christian Bontekoe & Felix Rohrer

Einführung in die Informatik I

C++ Teil 4. Sven Groß. 30. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 16

Einführung in die Programmierung Wintersemester 2017/18

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Einführung in die Programmierung Wintersemester 2010/11

Informatik II Übung 4 Gruppe 7

8 Anwendung: Suchen. Folge a ganzer Zahlen; Element x. Wo kommt x in a vor?

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

C.3 Funktionen und Prozeduren

Computer-Systeme Teil 11: Routinen

Einführung in die Systemprogrammierung

Vorsemesterkurs Informatik Übungsaufgaben. Tag 4a - Python

Inhalt Kapitel 2: Rekursion

1 pulsierender Speicher

Arithmetik, Register und Speicherzugriff. Grundlagen der Rechnerarchitektur Assembler 9

Transkript:

Technische Informatik I Übung 3: Assembler Roman Trüb Computer Engineering Group, ETH Zürich 1

Lernziele Übung 3 Aufgabe 1 Aufbau und Aufruf von Funktionen in Assembler Assembler Codeanalyse Aufgabe 2 Aufbau und Manipulation des Stacks Schreiben einer vollständigen Assembler-Funktion 2

Voraussetzungen Übung 3 Grundlegend Assembler-Kenntnisse Vorlesung Kapitel 2 Computerübung 2 Funktionen und Stack Vorlesung Kapitel 3 (v.a. Folien 3-10 bis 3-21) Hennessy Appendix A, A.6 3

Stack wächst nach unten Der Stack [3-14] Adresse 0xFFFFFFFF Sichern von Kontext im Speicher: Argumente, Registerinhalten und lokale Variablen Aufgrund verschachtelter Funktionsaufrufe keine absolute Adresse im Speicher Stackframe main() Stackframe Func1() Stackframe Func2() Stackframe Func3() freier Stack Adresse 0x0 4

Stack wächst nach unten Stack bei Funktionsaufruf $fp Gesicherte Argumente Rücksprungadresse Framepointer Stackframe der aufrufenden Funktion $sp lokale Daten 5

Funktionsaufruf: Sichern der Register [3-15] Aufrufendes Programm Vor Funktionsaufruf temporäre Register sichern (wenn nicht als Parameter genutzt) Unterprogramm Am Anfang der Funktion sichere Register sichern (wenn in Funktion geändert) Sichere Register $s0-$s7 $sp, $fp Temporäre Register $t0-$t9 $a0-$a3 $ra $v0, $v1 $gp 6

Ablauf eines Funktionsaufrufs [3-15] Aufrufendes Programm Unterprogramm 1. Temporäre Register sichern 2. Argumente speichern 3. Sprunginstruktion (jal) 4. Rahmen allozieren ($sp) 5. Sichere Register speichern 6. Rahmenzeiger $fp nachführen 11. Temporäre Register laden 12. Zeiger $sp zurücksetzen (2.) 7. Resultate sichern 8. Sichere Register laden 9. Rahmen de-allozieren ($sp) 10. Zurückspringen (jr $ra) 7

Funktionsaufruf mit Sprunginstruktionen Funktionsaufruf jal Label2 # $ra=pc+4 & go to Label2 Zurückspringen (am Ende der Funktion) jr $ra # PC=$ra (Adresse der nächsten Instruktion ist in Register $ra) 8

Übungsaufgaben 9

Aufgabe 1: Wurzelfunktion Implementierung des Heron Verfahrens Eingabe: $f12 = Radikand a $a1 = Anzahl Iterationen n max Iteration: x n+1 = 1 x 2 n + a x n Ausgabe: $f0 = Ergebnis x nmax Keine Stackverwaltung Sicherung der Register vereinfacht 10

Aufgabe 1: Implementierung 2 heron: move $f20, $f12 Sichern der Register $ra und $f20 Label4: jr $ra Wiederherstellen der Register Register werden vor Verwendung gesichert, um sie am Ende der Funktion wieder in den Originalzustand zu versetzen 11

Lösung zu Aufgabe 1 12

Lösung 1: Implementierung 1 heron: move $f2, $f12 # $f2 := $f12 move $t1, $zero # $t1 := 0 ble $a1, $zero, $Label3 # if ($a1 <= $0) 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 addi??? $t1, $t1, 1 # ==> Hier # oder: fehlt addi eine Zeile $a1, $a1, -1 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 and return ($pc := $ra) Initialisierung x n+1 = 1 2 x n + a x n Schleifenzähler while ($t1 < n) Finalisierung 13

Lösung 1: Implementierung 2 (main) void main(void) { float sqrt2 = heron(2, 10); main: li $f12, 2.0e0 li $a1, 10 jal heron 14

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register if (n <= 0) { return a; else { float prev_res = heron(a, n-1); return (0.5*(prev_res + a/prev_res)); // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result a a 15

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result a a 16

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register if (n <= 0) { else { // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result a a 17

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register if (n <= 0) { return a; else { // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result a a 18

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register if (n <= 0) { return a; else { float prev_res = heron(a, n-1); // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result/ prev_res a a 19

Lösung 1: Implementierung 2 (heron) float heron(float a, int n) { // Sichern der Register if (n <= 0) { return a; else { float prev_res = heron(a, n-1); return (0.5*(prev_res + a/prev_res)); // Wiederherstellen der Register heron: move $f20, $f12 bgt $a1, $0, $Label2 move $f0, $f20 j $Label4 $Label2: move $f12, $f20 addi $a1, $a1, -1 jal heron div $f2, $f20, $f0 add $f2, $f2, $f0 li $f0, 5.0e-1 mul $f2, $f2, $f0 move $f0, $f2 $Label4: jr $ra Reg. a1 f0 f2 f12 f20 Variable n result prev_res temp a a 20

Lösung 1: Effizienz Implementierung 1: Iteration (Schleifen) Implementierung 2: Rekursion Schleifen sind schneller: Aufbau des Stacks weniger aufwändig Weniger Instruktionen (Register effektiver ausgenutzt) 21

Aufgabe 2: Fibonacci-Zahlen Fib n = Fib n 1 + Fib n 2 Fib 1 = Fib 2 = 1 22

Aufgabe 2: Register nach Funktionsaufrufen li $s3, 3 # $s3 = 3 li $t2, 2 # $t2 = 2 li $a1, 1 # $a1 = 1 li $v0, 0 # $v0 = 0 jal somefunction # $s3 == # $t2 == # $a1 == # $v0 == 3 [nicht definiert] [nicht definiert] [evtl. Rückgabewert von somefunction, ansonsten nicht definiert] 23

Stack wächst nach unten Aufgabe 2: Stack am Funktionsanfang $fp Gesicherte Argumente Rücksprungadresse Framepointer Stackframe der aufrufenden Funktion $sp lokale Daten 24

Lösung Aufgabe 2 25

Lösung 2: Pseudocode 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; Fib: # Vorbereitungsphase: sw $ra, 4($sp) bgt,, recursion j abbauphase rekursion: jal Fib jal Fib abbauphase: j $ra 26

Lösung 2: Registerzuordnung 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; Variable n result n1 n2 Zu sichern? ja nein ja nein Temporäre Register für Zwischenergebnisse verwenden 27

Lösung 2: Vorbereitungsphase Fib: 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) # Schritt 5: ra 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 $recursion li $t0, 1 # else fib(2) = fib(1) = 1 j abbauphase # Zur Abbauphase springen 28

Stack wächst nach unten Lösung 2: Stack nach Vorbereitungsphase Gesicherte Argumente Rücksprungadresse Framepointer lokale Daten Stackframe der aufrufenden Funktion $fp $sp n altes $ra altes $fp Argument der Funktion zu sichernde Register Push $ra: addi $sp, $sp, -4 sw $ra, 0($sp) Pop $ra: lw $ra, 0($sp) addi $sp, $sp, 4 29

Lösung 2: Aufruf von Fib(n-1) move $t0, $a0 # Das Argument n von Fib in t0 laden rekursion: addi $sp, $sp, -4 # Stack Pointer herabsetzen. Wir wollen # einen weiteren Wert speichern addi $a0, $t0, -1 # $t0 = n-1 jal Fib # Fib(n-1) sw $v0, 0($sp) # Resultat von Fib(n-1) auf dem # Stack speichern 30

Stack wächst nach unten Lösung 2: Stack nach Aufruf von Fib(n-1) Gesicherte Argumente Rücksprungadresse Framepointer lokale Daten Stackframe der aufrufenden Funktion $fp $sp n altes $ra altes $fp Fib(n-1) Argument der Funktion gesicherte Register Resultat von Fib(n-1) Resultat vorläufig auf Stack belassen 31

Lösung 2: Aufruf von Fib(n-2) rekursion: addi $sp, $sp, -4 # Stack Pointer herabsetzen addi $a0, $t0, -1 # $t0 = n-1 jal Fib # Fib(n-1) sw $v0, 0($sp) # Resultat von Fib(n-1) 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) 32

Lösung 2: Rekursion rekursion: addi $sp, $sp, -4 # Stack Pointer herabsetzen addi $a0, $t0, -1 # $t0 = n-1 jal Fib # Fib(n-1) sw $v0, 0($sp) # Resultat von Fib(n-1) speichern lw $t0, 0($fp) # Argument von Fib wieder holen addi $a0, $t0, -2 # Argument fuer Fib(n-2) jal Fib # Fib(n-2) move $t0, $v0 # Resultat von Fib(n-2) aus v0 # holen und in t0 laden lw $t1, 4($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 33

Stack wächst nach unten Lösung 2: Stack vor Abbauphase Gesicherte Argumente Rücksprungadresse Framepointer lokale Daten Stackframe der aufrufenden Funktion $fp $sp n altes $ra altes $fp Argument der Funktion gesicherte Register 34

Lösung 2: Abbauphase abbauphase: move $v0, $t0 # Im Register t0 liegt das Resultat # 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 35

Stack wächst nach unten Lösung 2: Stack nach Abbauphase $fp Gesicherte Argumente Rücksprungadresse Framepointer Stackframe der aufrufenden Funktion $sp lokale Daten 36

Lösung 2: Abschliessende Bemerkungen Auch hier iterative Implementierung möglich: int Fib(int n) { int i1 = 1, i2 = 1, tmp; while(n-- > 2) { tmp = i1+i2; i2 = i1; i1 = tmp; return i1; Iteratives Verfahren deutlich effizienter Immer hinterfragen: Problem wirklich rekursiv? 37