• Keine Ergebnisse gefunden

Und noch ein Quiz

N/A
N/A
Protected

Academic year: 2022

Aktie "Und noch ein Quiz"

Copied!
26
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Und noch ein Quiz

Annahme:

$s1 = 0xFFFFFFFF

$s2 = 0x00000001

In welchem der beiden Code‐Abschnitte wird gesprungen?

...

slt $t0,$s1,$s2

bne $t0,$zero, lab ...

...

lab: ...

...

...

sltu $t0,$s1,$s2 beq $t0,$zero, lab ...

...

lab: ...

Sprung: ...

ja nein

Sprung:

ja nein

(2)

Prozeduren

(3)

Das Prinzip von Prozeduren

Hauptprogramm:

. . .

x = 2*fakultät(10) .

. . Programm‐

abarbeitung

Prozedur mit dem  Namen fakultät

. .

Berechne n!

. . Prozeduraufruf

mit Parameter n=10

Prozedurrücksprung mit Ergebnis n!

Randbemerkung: was ist n! ?

(4)

Programmzähler und Rücksprungadresse

0x0040000 : 0011 ... 1001 0x0040004 : 0001 ... 1000 0x0040008 : 1001 ... 1111 0x004000c : 1011 ... 0001 0x0040010 : 0011 ... 1000 0x0040014 : 1001 ... 1111 0x0040018 : 0001 ... 0001 0x004001c : 1011 ... 0011 0x0040020 : 1011 ... 1100 0x0040024 : 0101 ... 1001 0x0040028 : 1000 ... 0011 0x004002c : 1000 ... 1011 0x0040030 : 0001 ... 1100 0x0040034 : 1001 ... 1111 0x0040038 : 1001 ... 1111

Startadresse des Hauptprogramms Aufruf der Prozedur

Register $pc

Prozedur Fakultät

Rücksprung aus der Prozedur

Adresse Maschineninstruktion

Register $ra

(5)

Assembler‐Beispiel

Hauptprogramm: ...

0x004000c addi $a0,$zero,10 # setze $a0 auf 10 0x0040010 jal Fakultaet # rufe Prozedur auf 0x0040014 sll $v0,2 # Berechne Rückgabe*2

...

Fakultaet:

# Die Prozedur Fakultaet

# erwartet den Übergabeparameter in $a0

# gibt das Ergebnis in $v0 zurück

0x0040024 ... # Berechnung der Fakultät ... # Das Ergebnis sei in $a0 0x004002c add $v0,$a0,$zero # speichere Ergebnis in $v0 0x0040030 jr $ra

Register $pc Register $ra Register $a0 Register $v0

(6)

Problem

Hauptprogramm:

. .

$s0 = 42 vor Aufruf

. .

x = 2*fakultät(10) .

.

Annahme immer  noch $s0=42 !?!

. . Programm‐

abarbeitung

Prozedur mit dem  Namen fakultät

. .

Berechne n!

Überschreibe dabei 

$s0 mit 114 .

. Prozeduraufruf

mit Parameter n=10

Prozedurrücksprung mit Ergebnis n!

Register $s0

(7)

Lösung

Hauptprogramm:

. .

$s0 = 42 vor Aufruf

.

x = 2*fakultät(10) .

.

Es gilt immer  noch $s0=42 !!!

. .

Prozedur mit dem  Namen fakultät

Rette Inhalt von $s0  auf dem Stack

.

Berechne n!

($s0 wird dabei  überschrieben) Restauriere Inhalt  von $s0 mittels Stack

. Register $s0 .

0x7fffffff : ...

0x7ffffffe : ...

0x7ffffffd : ...

0x7ffffffc : ...

0x7ffffffb : ...

0x7ffffffa : ...

0x7ffffff9 : ...

0x7ffffff8 : ...

0x7ffffff7 : ...

0x7ffffff6 : ...

0x7ffffff5 : ...

0x7ffffff4 : ...

0x7ffffff3 : 0x7ffffff2 : 0x7ffffff1 : 0x7ffffff0 : 0x7fffffef : 0x7fffffee : 0x7fffffec :

.

Register $sp

Stack

