Was bisher geschah…

11/7/2007
Rechnerarchitektur und
Assemblerprogrammierung
Vorlesung 4
Was bisher geschah…
y Prozeduren
y Unterstützung durch MIPS-Architektur
y Instruktion jal
y Spezialregister $ra, $sp, $fp
1
11/7/2007
Bisher bekannte Instruktionen
Arithmetik
Datentransfer
Logik
Sprünge
add
lw
and
beq
sub
sw
or
bne
addi
nor
j
lui
andi
jr
ori
slt
sll
slti
srl
jal
20 von 52 Instruktionen
MIPS-Register
Register
$zero
$v0-$v1
$a0-$a3
$t0-$t7
$s0-$s7
$t8-$t9
$sp
$fp
$ra
28 von 32 Registern
2
11/7/2007
Erinnerung Prozeduraufruf
Aufrufer …
Prozedur …
Aufrufer …
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
… schreibt evtl. zusätzliche Argumente auf den Stack
… sichert Argumentregister $a0, …, $a3 und $ra auf Stack
… legt Argumente in $a0, …, $a3 ab
… springt zu Prozedur, aktueller PC wird in $ra gesichert
… sichert $s0, …, $s7 auf Stack
… führt Berechnung durch
… schreibt Ergebnisse in $v0, $v1
… liest $s0, …, $s7 von Stack und schreibt zurück
… springt an Adresse in $ra
... liest $a0, $a3 und $ra vom Stack und schreibt zurück
… löscht evtl. zusätzliche Argumente vom Stack
… verarbeitet Ergebnisse $v0, $v1
Aufrufkonventionen
y Konvention bzgl. …
y Register-Semantik
y Reihenfolge
y
y
Argumente
gesicherte Register, etc.
y Rolle Aufrufer/Prozedur
y MIPS
y Argumente in Registern (von links nach rechts)
y mehr als vier
Stack (von links nach rechts)
y Reihenfolge
y (evtl.) Stack-Argumente
y Gerettete Argumentregister
y Gerettetes $ra
y Gerettete Variablenregister
y Lokale Daten
3
11/7/2007
Exkurs: x86
y x86–Architektur kennt verschiedene
Aufrufkonventionen
y Bereits darüber gestolpert?
__cdecl, __fastcall, __stdcall, thiscall
y Einfluss
y der Programmiersprache?
y des Programmiermodells?
__cdecl
y Standard bei C/C++
y Prozeduren mit variabel langer Argumentliste …
int method ( int a, ... );
y Alle Argumente auf Stack (von rechts nach links)
y Anzahl Argumente von Aufruf zu Aufruf unterschiedlich
Aufrufer räumt Stack auf
Instruktionen zum Aufräumen nach jedem Aufruf
größere Binaries
y Dank C/C++ sehr weit verbreitet
4
11/7/2007
__stdcall
y Standard bei WIN32 API, COM
y Argumente von rechts nach links auf Stack
y Prozedur räumt auf
y Instruktionen zum Aufräumen am Ende der Prozedur
y
nur einmal pro Prozedur
kleinere Binaries
__fastcall
y Standard bei Itanium und AMD64
y Erste zwei Argumente (von links, <32 Bit) in
Registern
y Weitere Argumente von rechts nach links auf Stack
y Geschwindigkeitsvorteil
y Prozedur räumt Stack auf
5
11/7/2007
Visual C/C++
y Visual C/C++
y __cdecl ist Standard
y Alternative Aufrufkonvention erzwingen durch…
int [__cdecl] methodA(int x, int y);
int __stdcall methodB(int x, int y);
int __fastcall methodC(int x, int y);
GCC
y Aufrufkonvention erzwingen durch…
int methodA(int x, int y) __attribute__((cdecl));
int methodB(int x, int y) __attribute__((stdcall));
int methodC(int x, int y) __attribute__((fastcall));
y Registernutzung durch Switches einstellbar …
-fcall-used-reg Treat the register named reg as an allocable register
that is clobbered by function calls. It may be allocated for temporaries
or variables that do not live across a call. Functions compiled this way
will not save and restore the register reg .
-fcall-saved-reg Treat the register named reg as an allocable register
saved by functions. It may be allocated even for temporaries or
variables that live across a call. Functions compiled this way will save
and restore the register reg if they use it.
6
11/7/2007
Interoperabilität
y Aufrufer und Prozedur bzgl. Konvention einigen!
y Innerhalb Compile-Einheit kein Problem
Compiler regelt alles… ☺
int methodA(int x, int y) __attribute__((cdecl));
int methodB(int x, int y) __attribute__((stdcall));
int methodA(int x, int y) {
methodB(x,y);
}
y Mischung aus Assembler und C/C++ …
y Aufrufkonvention aufzurufender Prozedur beachten
y Mismatch
Stack
Fazit
y __stdcall vs. __cdecl
y Stack aufräumen geht mit wenigen Instruktionen
Größenunterschied der Binaries marginal
y __stdcall vs. __fastcall
y Geschwindigkeitsvorteil nur vordergründig
y Registerinhalte auf Stack retten
Speicherzugriff
7
11/7/2007
Speicher…
y Lokale Variablen in Prozeduren bereits behandelt
y Stack
y Adressierung relativ zu $fp
y Instruktionen
y Wo im Speicher?
y Statische / Globale Variablen
y Größe steht bei Kompilierung fest
y Wo im Speicher?
y Dynamische Datenstrukturen?
y Allokation zur Laufzeit
y Variable Größe
y Wo im Speicher?
y Speicherorganisation?
Kapitel 3
Maschinensprache
Speicherorganisation
8
11/7/2007
Heap
y Speicherbereich für dynamische Datenstrukturen
y Größe kann zur Laufzeit wachsen
y Stack ebenfalls dynamisch
y Probleme?
y Ideen?
MIPS Speicherorganisation
y Nur eine Konvention
y Nirgendwo in MIPS-Architektur festgelegt
y Wir brauchen…
y Code
y
Textsegment
y statische Daten
y
Datensegment
y Stack
y
Stacksegment
y dynamische Datenstrukturen
y
Heap
OS
Stack
Heap
Stat. Daten
Text
Reserviert
9
11/7/2007
Genauere Betrachtung
0xffff ffff
0x7fff fffd
0x7fff fffc
OS
2 GB
Bereich 2-4 GB für OS
reserviert!!!
Stack
~ 1,8 GB
0x1001 0000
0x1000 0000
Heap
Statische Daten
64 KB
Text
252 MB
Reserviert
256 KB
0x0040 0000
0x0
Statische Variablen
y C
y Variablen außerhalb von Prozeduren
static
y + explizit als static markierte Variablen
y Alle anderen = automatic
y Zugriff?
y Zusätzliches Zeiger-Register $gp (Global Pointer)
y Mit 0x1000 8000 initialisiert ( spim)
Register
y Zugriff durch 16 Bit Offset
$zero
y
lw $t0, OFFSET($gp)
0x1000 ffff
0x1000 8000
0x1000 0000
Statische Daten
Adresse
Semantik
0
Konstante 0
$v0 - $v1
2-3
Rückgabewerte
$a0-$a3
4-7
Argumente
$t0-$t7
8-15
Temporäre Register
$s0-$s7
16-23
Gesicherte Register
$t8-$t9
24-25
Temporäre Register
$gp
28
Globaler Zeiger
$sp
29
Stackzeiger
$fp
30
Framezeiger
$ra
31
Rücksprungadresse
10
11/7/2007
Dynamische Datenstrukturen
y Auf dem Heap
y Allokieren/Freigeben von Speicher durch Entwickler
y Mit malloc/free in C
y Mit new/delete in C++
y Fehlerhafte Verwendung fatal
y
y
y
Fehlendes malloc/new?
Fehlendes free/delete?
Wie verhindern?
Stack
y Größe dynamisch
y Stack wächst von oben nach unten
y
$sp mit 0x7fff fffc initialisieren
y Heap wächst von unten nach oben
y Kollision/Überschneidung fatal
y Wie verhindern?
y Stackverwaltung …
y … in Assembler
y
Programmierer verantwortlich
y … in Hochsprachen
y durch Compiler
y Garantiert korrekt
11
11/7/2007
Exkurs: ? Buffer Overflows
$a0
$ra
y Beispiel…
y 5 Bytes auf Stack reservieren
y Problem?
&arr
0
0
0
0
0
void PROBLEM()
{
char arr[5];
strcpy(arr,GETDATA());
...
}
Canaries
y Früher: Kanarienvögel in Kohleminen
y anfälliger Stoffwechsel
y “Warnsystem” vor Kohlenmonoxid
y Idee?
y Zufälligen Wert vor $ra einfügen
y Vor Rücksprung Wert testen!
y Function Pointer?
&arr
$a0
CANARY
$ra
0
0
0
0
0
void NOT_SECURE()
{
char arr[42];
strcpy(arr,GETDATA());
...
}
12
11/7/2007
Zusammenfassung Speicher
y Verschieden Arten von Variablen
y statisch
zur Übersetzungszeit
y
y
y
Lebensdauer an Programm gebunden
Größe zur Laufzeit nicht veränderbar
Statischer Datenbereich
y automatisch
beim Betreten einer Funktion
y Lebensdauer an Funktion gebunden
y Größe zur Laufzeit nicht veränderbar
y Vorsicht vor Buffer Overflows!
y Stack
y dynamisch
beliebig
y beliebige Lebensdauer
y Größe variabel
y Heap
Objektorientierung
y Was ist ein Objekt?
y Zusammenhänge mit …
y … Speicherorganisation …
y … Aufrufsemantiken?
13
11/7/2007
Beispiel: OO in C++
class
Point
{
public:
int x, y;
static int m;
void move() {
this.x+=m;
this.y+=m;
}
}
Point::m = 1;
Point p1;
p1.x = 7; p1.y = 42;
Point p2;
p2.x = 2; p2.y = 0;
Point p3;
p3.x = 10; p3.y = 25;
Was steht wo im Speicher?
class
Point
{
public:
int x, y;
static int m;
void move() {
this.x+=m;
this.y+=m;
}
}
Point::m = 1;
Point p1;
p1.x = 7; p1.y = 42;
Point p2;
p2.x = 2; p2.y = 0;
Point p3;
p3.x = 10; p3.y = 25;
14
11/7/2007
Objekte auf dem Stack
class
Point
Stack
{
public:
int x, y;
static int m;
void move() {
this.x+=m;
this.y+=m;
}
}
Point::m = 1;
Point p1;
p1.x = 7; p1.y = 42;
Point p2;
p2.x = 2; p2.y = 0;
Point p3;
p3.x = 10; p3.y = 25;
p1
x=7
y=42
p2
x=2
y=0
p3
x=10
y=25
statische Daten
class Point
m=1
Textsegment
Point::move() {
this.x+=m;
this.y+=m;
}
Objekte auf dem Heap
class
Point
{
Stack
p1
p2
p3
public:
int x, y;
static int m;
void move() {
this.x+=m;
this.y+=m;
}
}
Point::m = 1;
Point p1 = new Point();
p1->x = 7; p1->y = 42;
Point p2 = new Point();
P2->x = 2; p2->y = 0;
Point p3 = new Point();
P3->x = 10; p3->y = 25;
p1
x=7
y=42
p2
x=2
y=0
p3
x=10
y=25
Heap
statische Daten
class Point
m=1
Textsegment
Point::move() {
this.x+=m;
this.y+=m;
}
15
11/7/2007
Instanzmethoden
y Methodencode nur einmal im Speicher
y Zugriff auf Instanzvariablen?
Stack
p1
p2
p3
y Ideen?
p1
x=7
y=42
p2
x=2
y=0
p3
x=10
y=25
Heap
statische Daten
class Point
m=1
Textsegment
Point::move() {
this.x+=m;
this.y+=m;
}
thiscall
y Aufrufkonvention für C++-Instanzmethoden
y this in Register übergeben
y Prozedur räumt Stack auf
y Variabel lange Argumentlisten?
__cdecl
this auf Stack übergeben
y Überladene Funktionen
y Ideen?
16
11/7/2007
NameMangling
y Codierung der Parameter in Symbolnamen
y Beispiel…
int methodA(int x, int y) {
return methodB(x,y);
}
float methodA(float x, float y) {
return x+y;
}
0000000000000130 T _Z7methodAff
0000000000000110 T _Z7methodAii
Das war’s für heute…
y Folien, Übungsaufgaben wie immer im Laufe des
Tages auf
http://syssoft.uni-trier.de/~scholtes
17
11/7/2007
Rechnerarchitektur und
Assemblerprogrammierung
Übung 3
Aufgabe 1
y Implementierung einer Fibonacci-Prozedur + Aufruf
18
11/7/2007
Lösung: Prozedur
FIB:
N1:
REC:
bne $a0, $zero, N1
addi $v0, $zero, 0
jr $ra
addi $t0, $zero, 1
bne $a0, $t0, REC
addi $v0, $t0, 0
jr $ra
add $sp, $sp, -4
sw $s0, 0($sp)
addi $sp, $sp, -8
sw $a0, 4($sp)
sw $ra, 0($sp)
addi $a0, $a0, -1
jal FIB
addi $s0, $v0, 0
# falls n==0 gib 0 zurück
#
#
#
#
#
#
addi $a0, $a0, -1
jal FIB
add $v0, $v0, $s0
# neues Argument ist n-2
# Rekursiver Aufruf mit n-1
# Addiere Fib(n-1) zu Fib(n-2) in s0
lw $ra, 0($sp)
lw $a0, 4($sp)
addi $sp, $sp, 8
# altes $ra wiederherstellen
# altes Argument n wiederherstellen
# Werte auf Stack löschen
lw $s0, 0($sp)
addi $sp, $sp, 4
jr $ra
# s0 wiederherstellen
# falls n==1 gib 1 zurück
# $s0 auf Stack sichern
2 Wörter auf Stack reservieren
zunächst Argument $a0=n sichern
dann $ra sichern
neues Argument ist n-1
Rekursiver Aufruf mit n-2
Speichere Fib(n-1) in s0
# Rücksprung
Lösung: Aufruf
main:
addi $v0, $zero, 5
syscall
# Wert n in v0 legen
addi $sp, $sp, -8
sw $a0, 4($sp)
sw $ra, 0($sp)
# Altes $ra und $a0 sichern!
addi $a0, $v0, 0
jal FIB
addi $a0, $v0, 0
addi $v0, $zero, 1
syscall
# Argument in Register $a0 legen
# Aufrufen
# Ausgeben
lw $ra, 0($sp)
lw $a0, 4($sp)
addi $sp, $sp, 8
jr $ra
# $ra und $a0 wiederherstellen!
# Stack aufräumen
19
11/7/2007
Aufgabe 2
y Übersetzung einer C-Prozedur mit Stack-Variablen
y Mit und ohne $fp
int proc ( int x , int y )
{
int a = x + y ;
int b = 16 * a ;
if (b<1024)
{
int c = proc ( a , b ) ;
return 2 * c ;
}
else
return 1;
}
Lösung ohne $fp
proc:
RET:
addi $sp, $sp, -8
# Zwei Stack-Variablen a, b reservieren
add $s0, $a0, $a1
sw $s0, 4($sp)
sll $s1, $s0, 4
sw $s1, 0($sp)
slti $t0, $s1, 1024
beq $t0, $zero, RET
addi $sp, $sp, -12
sw $a0, 8($sp)
sw $a1, 4($sp)
sw $ra, 0($sp)
lw $a0, 12($sp)
lw $a1, 8($sp)
jal proc
lw $a0, 8($sp)
lw $a1, 4($sp)
lw $ra, 0($sp)
addi $sp, $sp, 12
addi $sp, $sp, -4
addi $s2, $v0, 0
sw $s2, 0($sp)
sll $v0, $s2, 1
addi $sp, $sp, 12
j $ra
#
#
#
#
#
addi $v0, $zero, 1
addi $sp, $sp, 8
j $ra
a = x + y
Auf Stack schreiben :-)
b = 16 * a
Auf Stack schreiben ☺
Falls b nicht kleiner 1024 gehe zu RET
# $ra, $a0 und $a1 sichern
# a und b vom Stack lesen :-)
# Rekursiver Aufruf
# $a0, $a1, $ra wiederherstellen
#
#
#
#
#
Stack Variable c reservieren
c = proc(a,b)
Auf Stack schreiben
return 2*c
Alle drei Stack-Variablen löschen
# Zwei Stack-Variablen löschen
20
11/7/2007
Lösung mit $fp
proc:
RET:
addi $sp, $sp, -4
sw $fp, 0($sp)
addi $fp, $sp, 0
addi $sp, $sp, -8
add $s0, $a0, $a1
sw $s0, -4($fp)
sll $s1, $s0, 4
sw $s1, -8($fp)
slti $t0, $s1, 1024
beq $t0, $zero, RET
addi $sp, $sp, -12
sw $a0, 8($sp)
sw $a1, 4($sp)
sw $ra, 0($sp)
lw $a0, -4($fp)
lw $a1, -8($fp)
jal proc
lw $a0, 8($sp)
lw $a1, 4($sp)
lw $ra, 0($sp)
addi $sp, $sp, 12
addi $sp, $sp, -4
addi $s2, $v0, 0
sw $s2, -12($t0)
sll $v0, $s2, 1
addi $sp, $sp, 12
lw $fp, 0, ($sp)
addi $sp, $sp, 4
j $ra
addi $v0, $zero, 1
addi $sp, $sp, 8
lw $fp, 0, ($sp)
addi $sp, $sp, 4
j $ra
# Alten FP sichern
#
#
#
#
#
#
#
FP setzen
Zwei Stack-Variablen a, b reservieren
a = x + y
a auf Stack schreiben :-)
b = 16 * a
b auf Stack schreiben
Falls b nicht kleiner 1024 gehe zu RET
# $ra, $a0 und $a1 sichern
# a und b vom Stack lesen :-)
# Rekursiver AUfruf
# $a0, $a1, $ra wiederherstellen
#
#
#
#
#
#
Stack Variable c reservieren
c = proc(a,b)
c auf Stack schreiben
return 2*c
Alle drei Stack-Variablen löschen
FP wiederherstellen
# Zwei Stack-Variablen löschen
# FP wiederherstellen
Aufgabe 3
y Siehe heutige Vorlesung ☺
21
11/7/2007
Das war’s für heute…
y Übungsaufgaben auf
http://syssoft.uni-trier.de/~scholtes
22