(8)

Assembler‐Beispiel

Fakultaet: addi $sp, $sp, -4 # erhöhe Stack-Pointer um ein Word sw $s0, 0($sp) # rette $s0 auf Stack

# berechne Fakultät

# $s0 wird dabei überschrieben

lw $s0, 0($sp) # restauriere $s0 vom Stack addi $sp, $sp, 4 # dekrementiere Stack-Pointer jr $ra # Springe zurück zum Aufrufer

...

0x7ffffff7 : ...

0x7ffffff6 : ...

0x7ffffff5 : ...

0x7ffffff4 : ...

0x7ffffff3 : 0x7ffffff2 : 0x7ffffff1 : 0x7ffffff0 : 0x7fffffef : 0x7fffffee : 0x7fffffec :

...

Register $s0 Register $sp

(sei $s0=0xffef2314 vor Aufruf von Fakultaet)

(9)

Registerkonvention

Name Nummer Verwendung Wird über Aufrufgrenzen bewahrt?

$zero 0 Konstante 0 n.a.

$at 1 nein

$v0‐$v1 2‐3 Prozedur‐Rückgabe nein

$a0‐$a3 4‐7 Prozedur‐Parameter nein

$t0‐$t7 8‐15 Temporäre nein

$s0‐$s7 16‐23 Temporär gesicherte ja

$t8‐$t9 24‐25 Temporäre nein

$k0‐$k1 26‐27 nein

$gp 28 ja

$sp 29 Stack‐Pointer ja

$fp 30 ja

$ra 31 Return‐Adresse ja

(10)

Rekursive Prozeduren

Hauptprogramm:

. . .

x = 2*fakultät(10) .

. .

Prozedur mit dem  Namen fakultät

. .

Berechne n!

. . Prozeduraufruf

Letzter Rücksprung mit Gesamtergebnis

Wenn Rekursionsende noch nicht erreicht, dann erneuter Prozeduraufruf

(„mit kleinerem Parameter“)

Alle vorigen Rücksprünge

(11)

Verwendung des Stacks

Haupt‐

programm

Fakultät

Fakultät

Fakultät

Rekursionsende Stack

$sp

Fakultät

(12)

Assembler‐Beispiel

Auf der nächste Folie wollen wir die Fakultät n! nach folgendem  Algorithmus berechnen

int fact (int n) { if (n < 1) {

return 1;

}

else {

return n * fact(n-1);

} }

(13)

Assembler‐Beispiel

# Berechnung der Fakultät von n (also n!)

# Eingabeparameter n ist in $a0 gespeichert

# Rückgabeparameter der Berechnung ist $v0

fact: addi $sp, $sp, -8 # push Stack-Pointer um zwei Word sw $ra, 4($sp) # rette Rücksprungadresse auf Stack sw $a0, 0($sp) # rette Eingabeparameter auf Stack slti $t0, $a0, 1 # teste n < 1

beq $t0, $zero, L1 # wenn n >= 1 dann gehe nach L1 addi $v0, $zero, 1 # es wird 1 zurückgegeben

addi $sp, $sp, 8 # pop Stack-Pointer um zwei Word jr $ra # Rücksprung zum Prozedur-Aufrufer L1: addi $a0, $a0, -1 # setze Argument auf n-1

jal fact # rufe fact rekursiv mit n-1 auf

lw $a0, 0($sp) # restauriere Eingabeparam vom Stack lw $ra, 4($sp) # restauriere Rücksprungadr vom Stack addi $sp, $sp, 8 # pop Stack-Pointer um zwei Word

(14)

Procedure‐Frame und Frame‐Pointer

Null bis vier Argument‐

Register ($a0‐$a3) Return‐Adresse $ra Null bis acht Saved‐

Register ($s0‐$s7) Möglicher zusätzlicher 

Speicher der während  der Ausführung der 

Prozedur  benötigt  wird und nach  Prozedurrückkehr nicht 

mehr

Hohe Adresse

Niedrige Adresse Stack‐Pointer $sp

Frame‐Pointer $fp

Unbenutzer Stack‐Speicher

Benutzer Stack‐Speicher

Procedure‐Frame

Argument 5 Argument 6

(15)

Speicherbelegungskonvention

Reserviert

Text (d.h. das Programm  in Form von Maschinen‐

instruktionen) Statische Daten (z.B. 

Konstanten oder  statische Variablen)

Stack

Der Heap speichert alle  dynamischen (d.h. 

während der Laufzeit  angelegten) Daten.

Heap

0x00400000 0x10000000 0x10008000 0x7ffffffc

0x00000000

$pc

$sp

$gp

(16)

Die Sprunginstruktionen zusammengefasst

Instruktion Beispiel Beduetung

j j Label $pc = Sprungadresse

jal jal Label $ra = $pc+4, $pc = Sprungadresse jr jr $s1 $pc = Registerinhalt

$pc ist der Program‐Counter

$ra ist das 32te CPU‐Register 

(17)

Schwieriges Quiz

Rmul: addi $sp, $sp, -4 # rette Rücksprungadresse sw $ra, 0($sp) #

add $t0, $a0, $zero # $t0 = n addi $a1, $a1, -1 # m = m - 1

beq $a1, $zero, End # wenn m=0, dann Ende jal Rmul # $v0 = Rmul(n,m-1) add $t0, $t0, $v0 # $t0 = $t0 + $v0 End: add $v0, $t0, $zero # $v0 = $t0

lw $ra, 0($sp) # springe zurück addi $sp, $sp, 4 #

Rekursive Berechnung von n*m in der Form Rmul(n,m) = n+Rmul(n,m‐1) Eingabeparameter: $a0 für n und $a1 für m>0

Rückgabeparameter: $v0 Temporäre Berechnung: $t0

$a0, $a1, $v0, $t0 brauchen  nach Registerkonvention alle  nicht über Aufrufgrenzen  bewahrt zu werden.

(18)

Registerkonvention, dass ein Register über Aufrufgrenzen nicht  bewahrt wird bedeutet:

• Register darf nach belieben überschreiben werden.

• Register muss vor dem Rücksprung nicht restauriert werden.

• Prozedur muss aber das Register für sich selbst sichern!

• Beispiel:

Verwendung von $t0 Sichern von $t0

Aufruf einer anderen Prozedur Restaurieren von $t0

•Ausnahme: wir wissen genau, dass das Register in keiner der aufgerufenen Prozeduren verwendet wird.

• Prozeduren, die keine anderen aufruft muss natürlich temporäre Register nie sichern.

Prozedur, die keine andere aufruft nennt man auch Leaf‐Procedure

Bemerkung zu vorigem Quiz

(19)

System‐Call – Mechanismus zum Aufrufen von Betriebssystem‐

funktionen.

Anwendung der Instruktion syscall am Beispiel:

addi $v0, $zero, 1 # Lade System‐Call‐Code in $v0

# hier System‐Call‐Code 1 für den

# Systemcall print_int addi $a0, $zero, 42 # Lade das Argument für den

# System‐Call nach $a0.

# Hier soll die Zahl 42

# ausgegeben werden.

syscall # Rufe den System‐Call auf

# dies führt zu einer Exception

# vom Typ 8 (System‐Call)

System‐Calls

(20)

In SPIM/MARS verfügbare System‐Calls

(21)

Pseudoinstruktionen, Direktiven und Makros

(22)

Motivation für Pseudoinstruktionen

Wir hatten häufiger schon

addi $s1,$zero,wert # $s1=wert

Eine Instruktion li (Load‐Immediate) wäre doch nachvollziebarer li $s1,wert # $s1=wert

MIPS als ISA aus dem RISC‐Lager versucht aber den Instruktion‐Set  möglichst klein zu halten. Damit ist so was wie ein li in der ISA  nicht eingebaut. Kann man ja mit einem addi und dem $zero

Register ausdrücken.

Dennoch gibt es in MIPS oben genannte Instruktion. Wo kommt die  her?

Das ist eine sogenannte Pseudoinstruktion, die der Assembler in  Instruktionen der MIPS ISA übersetzt.

(23)

Umsetzung von Pseudoinstruktionen

Wie würde folgende move Instruktion vom Assembler umgesetzt?

move $s1,$s2 # Pseudoinstruktion $s1=$s2

Wie würde folgende blt Instruktion vom Assembler umgesetzt?

blt $s1,$s2, Label # Springe nach Label,

# wenn $s1<$s2 gilt

Beachte: Registerkonvention. Pseudoinstruktionen die ein Register  zum Zwischenspeichern von Ergebnissen brauchen, benutzen dazu  das Register $at (Assembler‐Temporary)

(24)

Einige MIPS‐Assembler Pseudoinstruktioen

Instruktion Beispiel Erklärung des Beispiel

blt, bltu blt $s1, $s2, Label Springe nach Label, wenn 

$s1 < $s2 (signed)

bgt, bgtu bgt $s1, $s2, Label Springe nach Label, wenn 

$s1 > $s2 (signed)

ble, bleu ble $s1, $s2, Label Springe nach Label, wenn 

$s1 <= $s2 (signed)

bge, bgeu bge $s1, $s2, Label Springe nach Label, wenn 

$s1 >= $s2 (signed)

li li $s1, 42 Lade Immediate 42 in $s1 move move $s1, $s2 $s1 = $s2

MARS unterstützt beispielsweise neben den 155 Basisinstruktionen  weitere 388 zusätzliche Pseudoinstruktionen.

(25)

Direktiven

Direktiven vereinfachen das Datenlayout  eines Programms im Speicher.

Damit der Assembler ein Programm, wie  auf der rechten Seite gezeigt, erzeugt,  schreiben wir:

.text 0x00400010 li $v0, 1

li $a0, 5 syscall

.data 0x10001000 str:

.asciiz "Hallo Welt!“

0x00400010 : li $v0, 1 0x00400014 : li $a0, 5 0x00400014 : syscall ...

0x10001000 : ‘H’

0x10001001 : ‘a’

0x10001002 : ‘l’

0x10001003 : ‘l’

0x10001004 : ‘o’

...

(26)

Makros (nicht Besandteil von SPIM/MARS)

Makros definieren in einem Wort eine Folge von Instruktionen. 

Beim assemblieren wird jedes Auftreten des Makronamens im Code  mit den Instruktionen ausgetauscht.

Beispiel:

.macro print_int($arg) la $a0, int_str

mov $a1, $arg jal printf

.end_macro ...

.data

int_str: .asciiz „%d“

Code:

...

print_int($t0) ...

wird expandiert zu:

...

la $a0, int_str mov $a1, $t0

jal printf ...

Referenzen

ÄHNLICHE DOKUMENTE

Die Bestätigung durch die Enter-Taste kann man zwar wie den Start eines neuen Versuches an- sehen, aber sicherer ist es, bei einem neuen Versuch über Menu – Daten – Alte

Die Untersuchung von Lade- und Entladevorgängen am Kondensator ist Standard in der Oberstufe. Dazu wird der Kondensator über einen Widerstand auf- und wieder

(1) Stellen Sie eine begründete Vermutung zum zeitlichen Verlauf der Entladespannung über dem Kondensator auf und überprüfen Sie Ihre Vermutung

(1) Stellen Sie eine begründete Vermutung zum zeitlichen Verlauf der Entladespannung über dem Kondensator auf und überprüfen Sie Ihre Vermutung im

Tragen Sie für einen bestimmten Widerstand und verschiedene Kondensatoren (Kapazitäten) die Zeit ein, bis die Spannung auf einen von Ihnen festzulegenden Prozentsatz gesunken ist.

Vorschlag für ein Messprotokoll Zu (8): Tragen Sie für die verschiedenen Widerstände die halbe Entladedauer ein (Zeit, in der die Spannung auf den halben Wert gesunken ist). Zu

Für das Abladen von Gras im Tenn oder für die Beschickung von Fördergebläsen (Hochsilo, Heulager) kann der Wagen zusätzlich zu den Dosierwalzen mit einem Querförderband

Die Schweizer Obstbranche traf sich zu Beginn des neuen Jahres für zwei Tage in Wädenswil.. Unbestritten waren neue Beiträge zu wichtigen Themen wie Klimawandel,