Assembler - TAMS - Universität Hamburg

Werbung
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
64-040 Rechnerstrukturen
64-040 Modul InfB-RS: Rechnerstrukturen
https://tams.informatik.uni-hamburg.de/
lectures/2015ws/vorlesung/rs
– Kapitel 13 –
Norman Hendrich
Universität Hamburg
Fakultät für Mathematik, Informatik und Naturwissenschaften
Fachbereich Informatik
Technische Aspekte Multimodaler Systeme
Wintersemester 2015/2016
N. Hendrich
1
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13 Assembler-Programmierung
64-040 Rechnerstrukturen
Kapitel 13
Assembler-Programmierung
Motivation
Grundlagen der Assemblerebene
x86 Assemblerprogrammierung
Elementare Befehle und Adressierungsarten
Operationen
Kontrollfluss
Sprungbefehle und Schleifen
Mehrfachverzweigung (Switch)
Funktionsaufrufe und Stack
Speicherverwaltung
Elementare Datentypen
Arrays
Strukturen
N. Hendrich
969
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13 Assembler-Programmierung
64-040 Rechnerstrukturen
Kapitel 13 (cont.)
Objektorientierte Konzepte
Linker und Loader
Dynamische Speicherverwaltung
Puffer-Überläufe
Literatur
N. Hendrich
970
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Wiederholung: Kompilierungssystem
printf.o
hello.c
Source
program
(text)
Prehello.i
processor
(cpp)
Compiler hello.s
(cc1)
Modified
source
program
(text)
Assembler hello.o
(as)
Assembly
program
(text)
Linker
(ld)
Relocatable
object
programs
(binary)
hello
Executable
object
program
(binary)
[BO14]
I
verschiedene Repräsentationen des Programms
I
I
I
I
Ausführung der Maschinensprache
I
I
N. Hendrich
Hochsprache
Assembler
Maschinensprache
von-Neumann Zyklus: Befehl holen, decodieren, ausführen
reale oder virtuelle Maschine
971
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Wiederholung: Kompilierungssystem (cont.)
temp = v[k];
High Level Language
Program
v[k] = v[k+1];
v[k+1] = temp;
Compiler
Assembly Language
Program
Assembler
Machine Language
Program
0000
1010
1100
0101
1001
1111
0110
1000
lw $15,
lw $16,
sw $16,
sw $15,
0($2)
4($2)
0($2)
4($2)
1100
0101
1010
0000
1010
0000
0101
1100
0110
1000
1111
1001
1111
1001
1000
0110
0101
1100
0000
1010
1000
0110
1001
1111
Machine Interpretation
Control Signal
Specification
N. Hendrich
ALUOP[0:3] <= InstReg[9:11] & MASK
[PH14]
972
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Warum Assembler?
Programme werden nur noch selten in Assembler geschrieben
I Programmentwicklung in Hochsprachen weit produktiver
I Compiler/Tools oft besser als handcodierter Assembler
aber Grundwissen bleibt trotzdem unverzichtbar
I Verständnis des Ausführungsmodells auf der Maschinenebene
I Programmverhalten bei Fehlern / Debugging
I Programmleistung verstärken
I
I
I
Systemsoftware implementieren
I
I
I
N. Hendrich
Ursachen für Programm-Ineffizienz verstehen
effiziente „maschinengerechte“ Datenstrukturen / Algorithmen
Compilerbau: Maschinencode als Ziel
Betriebssysteme implementieren (Prozesszustände verwalten)
Gerätetreiber schreiben
973
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Assembler: Lernziele
I
Grundverständnis der Programmausführung
I
I
I
I
I
Umsetzung arithmetisch/logischer Operationen
Umsetzung der gängigen Kontrollstrukturen:
(mehrfach) Verzweigungen, (bedingte) Sprünge, Schleifen
Datenstrukturen
ein- und mehrdimensionale Arrays
Funktionsaufrufe
I
I
I
Funktionsparameter
lokale Variablen
rekursive Funktionen
Stack
by-value, by-reference
I
Grundlagen der Speicherverwaltung
I
Umsetzung objektorientierter Konzepte im Rechner
N. Hendrich
Heap
vtable
974
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Assembler: Speicherverwaltung
I
Speicher aufgeteilt in mehrere Regionen
I
I
I
I
I
I
I
Programmierfehler und Sicherheitslücken
I
I
I
I
I
N. Hendrich
Programmcode
Funktionsbibliotheken, Linker und Loader
Stack mit Funktionsaufrufen und lokalen Variablen
statisch allozierte Daten und globale Variablen
dynamisch allozierte Daten
Umsetzung objektorientierter Konzepte
aktuelle Rechner bieten keinen/kaum Speicherschutz
geschützte Systeme (“capabilities”) bisher am Markt gescheitert
fehlerhafte dynamische Speicherverwaltung
Pufferüberläufe, Stack-allocated Daten
Ausnutzen durch bösartigen Code
975
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Assembler in RS
I
Beschränkung auf wesentliche Konzepte
I
I
I
I
diverse nicht behandelte Themen
I
I
I
I
I
I
N. Hendrich
GNU Assembler für x86 (32-bit)
nur ein Datentyp: 32-bit Integer (long)
nur kleiner Subset des gesamten Befehlssatzes
Makros
Implementierung eines Assemblers (2-pass)
Tips für effizientes Programmieren
Befehle für die Systemprogrammierung (supervisor mode)
x86 Gleitkommabefehle
...
976
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.1 Assembler-Programmierung - Motivation
64-040 Rechnerstrukturen
Assembler-Programmierung
CPU
Memory
Addresses
Registers
E
I
P
Data
Condition
Codes
Object Code
Program Data
OS Data
Instructions
[BO14]
Stack
Assembler aus der Sicht des Programmierers
N. Hendrich
977
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Beobachtbare Zustände (Assemblersicht)
I
Programmzähler (Instruction Pointer)
I
I
I
I
I
EFLAGS Register
gespeicherte Statusinformationen über die letzte
arithmetische Operation
für bedingte Sprünge benötigt (Conditional Branch)
Speicher
I
I
I
N. Hendrich
häufig benutzte Programmdaten
eax. . . ebp Register
Zustandscodes
I
I
Adresse der nächsten Anweisung
Registerbank
x86 eip Register
byteweise adressierbares Array
Code, Nutzerdaten, (einige) OS Daten
beinhaltet Kellerspeicher zur Unterstützung von Abläufen
978
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Umwandlung von C in Objektcode
text
C program (p1.c p2.c)
Compiler (gcc -S)
text
Asm program (p1.s p2.s)
Assembler (gcc or as)
binary
Object program (p1.o p2.o)
Static libraries
(.a)
Linker (gcc or ld)
binary
Executable program (p)
[BO14]
N. Hendrich
979
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Kompilieren zu Assemblercode: Funktion sum()
code.c
code.s
int sum(int x, int y)
{
int t = x+y;
return t;
}
[BO14]
I
Befehl gcc -O -S code.c
I
Erzeugt code.s
N. Hendrich
_sum:
pushl %ebp
movl %esp,%ebp
movl 12(%ebp),%eax
addl 8(%ebp),%eax
movl %ebp,%esp
popl %ebp
ret
980
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Assembler: Charakteristika
I
I
hardwarenahe Programmierung: Zugriff auf kompletten
Befehlssatz und alle Register einer Maschine
je ein Befehl pro Zeile
I
I
I
I
I
I
symbolische Label für Sprungadressen
I
I
N. Hendrich
Mnemonics für die einzelnen Maschinenbefehle
Konstanten als Dezimalwerte oder Hex-Werte
eingängige Namen für alle Register
Addressen für alle verfügbaren Adressierungsarten
Konvention bei gcc/gas x86: Ziel einer Operation steht rechts
Verwendung in Sprungbefehlen
globale Label definieren Einsprungpunkte für den Linker/Loader
981
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Assembler: Datentypen
I
I
nur die von der Maschine unterstützten „primitiven“ Daten
keine Aggregattypen wie Arrays, Strukturen, oder Objekte
I
I
nur fortlaufend adressierbare Bytes im Speicher
Ganzzahl-Daten, z.B. 1, 2, 4, oder 8 Bytes
I
I
I
Datenwerte für Variablen
positiv oder vorzeichenbehaftet
Textzeichen (ASCII, Unicode)
I
Gleitkomma-Daten mit 4 oder 8 Bytes
I
Adressen bzw. „Pointer“
N. Hendrich
8. . . 64 bits
int/long/long long
signed/unsigned
char
float/double
untypisierte Adressenverweise
982
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Assembler: Befehle/Operationen
I
arithmetische/logische Funktionen auf Registern und Speicher
I
I
I
Datentransfer zwischen Speicher und Registern
I
I
I
I
I
I
N. Hendrich
Daten aus Speicher in Register laden
Registerdaten im Speicher ablegen
ggf. auch Zugriff auf Spezial-/OS-register
Kontrolltransfer
I
I
Addition/Subtraktion, Multiplikation, usw.
bitweise logische und Schiebe-Operationen
unbedingte / bedingte Sprünge
Unterprogrammaufrufe: Sprünge zu/von Prozeduren
Interrupts, Exceptions, System-Calls
Makros: Folge von Assemblerbefehlen
983
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Objektcode: Funktion sum()
I
I
I
I
N. Hendrich
13 bytes Programmcode
0x401040 <sum>:
0x55
x86-Instruktionen mit 1-, 2- oder 3 bytes 0x89
Erklärung s.u.
0xe5
0x8b
0x45
Startadresse: 0x401040
0x0c
vom Compiler/Assembler gewählt
0x03
0x45
0x08
0x89
0xec
0x5d
0xc3
984
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Assembler und Linker
Assembler
I
übersetzt .s zu .o
I
binäre Codierung jeder Anweisung
I
(fast) vollständiges Bild des ausführbaren Codes
I
Verknüpfungen zwischen Code in verschiedenen Dateien fehlen
Linker / Binder
I
I
löst Referenzen zwischen Dateien auf
kombiniert mit statischen Laufzeit-Bibliotheken
I
I
manche Bibliotheken sind dynamisch verknüpft
I
N. Hendrich
z.B. Code für malloc, printf
Verknüpfung wird zur Laufzeit erstellt
985
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Beispiel: Maschinenbefehl für Addition
I
C-Code
I
I
addiert zwei Ganzzahlen mit Vorzeichen
Assembler
I
Addiere zwei 4-byte Integer
I
I
I
Operanden
Similar to
expression
x += y
%eax
M[%ebp+8]
%eax
%eax
Objektcode (x86-Befehlssatz)
I
I
N. Hendrich
addl 8(%ebp),%eax
long Wörter (für gcc)
keine signed/unsigned Unterscheidung
x: Register
y: Speicher
t: Register
Ergebnis in
I
int t = x+y;
3-Byte Befehl
Speicheradresse 0x401046
0x401046:
03 45 08
986
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Objektcode Disassembler: objdump
00401040 <_sum>:
0:
55
1:
89 e5
3:
8b 45 0c
6:
03 45 08
9:
89 ec
b:
5d
c:
c3
d:
8d 76 00
I
objdump -d . . .
I
I
I
N. Hendrich
push
mov
mov
add
mov
pop
ret
lea
%ebp
%esp,%ebp
0xc(%ebp),%eax
0x8(%ebp),%eax
%ebp,%esp
%ebp
0x0(%esi),%esi
[BO14]
Werkzeug zur Untersuchung des Objektcodes
rekonstruiert aus Binärcode den Assemblercode
kann auf vollständigem, ausführbaren Programm (a.out)
oder einer .o Datei ausgeführt werden
987
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Alternativer Disassembler: gdb
Disassembled
Object
0x401040:
0x55
0x89
0xe5
0x8b
0x45
0x0c
0x03
0x45
0x08
0x89
0xec
0x5d
0xc3
0x401040
0x401041
0x401043
0x401046
0x401049
0x40104b
0x40104c
0x40104d
<sum>:
<sum+1>:
<sum+3>:
<sum+6>:
<sum+9>:
<sum+11>:
<sum+12>:
<sum+13>:
push
mov
mov
add
mov
pop
ret
lea
%ebp
%esp,%ebp
0xc(%ebp),%eax
0x8(%ebp),%eax
%ebp,%esp
%ebp
[BO14]
0x0(%esi),%esi
gdb Debugger
gdb p
disassemble sum
Disassemble procedure
x/13b sum
N. Hendrich
Examine the 13 bytes starting at sum
988
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.2 Assembler-Programmierung - Grundlagen der Assemblerebene
64-040 Rechnerstrukturen
Was kann „disassembliert“ werden?
% objdump -d WINWORD.EXE
WINWORD.EXE:
file format pei-i386
No symbols in "WINWORD.EXE".
Disassembly of section .text:
30001000 <.text>:
30001000: 55
30001001: 8b ec
30001003: 6a ff
30001005: 68 90 10 00 30
3000100a: 68 91 dc 4c 30
I
I
N. Hendrich
push
mov
push
push
push
%ebp
%esp,%ebp
$0xffffffff
$0x30001090
$0x304cdc91
alles, was als ausführbarer Code interpretiert werden kann
Disassembler untersucht Bytes und rekonstruiert
Assemblerquelle (soweit wie möglich)
[BO14]
989
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3 Assembler-Programmierung - x86 Assemblerprogrammierung
64-040 Rechnerstrukturen
x86 Assemblerprogrammierung
I
I
I
I
Adressierungsarten
arithmetische Operationen
Statusregister
Umsetzung von Programmstrukturen
Einschränkungen
I Beispiele nutzen nur die 32-bit (long) Datentypen
I
I
I
x86 wird wie 8-Register 32-bit Maschine benutzt (=RISC)
CISC Komplexität und Tricks bewusst vermieden
Beispiele nutzen gcc/gas Syntax (vs. Microsoft/Intel)
Grafiken und Beispiele dieses Abschnitts sind aus R.E. Bryant, D.R.
O’Hallaron: Computer systems – A programmers perspective [BO14],
bzw. dem zugehörigen Foliensatz
N. Hendrich
990
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
Datentransfer „move“
I
Format: movl hsrci , hdsti
transferiert ein 4-Byte „long“ Wort
sehr häufige Instruktion
I
Typ der Operanden
I
I
I
Immediate: Konstante, ganzzahlig
I
I
I
I
Register: 8 Ganzzahl-Register
I
%esp und %ebp für spezielle
Aufgaben reserviert
z.T. Spezialregister für andere Anweisungen
I
zahlreiche Adressmodi
I
I
N. Hendrich
wie C-Konstante, aber mit dem Präfix $
z.B.: $0x400, $-533
codiert mit 1, 2 oder 4 Bytes
%eax
%edx
%ecx
%ebx
%esi
%edi
%esp
%ebp
Speicher: 4 konsekutive Speicherbytes
991
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
movl Operanden-Kombinationen
Source
movl
C Analogon
movl $0x4,%eax
temp = 0x4;
movl $-147,(%eax)
*p = -147;
Imm
Reg
Mem
Reg
Reg
Mem
movl %eax,%edx
temp2 = temp1;
movl %eax,(%edx)
*p = temp;
Reg
movl (%eax),%edx
temp = *p;
Mem
N. Hendrich
Destination
992
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
movl: Operanden/Adressierungsarten
I
Immediate:
I
I
I
I
(R) → Mem[Reg[R]]
Register R spezifiziert die Speicheradresse
Beispiel: movl (%ecx), %eax
Displacement: D(R) → Mem[Reg[R]+D]
I
I
I
N. Hendrich
%R → Reg[R]
Inhalt eines der 8 Universalregister eax. . . ebp
Normal:
I
I
positiver (oder negativer) Integerwert
Register:
I
$x → x
Register R
Konstantes „Displacement“ D spezifiziert den „offset“
Beispiel: movl 8(%ebp), %edx
993
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
Beispiel: Funktion swap()
void swap(int *xp, int *yp)
{
int t0 = *xp;
int t1 = *yp;
*xp = t1;
*yp = t0;
}
Nutzung der Register: ecx:
edx:
eax:
ebx:
N. Hendrich
yp
xp
t1
t0
swap:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl
movl
movl
movl
movl
movl
12(%ebp),%ecx
8(%ebp),%edx
(%ecx),%eax
(%edx),%ebx
%eax,(%edx)
%ebx,(%ecx)
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
Set
Up
Body
Finish
994
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
Indizierte Adressierung
I
allgemeine Form
I
Imm(Rb,Ri,S) → Mem[Reg[Rb]+S*Reg[Ri]+Imm]
I
I
I
I
I
gebräuchlichste Fälle
I
I
I
I
I
N. Hendrich
hImmi Offset
hRbi Basisregister: eins der 8 Integer-Registern
hRii
Indexregister: jedes außer %esp
%ebp grundsätzlich möglich, jedoch unwahrscheinlich
hSi
Skalierungsfaktor 1, 2, 4 oder 8
(Rb)
Imm(Rb)
(Rb,Ri)
Imm(Rb,Ri)
(Rb,Ri,S)
→
→
→
→
→
Mem[Reg[Rb]]
Mem[Reg[Rb] +
Mem[Reg[Rb] +
Mem[Reg[Rb] +
Mem[Reg[Rb] +
Imm]
Reg[Ri]]
Reg[Ri] + Imm]
S*Reg[Ri]]
995
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.1 Assembler-Programmierung - x86 Assemblerprogrammierung - Elementare Befehle und Adressierungsarten
64-040 Rechnerstrukturen
Beispiel: Adressberechnung
%edx 0xf000
%ecx
N. Hendrich
0x100
Expression
Computation
Address
0x8(%edx)
0xf000 + 0x8
0xf008
(%edx,%ecx)
0xf000 + 0x100
0xf100
(%edx,%ecx,4)
0xf000 + 4*0x100
0xf400
0x80(,%edx,2)
2*0xf000 + 0x80
0x1e080
996
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.2 Assembler-Programmierung - x86 Assemblerprogrammierung - Operationen
64-040 Rechnerstrukturen
Arithmetische Operationen
I
binäre Operatoren
Format
Computation
addl Src,Dest
Dest = Dest + Src
subl Src,Dest
Dest = Dest - Src
imull Src,Dest
Dest = Dest * Src
sall Src,Dest
Dest = Dest << Src
also called shll
sarl Src,Dest
Dest = Dest >> Src
Arithmetic
shrl Src,Dest
Dest = Dest >> Src
Logical
xorl Src,Dest
Dest = Dest ^ Src
andl Src,Dest
Dest = Dest & Src
Src,Dest
Dest = Dest | Src
orl
N. Hendrich
997
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.2 Assembler-Programmierung - x86 Assemblerprogrammierung - Operationen
64-040 Rechnerstrukturen
Arithmetische Operationen (cont.)
I
I
unäre Operatoren
Format
Computation
incl Dest
Dest = Dest + 1
decl Dest
Dest = Dest - 1
negl Dest
Dest = - Dest
notl Dest
Dest = ~ Dest
leal-Befehl: load effective address
I
I
I
N. Hendrich
Adressberechnung für (späteren) Ladebefehl
Speichert die Adresse in Register:
Imm(Rb,Ri,S) → Reg[Rb]+S*Reg[Ri]+Imm
wird oft von Compilern für arithmetische Berechnung genutzt
s. Beispiele
998
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.2 Assembler-Programmierung - x86 Assemblerprogrammierung - Operationen
64-040 Rechnerstrukturen
Beispiel: arithmetische Operationen
int arith
(int x, int y, int z)
{
int t1 = x+y;
int t2 = z+t1;
int t3 = x+4;
int t4 = y * 48;
int t5 = t3 + t4;
int rval = t2 * t5;
return rval;
}
arith:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl 12(%ebp),%edx
leal (%edx,%eax),%ecx
leal (%edx,%edx,2),%edx
sall $4,%edx
addl 16(%ebp),%ecx
leal 4(%edx,%eax),%eax
imull %ecx,%eax
movl %ebp,%esp
popl %ebp
ret
N. Hendrich
Set
Up
Body
Finish
999
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.2 Assembler-Programmierung - x86 Assemblerprogrammierung - Operationen
64-040 Rechnerstrukturen
Beispiel: arithmetische Operationen (cont.)
int arith
(int x, int y, int z)
{
int t1 = x+y;
int t2 = z+t1;
int t3 = x+4;
int t4 = y * 48;
int t5 = t3 + t4;
int rval = t2 * t5;
return rval;
}
movl 8(%ebp),%eax
movl 12(%ebp),%edx
leal (%edx,%eax),%ecx
leal (%edx,%edx,2),%edx
sall $4,%edx
addl 16(%ebp),%ecx
leal 4(%edx,%eax),%eax
imull %ecx,%eax
N. Hendrich
#
#
#
#
#
#
#
#
Offset
•
•
•
16
z
12
y
8
x
4
Rtn adr
0 Old %ebp
eax
edx
ecx
edx
edx
ecx
eax
eax
=
=
=
=
=
=
=
=
Stack
%ebp
x
y
x+y (t1)
3*y
48*y (t4)
z+t1 (t2)
4+t4+x (t5)
t5*t2 (rval)
1000
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.2 Assembler-Programmierung - x86 Assemblerprogrammierung - Operationen
64-040 Rechnerstrukturen
Beispiel: logische Operationen
int logical(int x, int y)
{
int t1 = x^y;
int t2 = t1 >> 17;
int mask = (1<<13) - 7;
int rval = t2 & mask;
return rval;
}
logical:
pushl %ebp
movl %esp,%ebp
movl
xorl
sarl
andl
movl %ebp,%esp
popl %ebp
ret
213 = 8192, 213 – 7 = 8185
movl
xorl
sarl
andl
N. Hendrich
8(%ebp),%eax
12(%ebp),%eax
$17,%eax
$8185,%eax
8(%ebp),%eax
12(%ebp),%eax
$17,%eax
$8185,%eax
eax
eax
eax
eax
=
=
=
=
Set
Up
Body
Finish
x
x^y
(t1)
t1>>17 (t2)
t2 & 8185
1001
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Kontrollfluss / Programmstrukturen
I
Zustandscodes
I
I
I
Ablaufsteuerung
I
I
I
N. Hendrich
Setzen
Testen
Verzweigungen: „If-then-else“
Schleifen: „Loop“-Varianten
Mehrfachverzweigungen: „Switch“
1002
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
x86: EFLAGS Register
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
[IA64]
X
X
X
X
X
X
X
X
S
C
X
X
S
S
S
S
S
N. Hendrich
V V
I I I A V R 0 N
0 0 0 0 0 0 0 0 0 0
T
C M F
D
P F
I
O
P
L
O D I T S Z
P
C
A
F F F F F F 0 F 0 F 1 F
ID Flag (ID)
Virtual Interrupt Pending (VIP)
Virtual Interrupt Flag (VIF)
Alignment Check (AC)
Virtual-8086 Mode (VM)
Resume Flag (RF)
Nested Task (NT)
I/O Privilege Level (IOPL)
Overflow Flag (OF)
Direction Flag (DF)
Interrupt Enable Flag (IF)
Trap Flag (TF)
Sign Flag (SF)
Zero Flag (ZF)
Auxiliary Carry Flag (AF)
Parity Flag (PF)
Carry Flag (CF)
1003
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Zustandscodes
I
vier relevante „Flags“ im Statusregister EFLAGS
I
I
I
I
CF
SF
ZF
OF
Carry Flag
Sign Flag
Zero Flag
Overflow Flag
1. implizite Aktualisierung durch arithmetische Operationen
I
I
I
I
I
N. Hendrich
Beispiel: addl hsrci , hdsti
in C: t=a+b
CF höchstwertiges Bit generiert Übertrag: Unsigned-Überlauf
ZF wenn t = 0
SF wenn t < 0
OF wenn das Zweierkomplement überläuft
(a > 0 && b > 0 && t < 0) || (a < 0 && b < 0 && t ≥ 0)
1004
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Zustandscodes (cont.)
2. explizites Setzen durch Vergleichsoperation
I
I
I
I
I
N. Hendrich
Beispiel: cmpl hsrc2i , hsrc1i
wie Berechnung von hsrc1i - hsrc2i
(subl hsrc2i , hsrc1i )
jedoch ohne Abspeichern des Resultats
CF höchstwertiges Bit generiert Übertrag
ZF setzen wenn sr c1 = sr c2
SF setzen wenn (sr c1 − sr c2) < 0
OF setzen wenn das Zweierkomplement überläuft
(a > 0 && b < 0 && (a − b) < 0) ||
(a < 0 && b > 0 && (a − b) ≥ 0)
1005
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Zustandscodes (cont.)
3. explizites Setzen durch Testanweisung
Beispiel: testl hsrc2i , hsrc1i
wie Berechnung von hsrc1i & hsrc2i
(andl hsrc2i , hsrc1i )
jedoch ohne Abspeichern des Resultats
⇒ hilfreich, wenn einer der Operanden eine Bitmaske ist
I
I
I
N. Hendrich
ZF setzen wenn sr c1&sr c2 = 0
SF setzen wenn sr c1&sr c2 < 0
1006
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Zustandscodes lesen: set..-Befehle
I
N. Hendrich
Befehle setzen ein einzelnes Byte (LSB) in Universalregister
SetX
Condition
Description
sete
ZF
Equal / Zero
setne
~ZF
Not Equal / Not Zero
sets
SF
Negative
setns
~SF
Nonnegative
setg
~(SF^OF)&~ZF
Greater (Signed)
setge
~(SF^OF)
Greater or Equal (Signed)
setl
(SF^OF)
Less (Signed)
setle
(SF^OF)|ZF
Less or Equal (Signed)
seta
~CF&~ZF
Above (unsigned)
setb
CF
Below (unsigned)
1007
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.3 Assembler-Programmierung - x86 Assemblerprogrammierung - Kontrollfluss
64-040 Rechnerstrukturen
Beispiel: Zustandscodes lesen
I
I
ein-Byte Zieloperand (Register, Speicher)
meist kombiniert mit movzbl
move with zero-extend byte to long
also Löschen der Bits 31. . . 8
%eax
%ah
%al
%edx
%dh
%dl
%ecx
%ch
%cl
%ebx
%bh
%bl
%esi
int gt (int x, int y)
{
return x > y;
}
%edi
%esp
%ebp
movl 12(%ebp),%eax
cmpl %eax,8(%ebp)
setg %al
movzbl %al,%eax
N. Hendrich
#
#
#
#
eax = y
Compare x : y
al = x > y
Zero rest of %eax
1008
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Sprünge („Jump“): j..-Befehle
I
N. Hendrich
unbedingter- / bedingter Sprung (abhängig von Zustandscode)
jX
Condition
Description
jmp
1
Unconditional
je
ZF
Equal / Zero
jne
~ZF
Not Equal / Not Zero
js
SF
Negative
jns
~SF
Nonnegative
jg
~(SF^OF)&~ZF
Greater (Signed)
jge
~(SF^OF)
Greater or Equal (Signed)
jl
(SF^OF)
Less (Signed)
jle
(SF^OF)|ZF
Less or Equal (Signed)
ja
~CF&~ZF
Above (unsigned)
jb
CF
Below (unsigned)
1009
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Assembler: Label
I
Assemblercode enthält je einen Maschinenbefehl pro Zeile
I
normale Programmausführung ist sequentiell
I
Befehle beginnen an eindeutig bestimmten Speicheradressen
I
Label: symbolische Namen für bestimmte Adressen
I
I
I
I
_max: global, Beginn der Funktion max()
L9: lokal, nur vom Assembler verwendete interne Adresse
I
Label müssen in einem Programm eindeutig sein
I
N. Hendrich
am Beginn einer Zeile, oder vor einem Befehl
vom Programmierer / Compiler vergeben
als symbolische Adressen für Sprünge verwendet
1010
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Beispiel: bedingter Sprung („Conditional Branch“)
_max:
pushl %ebp
movl %esp,%ebp
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
movl 8(%ebp),%edx
movl 12(%ebp),%eax
cmpl %eax,%edx
jle L9
movl %edx,%eax
Body
L9:
movl %ebp,%esp
popl %ebp
ret
N. Hendrich
Set
Up
Finish
1011
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Beispiel: bedingter Sprung („Conditional Branch“) (cont.)
int goto_max(int x, int y)
{
int rval = y;
int ok = (x <= y);
if (ok)
goto done;
rval = x;
done:
return rval;
}
movl 8(%ebp),%edx
movl 12(%ebp),%eax
cmpl %eax,%edx
jle L9
movl %edx,%eax
L9:
N. Hendrich
#
#
#
#
#
#
I
I
I
edx =
eax =
x : y
if <=
eax =
Done:
C-Code mit goto
entspricht mehr dem
Assemblerprogramm
schlechter Programmierstil (!)
x
y
goto L9
x
Skipped when x ≤ y
1012
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Beispiel: „Do-While“ Schleife
I
C Code
int fact_do
(int x)
{
int result = 1;
do {
result *= x;
x = x-1;
} while (x > 1);
return result;
}
goto Version
int fact_goto(int x)
{
int result = 1;
loop:
result *= x;
x = x-1;
if (x > 1)
goto loop;
return result;
}
I
Rückwärtssprung setzt Schleife fort
I
wird nur ausgeführt, wenn „while“ Bedingung gilt
N. Hendrich
1013
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
Beispiel: „Do-While“ Schleife (cont.)
int fact_goto
(int x)
{
int result = 1;
loop:
result *= x;
x = x-1;
if (x > 1)
goto loop;
return result;
}
Register
N. Hendrich
%edx
x
%eax
result
_fact_goto:
pushl %ebp
movl %esp,%ebp
movl $1,%eax
movl 8(%ebp),%edx
#
#
#
#
Setup
Setup
eax = 1
edx = x
L11:
imull %edx,%eax
decl %edx
cmpl $1,%edx
jg L11
#
#
#
#
result *= x
x-Compare x : 1
if > goto loop
movl %ebp,%esp
popl %ebp
ret
# Finish
# Finish
# Finish
1014
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
„Do-While“ Übersetzung
C Code
do
Body
while (Test);
I
I
beliebige Folge von C Anweisungen als Schleifenkörper
Abbruchbedingung ist zurückgelieferter Integer Wert
I
I
N. Hendrich
Goto Version
loop:
Body
if (Test)
goto loop
= 0 entspricht Falsch: Schleife verlassen
6= 0
–"–
Wahr: nächste Iteration
1015
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
„While“ Übersetzung
C Code
while (Test)
Body
Do-While Version
Goto Version
if (!Test)
goto done;
do
Body
while(Test);
done:
if (!Test)
goto done;
loop:
Body
if (Test)
goto loop;
done:
N. Hendrich
1016
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.4 Assembler-Programmierung - x86 Assemblerprogrammierung - Sprungbefehle und Schleifen
64-040 Rechnerstrukturen
„For“ Übersetzung
For Version
for (Init; Test; Update )
Body
Do-While Version
Init;
if (!Test)
goto done;
do {
Body
Update ;
} while (Test)
done:
N. Hendrich
While Version
Init;
while (Test ) {
Body
Update ;
}
Goto Version
Init;
if (!Test)
goto done;
loop:
Body
Update ;
if (Test)
goto loop;
done:
1017
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Mehrfachverzweigungen „Switch“
I
Implementierungsoptionen
1. Folge von „If-Then-Else“
+ gut bei wenigen Alternativen
− langsam bei vielen Fällen
2. Sprungtabelle „Jump Table“
I
I
I
Vermeidet einzelne Abfragen
möglich falls Alternativen kleine
ganzzahlige Konstanten sind
Compiler (gcc) wählt eine der
beiden Varianten entsprechend
der Fallstruktur
Anmerkung: im Beispielcode fehlt „Default“
N. Hendrich
typedef enum
{ADD, MULT, MINUS, DIV, MOD, BAD}
op_type;
char unparse_symbol(op_type op)
{
switch (op) {
case ADD :
return '+';
case MULT:
return '*';
case MINUS:
return '-';
case DIV:
return '/';
case MOD:
return '%';
case BAD:
return '?';
}
}
1018
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Sprungtabelle
Switch Form
switch(op) {
case val_0:
Block 0
case val_1:
Block 1
• • •
case val_n-1:
Block n–1
}
Jump Table
jtab:
Targ0
Jump Targets
Targ0:
Code Block
0
Targ1:
Code Block
1
Targ2:
Code Block
2
Targ1
Targ2
•
•
•
Targn-1
•
•
•
Approx. Translation
target = JTab[op];
goto *target;
Targn-1:
I
N. Hendrich
Code Block
n–1
Vorteil: k-fach Verzweigung in O(1) Operationen
1019
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Beispiel: „Switch“
Branching Possibilities
Enumerated Values
typedef enum
{ADD, MULT, MINUS, DIV, MOD, BAD}
op_type;
ADD
MULT
MINUS
DIV
MOD
BAD
char unparse_symbol(op_type op)
{
switch (op) {
• • •
}
}
Setup:
N. Hendrich
unparse_symbol:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
cmpl $5,%eax
ja .L49
jmp *.L57(,%eax,4)
#
#
#
#
#
#
0
1
2
3
4
5
Setup
Setup
eax = op
Compare op : 5
If > goto done
goto Table[op]
1020
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Beispiel: „Switch“ (cont.)
I
Compiler erzeugt Code für jeden case Zweig
I
I
I
I
I
je ein Label am Start der Zweige, .L51. . . .L56
Tabellenstruktur
jedes Ziel benötigt 4 Bytes
Basisadresse bei .L57
Sprünge
I
jmp *.L57(,%eax, 4)
I
I
I
I
I
N. Hendrich
Sprungtabelle ist mit Label .L57 gekennzeichnet
Register %eax speichert op
Skalierungsfaktor 4 für Tabellenoffset
Sprungziel: effektive Adresse .L57 + op×4
jmp .L49 markiert das Ende der Switch-Anweisung
1021
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Beispiel: „Switch“ (cont.)
Table Contents
Targets & Completion
.section .rodata
.align 4
.L57:
.long .L51 #Op =
.long .L52 #Op =
.long .L53 #Op =
.long .L54 #Op =
.long .L55 #Op =
.long .L56 #Op =
.L51:
movl $43,%eax # ’+’
jmp .L49
.L52:
movl $42,%eax # ’*’
jmp .L49
.L53:
movl $45,%eax # ’-’
jmp .L49
.L54:
movl $47,%eax # ’/’
jmp .L49
.L55:
movl $37,%eax # ’%’
jmp .L49
.L56:
movl $63,%eax # ’?’
# Fall Through to .L49
0
1
2
3
4
5
Enumerated Values
ADD
MULT
MINUS
DIV
MOD
BAD
N. Hendrich
0
1
2
3
4
5
1022
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Sprungtabelle aus Binärcode Extrahieren
Contents of section .rodata:
8048bc0 30870408 37870408 40870408 47870408
8048bd0 50870408 57870408 46616374 28256429
8048be0 203d2025 6c640a00 43686172 203d2025
…
I
im read-only Datensegment gespeichert (.rodata)
I
I
dort liegen konstante Werte des Codes
kann mit obdjump untersucht werden
obdjump code-examples -s --section=.rodata
I
I
I
N. Hendrich
[email protected]...
P...W...Fact(%d)
= %ld..Char = %
zeigt alles im angegebenen Segment
schwer zu lesen (!)
Einträge der Sprungtabelle in umgekehrter Byte-Anordnung
z.B: 30870408 ist eigentlich 0x08048730
1023
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.5 Assembler-Programmierung - x86 Assemblerprogrammierung - Mehrfachverzweigung (Switch)
64-040 Rechnerstrukturen
Zusammenfassung – Assembler
I
I
Primitive Operationen und Adressierung
C Kontrollstrukturen
I
I
I
I
Assembler Kontrollstrukturen
I
I
I
„Jump“
„Conditional Jump“
Compiler
I
I
I
N. Hendrich
„if-then-else“
„do-while“, „while“, „for“
„switch“
erzeugt Assembler Code für komplexere C Kontrollstrukturen
alle Schleifen in „do-while“ / „goto“ Form konvertieren
Sprungtabellen für Mehrfachverzweigungen „case“
1024
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack (Kellerspeicher)
Stack “Bottom”
I
Speicherregion
I
Startadresse vom OS vorgegeben
I
Zugriff mit Stackoperationen
I
I
Increasing
Addresses
wächst in Richtung niedrigerer
Adressen
Register %esp („Stack-Pointer“)
I
I
aktuelle Stack-Adresse
oberstes Element
Stack
Pointer
%esp
Stack Grows
Down
Stack “Top”
N. Hendrich
1025
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack (Kellerspeicher) (cont.)
I
Implementierung von Funktionen/Prozeduren
I
I
I
I
I
mehrere Varianten/Konventionen
I
I
I
I
I
N. Hendrich
Speicherplatz für Aufruf-Parameter
Speicherplatz für lokale Variablen
Rückgabe der Funktionswerte
auch für rekursive Funktionen (!)
Parameterübergabe in Registern
„Caller -Save“
„Callee-Save“
Kombinationen davon
Aufruf einer Funktion muss deren Konvention berücksichtigen
1026
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack: Push
Stack “Bottom”
pushl hsrci
I
holt Operanden aus hsrci
I
dekrementiert %esp um 4
I
Increasing
Addresses
speichert den Operanden unter der
von %esp vorgegebenen Adresse
Stack
Pointer
%esp
Stack Grows
Down
-4
Stack “Top”
N. Hendrich
1027
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack: Pop
Stack “Bottom”
popl hdsti
I
liest den Operanden unter der
von %esp vorgegebenen Adresse
Increasing
Addresses
I
inkrementiert %esp um 4
I
schreibt gelesenen Wert in hdsti
Stack
Pointer
%esp
Stack Grows
Down
+4
Stack “Top”
N. Hendrich
1028
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiele: Stack-Operationen
pushl %eax
0x110
0x110
0x10c
0x108
0x110
0x10c
123
popl %edx
0x10c
0x108
123
0x108
123
0x104
213
0x104
213
213
%eax
213
%eax
213
%eax
%edx
555
%edx
555
%edx
555
213
%esp
0x108
%esp
0x108
0x104
%esp
0x104
0x108
N. Hendrich
1029
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Funktions-/Prozeduraufruf
I
x86 ist CISC: spezielle Maschinenbefehle für Funktionsaufruf
I
I
I
I
I
zwei Register mit Spezialaufgaben
I
I
N. Hendrich
call zum Aufruf einer Funktion
ret zum Rücksprung aus der Funktion
beide Funktionen ähnlich jmp: eip wird modifiziert
Stack wird zur Parameterübergabe verwendet
%esp „stack-pointer“: Speicheradresse des top-of-stack
%ebp „base-pointer“: Speicheradresse der aktuellen Funktion
1030
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Funktions-/Prozeduraufruf (cont.)
I
Prozeduraufruf: call hlabeli
I
I
I
Rücksprungadresse auf Stack („Push“)
Sprung zu hlabeli
Wert der Rücksprungadresse
I
I
Adresse der auf den call folgenden Anweisung
Beispiel: 804854e: e8 3d 06 00 00 ;call 8048b90
8048553:
hmaini
8048b90:
hproci
...
I
I
...
ret
Rücksprungadresse 0x8048553
;pushl %eax
;...
;Prozedureinsprung
;...
;Rücksprung
Rücksprung ret
I
I
N. Hendrich
50
...
Rücksprungadresse vom Stack („Pop“)
Sprung zu dieser Adresse
1031
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Prozeduraufruf
I
Prozeduraufruf call
804854e:
8048553:
e8 3d 06 00 00
50
call
0x110
8048b90 <main>
%eax
8048b90
0x110
0x10c
0x108
call
pushl
0x10c
123
0x108
123
0x104 0x8048553
%esp
0x108
%esp
%eip 0x804854e
0x108
0x104
%eip 0x8048b90
0x804854e
%eip is program counter
N. Hendrich
1032
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Prozeduraufruf (cont.)
I
Prozedurrücksprung ret
8048591:
c3
ret
ret
0x110
0x110
0x10c
0x108
0x10c
123
0x108
0x104 0x8048553
%esp
0x104
%eip 0x8048591
123
0x8048553
%esp
0x104
0x108
%eip 0x8048553
0x8048591
%eip is program counter
N. Hendrich
1033
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack-basierende Programmierung
I
für alle Programmiersprachen, die Rekursion unterstützen
I
C, Pascal, Java, Lisp, usw.
I
I
I
benötigt Platz, um den Zustand jeder Instanziierung zu speichern
I
I
I
I
I
I
dynamischer Zustandsspeicher für Aufrufe
zeitlich limitiert: vom Aufruf (call) bis zum Rücksprung (ret)
aufgerufenes Unterprogramm („Callee“) wird vor dem
aufrufendem Programm („Caller“) beendet
Stack-„Frame“
I
N. Hendrich
Argumente
lokale Variable(n)
Rücksprungadresse
Stack-„Prinzip“
I
I
Code muss „reentrant“ sein
erlaubt mehrfache, simultane Instanziierungen einer Prozedur
der Bereich/Zustand einer einzelnen Prozedur-Instanziierung
1034
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Stack-Frame
I
I
„Closure“: alle Daten für einen Funktionsaufruf
Daten
I
I
I
I
I
Verwaltung
I
I
I
beim Aufruf wird Speicherbereich zugeteilt
beim Return
–"–
freigegeben
Adressenverweise („Pointer“)
I
I
N. Hendrich
Aufruf-Parameter der Funktion/Prozedur
Rücksprungadresse
lokale Variablen
temporäre Daten
„Setup“ Code
„Finish“ Code
Stackpointer %esp gibt das obere Ende des Stacks an
Framepointer %ebp gibt den Anfang des aktuellen Frame an
1035
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame
Code Structure
yoo(…)
{
•
•
who();
•
•
}
N. Hendrich
Call Chain
yoo
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
who
amI
amI(…)
{
•
•
amI();
•
•
}
amI
amI
amI
1036
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
yoo(…)
{
•
•
who();
•
•
}
N. Hendrich
Call Chain
yoo
Frame
Pointer
%ebp
•
•
•
yoo
Stack
Pointer
%esp
1037
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
N. Hendrich
Call Chain
yoo
Frame
Pointer
%ebp
yoo
who
who
Stack
Pointer
%esp
1038
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
Frame
Pointer
%ebp
who
amI
amI
Stack
Pointer
%esp
N. Hendrich
1039
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
who
amI
amI
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
N. Hendrich
1040
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
who
amI
amI
amI
amI
Frame
Pointer
%ebp
amI
amI
Stack
Pointer
%esp
N. Hendrich
1041
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
who
amI
amI
Frame
Pointer
%ebp
amI
amI
amI
N. Hendrich
Stack
Pointer
%esp
1042
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
amI();
•
•
}
Call Chain
yoo
yoo
who
Frame
Pointer
%ebp
amI
amI
amI
who
Stack
Pointer
%esp
amI
N. Hendrich
1043
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
yoo
Frame
Pointer
%ebp
yoo
who
who
amI
Stack
Pointer
%esp
amI
amI
N. Hendrich
1044
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
amI(…)
{
•
•
•
•
}
Call Chain
yoo
yoo
Frame
Pointer
%ebp
who
amI
amI
who
amI
amI
Stack
Pointer
%esp
amI
N. Hendrich
1045
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
•
•
•
who(…)
{
• • •
amI();
• • •
amI();
• • •
}
Call Chain
Frame
Pointer
%ebp
yoo
yoo
who
who
amI
amI
Stack
Pointer
%esp
amI
amI
N. Hendrich
1046
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Stack-Frame (cont.)
yoo(…)
{
•
•
who();
•
•
}
Call Chain
Frame
Pointer
%ebp
•
•
•
yoo
Stack
Pointer
%esp
yoo
who
amI
amI
amI
amI
N. Hendrich
1047
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
x86/Linux Stack-Frame
aktueller Stack-Frame
I
I
I
von oben nach unten organisiert
„Top“. . . „Bottom“
Parameter für weitere Funktion
die aufgerufen wird call
lokale Variablen
I
Caller
Frame
Arguments
Frame Pointer
(%ebp)
wenn sie nicht in Registern gehalten
werden können
I
gespeicherter Registerkontext
I
Zeiger auf vorherigen Frame
Saved
Registers
+
Local
Variables
Stack Pointer
(%esp)
N. Hendrich
Return Addr
Old %ebp
Argument
Build
1048
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
x86/Linux Stack-Frame (cont.)
„Caller“ Stack-Frame
I Rücksprungadresse
I
I
von call-Anweisung erzeugt
Caller
Frame
Argumente für aktuellen Aufruf
Arguments
Frame Pointer
(%ebp)
Return Addr
Old %ebp
Saved
Registers
+
Local
Variables
Stack Pointer
(%esp)
N. Hendrich
Argument
Build
1049
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Register Sicherungskonventionen
I
yoo („Caller“) ruft Prozedur who („Callee“) auf
yoo:
• • •
movl $15213, %edx
call who
addl %edx, %eax
• • •
ret
I
who:
• • •
movl 8(%ebp), %edx
addl $91125, %edx
• • •
ret
kann who Register für vorübergehende Speicherung benutzen?
I
Inhalt von %edx wird von who überschrieben
⇒ zwei mögliche Konventionen
I
I
N. Hendrich
„Caller -Save“
yoo speichert in seinen Frame vor Prozeduraufruf
„Callee-Save“
who speichert in seinen Frame vor Benutzung
1050
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
x86/Linux Register Verwendung
Integer Register
I zwei werden speziell verwendet
I
I
I
I
I
N. Hendrich
%ebx, %esi, %edi
alte Werte werden vor Verwendung
auf dem Stack gesichert
„Caller-Save“ Register
I
I
%ebp, %esp
„Callee-Save“ Register
I
%eax
Caller-Save
Temporaries
%edx
%ecx
%ebx
Callee-Save
Temporaries
%esi
%edi
%esp
Special
%ebp
%eax, %edx, %ecx
“Caller” sichert diese Register
Register %eax speichert auch den zurückgelieferten Wert
1051
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: Rekursive Fakultät
int rfact(int x)
{
int rval;
if (x <= 1)
return 1;
rval = rfact(x-1);
return rval * x;
}
I
%eax
I
I
%ebx
I
I
N. Hendrich
benutzt ohne vorheriges Speichern
am Anfang speichern
am Ende zurückschreiben
.globl rfact
.type
rfact,@function
rfact:
pushl %ebp
movl %esp,%ebp
pushl %ebx
movl 8(%ebp),%ebx
cmpl $1,%ebx
jle .L78
leal -1(%ebx),%eax
pushl %eax
call rfact
imull %ebx,%eax
jmp .L79
.align 4
.L78:
movl $1,%eax
.L79:
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
1052
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: rfact – Stack „Setup“
pre %ebp
%ebp
pre %ebx
Entering Stack
Caller
x
Rtn adr
%esp
rfact:
pushl %ebp
movl %esp,%ebp
pushl %ebx
pre %ebp
Caller
Callee
N. Hendrich
pre %ebx
8
x
4
Rtn adr
0 Old %ebp
%ebp
-4 Old %ebx
%esp
1053
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: rfact – Rekursiver Aufruf
Recursion
movl 8(%ebp),%ebx
cmpl $1,%ebx
jle .L78
leal -1(%ebx),%eax
pushl %eax
call rfact
imull %ebx,%eax
jmp .L79
.L78:
#
movl $1,%eax
.L79:
#
int rfact(int x)
{
int rval;
if (x <= 1)
return 1;
rval = rfact(x-1) ;
return rval * x;
}
N. Hendrich
# ebx = x
# Compare x : 1
# If <= goto Term
# eax = x-1
# Push x-1
# rfact(x-1)
# rval * x
# Goto done
Term:
# return val = 1
Done:
Registers
%ebx Stored value of x
%eax
Temporary value of x-1
Returned value from rfact(x-1)
Returned value from this call
1054
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: rfact – Rekursion
leal -1(%ebx),%eax
pushl %eax
call rfact
x
x
x
Rtn adr
Rtn adr
Rtn adr
Old %ebp
%ebp
Old %ebp
Old %ebx
%esp
Old %ebx
x-1
Old %ebp
%ebp
%esp
x-1
Rtn adr
%eax
x-1
%eax
x-1
%eax
x-1
%ebx
x
%ebx
x
%ebx
x
N. Hendrich
%ebp
Old %ebx
%esp
1055
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: rfact – Ergebnisübergabe
imull %ebx,%eax
Return from Call
x
x
Rtn adr
Rtn adr
Old %ebp
Old %ebp
%ebp
Old %ebx
x-1
%ebp
Old %ebx
%esp
x-1
%eax
(x-1)!
%eax
x!
%ebx
x
%ebx
x
%esp
Assume that rfact(x-1)
returns (x-1)! in register %eax
N. Hendrich
1056
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: rfact – Stack „Finish“
movl -4(%ebp),%ebx
movl %ebp,%esp
popl %ebp
ret
pre %ebp
pre %ebx
8
x
4
Rtn adr
0 Old %ebp
%ebp
-4 Old %ebx
-8
x-1
%eax
x!
%ebx Old %ebx
N. Hendrich
pre %ebp
pre %ebp
pre %ebx
pre %ebx
8
x
x
4
Rtn adr
Rtn adr
0 Old %ebp
%esp
%ebp
%esp
%ebp
%esp
%eax
x!
%ebx Old %ebx
%eax
x!
%ebx Old %ebx
1057
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Zeiger auf Adresse / call by reference
I
Variable der aufrufenden Funktion soll modifiziert werden
⇒ Adressenverweis (call by reference)
I
Beispiel: sfact
Recursive Procedure
void s_helper
(int x, int *accum)
{
if (x <= 1)
return;
else {
int z = *accum * x;
*accum = z;
s_helper (x-1,accum);
}
}
N. Hendrich
Top-Level Call
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
1058
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: sfact
Initial part of sfact
_sfact:
pushl %ebp
movl %esp,%ebp
subl $16,%esp
movl 8(%ebp),%edx
movl $1,-4(%ebp)
#
#
#
#
#
Save %ebp
Set %ebp
Add 16 bytes
edx = x
val = 1
8
x
4
Rtn adr
0 Old %ebp
%ebp
-4 val = 1
-8
I
lokale Variable val auf Stack speichern
I
I
I
Push val auf Stack
I
I
N. Hendrich
Pointer auf val
berechnen als -4(%ebp)
zweites Argument
movl $1, -4(%ebp)
-12
Unused
-16
%esp
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
1059
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: sfact – Pointerübergabe bei Aufruf
Calling s_helper from sfact
leal -4(%ebp),%eax
pushl %eax
pushl %edx
call s_helper
movl -4(%ebp),%eax
• • •
#
#
#
#
#
#
Compute &val
Push on stack
Push x
call
Return val
Finish
Stack at time of call
8
x
4
Rtn adr
0 Old %ebp
-8
-12
int sfact(int x)
{
int val = 1;
s_helper(x, &val);
return val;
}
N. Hendrich
%ebp
-4 val =x!
= 1
Unused
-16
&val
x
%esp
1060
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Beispiel: sfact – Benutzung des Pointers
void s_helper
(int x, int *accum)
{
• • •
int z = *accum * x;
*accum = z;
• • •
}
accum*x
accum
%eax
accum*x
x
%ecx
x
%edx
• • •
movl %ecx,%eax
# z = x
imull (%edx),%eax # z *= *accum
movl %eax,(%edx) # *accum = z
• • •
I
Register %ecx speichert x
I
Register %edx mit Zeiger auf accum
N. Hendrich
1061
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.3.6 Assembler-Programmierung - x86 Assemblerprogrammierung - Funktionsaufrufe und Stack
64-040 Rechnerstrukturen
Zusammenfassung – Stack
I
Stack ermöglicht Funktionsaufrufe und Rekursion
I
lokaler Speicher für jeden Prozeduraufruf („call“)
I
I
I
grundlegendes (Stack-) Prinzip
I
I
Prozeduren terminieren in umgekehrter Reihenfolge der Aufrufe
x86 Prozeduren sind Kombination von Anweisungen und
Konventionen
I
I
call- und ret-Befehle
Konventionen zur Registerverwendung
I
I
I
N. Hendrich
Instanziierungen beeinflussen sich nicht
Adressierung lokaler Variablen und Argumente ist relativ zur
Stackposition (Framepointer)
„Caller-Save“ / „Callee-Save“
%ebp und %esp
festgelegte Organisation des Stack-Frame
1062
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.1 Assembler-Programmierung - Speicherverwaltung - Elementare Datentypen
64-040 Rechnerstrukturen
Elementare Datentypen
I
Ganzzahl (Integer)
I
I
I
I
Gleitkomma (Floating Point)
I
I
N. Hendrich
wird in allgemeinen Registern gespeichert
abhängig von den Anweisungen: signed/unsigned
Intel
gas Bytes
C
gas: Gnu ASsembler
byte
b
1
[unsigned] char
word
w
2
[unsigned] short
double word
l
4
[unsigned] int
wird in Gleitkomma-Registern gespeichert
Intel
gas Bytes
C
gas: Gnu ASsembler
Single
s
4
float
Double
l
8
double
Extended
t
10/12
long double
1063
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Array: Allokation / Speicherung
I
T A[N];
I
I
Array A mit Daten von Typ T und N Elementen
fortlaufender Speicherbereich von N×sizeof(T) Bytes
char string[12];
x + 12
x
int val[5];
x
double a[4];
x+4
x+8
x
x+8
x + 16
x + 12
x + 16
x + 24
x + 20
x + 32
char *p[3];
x
N. Hendrich
x+4
x+8
1064
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Array: Zugriffskonvention
I
T A[N];
I
I
Array A mit Daten von Typ T und N Elementen
Bezeichner A zeigt auf erstes Element des Arrays: Element 0
int val[5];
1
x
5
x+4
2
x+8
1
3
x + 12
x + 16
x + 20
Reference Type Value
N. Hendrich
val[4]
int
3
val
int *
x
val+1
int *
x+4
&val[2]
int *
x+8
val[5]
int
??
*(val+1)
int
5
val + i
int *
x+4i
1065
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Beispiel: einfacher Arrayzugriff
typedef int zip_dig[5];
zip_dig cmu = { 1, 5, 2, 1, 3 };
zip_dig mit = { 0, 2, 1, 3, 9 };
zip_dig ucb = { 9, 4, 7, 2, 0 };
zip_dig cmu;
1
16
zip_dig mit;
20
0
36
zip_dig ucb;
2
24
2
40
9
56
N. Hendrich
5
28
1
44
4
60
1
32
3
48
7
64
3
52
2
68
36
9
56
0
72
76
1066
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Beispiel: einfacher Arrayzugriff (cont.)
I
I
Register %edx : Array Startadresse
%eax : Array Index
Adressieren von 4×%eax+%edx
⇒ Speicheradresse (%edx,%eax,4)
int get_digit
(zip_dig z, int dig)
{
return z[dig];
}
I
I
N. Hendrich
Memory Reference Code
# %edx = z
# %eax = dig
movl (%edx,%eax,4),%eax # z[dig]
keine Bereichsüberprüfung („bounds checking“)
Verhalten außerhalb des Indexbereichs ist
Implementierungsabhängig
1067
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Beispiel: Arrayzugriff mit Schleife
I
Originalcode
I
transformierte Version: gcc
I
I
I
I
N. Hendrich
Laufvariable i eliminiert
aus Array-Code
wird Pointer-Code
in „do-while“ Form
Test bei Schleifeneintritt
unnötig
int zd2int(zip_dig z)
{
int i;
int zi = 0;
for (i = 0; i < 5; i++) {
zi = 10 * zi + z[i];
}
return zi;
}
int zd2int(zip_dig z)
{
int zi = 0;
int *zend = z + 4;
do {
zi = 10 * zi + *z;
z++;
} while(z <= zend);
return zi;
}
1068
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Beispiel: Arrayzugriff mit Schleife (cont.)
I
I
I
Register %ecx : z
%eax : zi
%ebx : zend
*z + 2*(zi+4*zi)
ersetzt 10*zi + *z
z++ Inkrement: +4
int zd2int(zip_dig z)
{
int zi = 0;
int *zend = z + 4;
do {
zi = 10 * zi + *z;
z++;
} while(z <= zend);
return zi;
}
# %ecx = z
xorl %eax,%eax
leal 16(%ecx),%ebx
.L59:
leal (%eax,%eax,4),%edx
movl (%ecx),%eax
addl $4,%ecx
leal (%eax,%edx,2),%eax
cmpl %ebx,%ecx
jle .L59
N. Hendrich
# zi = 0
# zend = z+4
#
#
#
#
#
#
5*zi
*z
z++
zi = *z + 2*(5*zi)
z : zend
if <= goto loop
1069
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Zwei- und mehrdimensionale Arrays
(N × M) Matrizen? drei grundsätzliche Möglichkeiten
I
Array von Pointern auf Zeilen-Arrays von Elementen
I
I
I
Array von N × M Elementen und passende Adressierung
I
I
I
N. Hendrich
sehr flexibel, auch für nicht-rechteckige Layouts
Sharing/Aliasing von Zeilen möglich
Java
row-major Anordnung
column-major Anordnung
C, C++
Matlab, FORTRAN
bei Verwendung/Mischung von Bibliotheksfunktionen aus
anderen Sprachen unbedingt berücksichtigen
1070
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Java: Array von Pointern auf Arrays von Elementen
class MatrixDemo {
int matrix [][]; // matrix [i]->
public MatrixDemo ( int NROWS , int NCOLS ) {
matrix = new int[NROWS ][ NCOLS ];
for( int r=0; r < matrix . length ; r++ ) {
for( int c =0; c < matrix [r]. length ; c++ ) {
matrix [r][c] = 100*r + c;
}
}
// int [] row0 = matrix [0];
// int
m23 = matrix [2][3];
}
public int get( int r, int c ) {
return matrix [r][c];
}
}
N. Hendrich
0
1
2
3
100 101
102 103
200 201
202 203
300 301
302 303
400 401
402 403
1071
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Zweidimensionale Arrays in C
int n_rows = 4; int n_cols = 5;
int matrix [4][5]; // 00 01 02 03 04 10 11 12 13 14 20 .. 3
int schach [8][8] = { 0,1,2,3,4,5,6,7, 10 ,11 ,12 ,13 ,... , 20, 2
int
int
int
int
m00
m01
m20
m34
=
=
=
=
matrix [0][0];
matrix [0][1];
matrix [2][0];
matrix [3][4];
//
//
//
//
*( matrix [0]
*( matrix [0]
*( matrix [2]
*( matrix [3]
+
+
+
+
0);
1);
0);
4);
int *elem = &( matrix [2][2]);
elem ++;
// nächste Spalte (bzw. Wraparound );
elem += n_cols ; // nächste Zeile
I
Arrayelemente in „row-major“ Anordnung, Spalten fortlaufend
I
„column-major“ ist transponiert: 00 10 20 . . . 01 11 21 . . . 34
N. Hendrich
1072
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.2 Assembler-Programmierung - Speicherverwaltung - Arrays
64-040 Rechnerstrukturen
Mehrdimensionale Arrays: entsprechend
I
d-dimensionales N1 × N2 × · · · × Nd Array
I
I
Element addressiert mit Tupel (n1 ; n2 ; : : : ; nd ),
mit d (zero-offset) Indizes nk ∈ [0; N − K − 1]
row-major Anordnung: letzte Dimension ist fortlaufend
0
nd +Nd ·(nd−1 +Nd−1 ·(nd−2 +Nd−2 ·(· · · )))) =
d
X
d
Y
@
k=1
I
N. Hendrich
N‘ A nk
‘=k+1
column-major Anordnung: erste Dimension ist fortlaufend
n1 +N1 ·(n2 +N2 ·(n3 +N3 ·(· · ·+Nd−1 nd ) · · · ))) =
I
1
d
X
k−1
Y
k=1
‘=1
!
N‘ nk
oder Arrays von Arrays von Arrays auf Arrays auf Elemente
1073
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.3 Assembler-Programmierung - Speicherverwaltung - Strukturen
64-040 Rechnerstrukturen
Strukturen (Records)
I
I
I
Allokation eines zusammenhängenden Speicherbereichs
Elemente der Struktur über Bezeichner referenziert
verschiedene Typen der Elemente sind möglich
struct rec {
int i;
int a[3];
int *p;
};
void
set_i(struct rec *r,
int val)
{
r->i = val;
}
N. Hendrich
Memory Layout
i
0
a
4
p
16 20
Assembly
# %eax = val
# %edx = r
movl %eax,(%edx)
# Mem[r] = val
1074
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.3 Assembler-Programmierung - Speicherverwaltung - Strukturen
64-040 Rechnerstrukturen
Strukturen: Zugriffskonventionen
r
I
I
Zeiger auf Byte-Array für Zugriff
auf Struktur(element) r
Compiler bestimmt Offset für
jedes Element
struct rec {
int i;
int a[3];
int *p;
};
i
0
a
4
p
16
r + 4 + 4*idx
int *
find_a
(struct rec *r, int idx)
{
return &r->a[idx];
}
# %ecx = idx
# %edx = r
leal 0(,%ecx,4),%eax
# 4*idx
leal 4(%eax,%edx),%eax # r+4*idx+4
N. Hendrich
1075
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.3 Assembler-Programmierung - Speicherverwaltung - Strukturen
64-040 Rechnerstrukturen
Beispiel: Strukturreferenzierung
i
struct rec {
int i;
int a[3];
int *p;
};
0
a
4
i
0
p
16
a
4
16
Element i
void
set_p(struct rec *r)
{
r->p =
&r->a[r->i];
}
N. Hendrich
# %edx = r
movl (%edx),%ecx
leal 0(,%ecx,4),%eax
leal 4(%edx,%eax),%eax
movl %eax,16(%edx)
#
#
#
#
r->i
4*(r->i)
r+4+4*(r->i)
Update r->p
1076
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.3 Assembler-Programmierung - Speicherverwaltung - Strukturen
64-040 Rechnerstrukturen
Ausrichtung der Datenstrukturen (Alignment)
I
I
Datenstrukturen an Wortgrenzen ausrichten
double- / quad-word
sonst Problem
− ineffizienter Zugriff über Wortgrenzen hinweg
− virtueller Speicher und Caching
⇒ Compiler
I typisches
Länge
1 Byte
2 Byte
4 Byte
8 Byte
12 Byte
N. Hendrich
erzeugt „Lücken“ zur richtigen Ausrichtung
Alignment (IA32)
Typ
Windows Linux
char
keine speziellen Verfahren
short
Adressbits:
...0
...0
int, float, char *
–"–
...00
...00
double
–"–
...000
...00
long double
–"–
–
...00
1077
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.3 Assembler-Programmierung - Speicherverwaltung - Strukturen
64-040 Rechnerstrukturen
Beispiel: Structure Alignment
struct S1 {
char c;
int i[2];
double v;
} *p;
c
p+0
i[0]
p+4
Multiple of 4
Multiple of 8
N. Hendrich
i[1]
p+8
v
p+16
p+24
Multiple of 8
Multiple of 8
1078
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Umsetzung von Objektorientierung?
I
Klassen/Objekte verbinden Daten und Methoden
I
I
I
I
name-mangling
rtti
vtable
Grundidee
I
I
I
I
I
I
I
N. Hendrich
polymorphe Funktionen
Metadaten, run-time type-information
Vererbung und dynamischer Funktionsaufruf
Datenstrukturen wie in Assembler/C
Schema zur Erzeugung eindeutiger Namen
zusätzliche Pointer auf Typ/Klassen-Information
zusätzliche Pointer auf Funktionstabelle(n)
Methodenaufrufe bekommen this-Pointer als Argument
gute Performance erfordert effiziente Implementierung
Details normalerweise vor dem Programmierer verborgen
1079
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Objekte: Exemplare von Klassen
I
I
I
kombinieren Daten mit den zugehörigen Methoden
Datenelemente wie C/Assembler Strukturen angeordnet
ein Pointer auf die rtti-Datenstruktur
I
I
I
I
ein Pointer auf die vtable-Tabelle
I
I
I
Array mit allen Methoden der Klasse
Name-Mangling erhält Typ-Infos der Parameter
aus Effizienzgründen diese Pointer ggf. mit negativem Offset
I
N. Hendrich
Debug-Infos: Name der Klasse, Datenelemente
Pointer auf Basisklasse(n)
Interfaces und Vererbungsinformation
Speicherverwaltung berücksichtigt dies
1080
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Polymorphe Funktionen: Name-Mangling
I
I
Programmierer arbeitet mit Klassen und deren Methoden
polymorphe Funktionen, abhängig vom Typ der Parameter
class polymorph { public :
float f( int i )
{ return 2.0f*i; }
float f( float f ) { return 1.5f*f; } ...
}
I
aber: Assembler und Linker erwarten globale Funktionen
⇒ Name-Mangling („name decoration“) im Compiler
I
I
I
I
N. Hendrich
Funktionsname gebildet aus Prefix + Name + Typkennung
Prefix bildet Klassennamen/Namespace ab
Typkennung zur eindeutigen Unterscheidung der Argumente
_ZN9polymorph1fEi _ZN9polymorph1fEf
Java: siehe Java Native Interface und javah-Tool
1081
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Methodenaufruf: this-Pointer
I
bisher: Funktionen/Code vollkommen separat von Daten
I
woher weiss eine Methode, zu welchem Objekt sie gehört?
I
wie kommt eine Methode an Exemplarvariablen heran?
I
Trick: Compiler übergibt this als erstes Argument
I
I
I
I
I
I
N. Hendrich
implizit, muss normalerweise nicht geschrieben werden
Pointer auf das aktuelle Objekt
Referenz auf Daten über this->x
Referenz auf Methoden über this->vtable[offset]
zusätzliche Funktionsparameter anschließend wie gewohnt
Point3D.f( int i, int j ) wird intern zu
Point3D.f( Point3D *this, int i, int j )
1082
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Methodenaufruf: this-Pointer
# include <stdio .h>
class Point3D {
private : int x; int y; int z;
public :
Point3D ( int _x , int _y , int _z ) { x = _x; y = _y; z = _z; }
int getX () { return x; }
};
int main( int argc , char ** argv ) {
Point3D p( 42, 2, 3 );
printf ( "%d\n", p.getX () );
}
08048454 <_ZN7Point3D4getXEv >:
8048454:
55
8048455:
89 e5
8048457:
8b 45 08
804845 a:
8b 00
804845 c:
5d
804845 d:
c3
804845 e:
90
804845 f:
90
N. Hendrich
push
mov
mov
mov
pop
ret
nop
nop
%ebp
%esp ,% ebp
0x8(% ebp ),% eax
(% eax ),% eax
%ebp
1083
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Virtual Table: Dynamischer Methodenaufruf
I
Compiler kennt und sammelt alle Methoden einer Klasse
I
I
inklusive aller Methoden der Basisklassen
erzeugt vtable Array mit Pointer auf die Funktionen
I
Aufruf der Funktionen als *((this->vtable)+offset)()
wobei der Offset die jeweilige Methode auswählt
I
I
I
I
I
I
N. Hendrich
wieder this-Pointer als erster Parameter
weitere Parameter anschließend auf dem Stack
ein zusätzlicher Speicherzugriff (vergl. mit direktem Aufruf)
vererbte Methoden zeigen auf Code der Basisklasse
überschriebene Methoden zeigen auf Code der Unterklasse
super.f() durch Zugriff auf vtable der Basisklasse
1084
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Virtual Table: Vererbung
LearnCpp.Com: 12.5 the virtual table
N. Hendrich
1085
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.4.4 Assembler-Programmierung - Speicherverwaltung - Objektorientierte Konzepte
64-040 Rechnerstrukturen
Zusammenfassung – Datentypen
I
Arrays
I
I
I
I
Compileroptimierungen
I
I
I
I
I
Bytes werden in der ausgewiesenen Reihenfolge zugeteilt
ggf. Leerbytes, um die richtige Ausrichtung zu erreichen
Objekte
I
I
N. Hendrich
Compiler wandelt Array-Code in Pointer-Code um
verwendet Adressierungsmodi um Arrayindizes zu skalieren
viele Tricks, um die Array-Indizierung in Schleifen zu verbessern
Strukturen
I
I
fortlaufend zugeteilter Speicher
Adressverweis auf das erste Element
keine Bereichsüberprüfung (Bounds Checking)
wie Strukturen, zwei extra Pointer auf Typ-Infos und vtable
Methodenaufruf über vtable mit this-Pointer
1086
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Linker und Loader
I
Statisches Linken
I
Object-Dateien (ELF)
I
Statische Funktionsbibliotheken
I
Loading
I
Dynamische Funktionsbibliotheken (shared libraries)
N. Hendrich
1087
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Bisher: gesamtes Programm in einer Quelldatei
m.c
ASCII source file
Translator
p
I
Binary executable object file
(memory image on disk)
Probleme
− schlechte Effizienz: jede kleine Änderung erfordert volle
Neu-Compilierung des Programms
− keine Modularisierung: wie können wichtige Funktionen
wiederverwendet werden? (z.B. malloc, printf)
I
Lösung
I
N. Hendrich
Statisches Binden („static linking“)
1088
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Static Linking: Konzept
m.c
a.c
Translators
Translators
m.o
a.o
Separately compiled
relocatable object files
Linker (ld)
p
Executable object file (contains code
and data for all functions defined in m.c
and a.c)
I
Quelltext auf mehrere Dateien aufgeteilt
I
einzeln in (verschiebbaren: „PIC“) Objektcode compiliert
I
Linker baut daraus eine ausführbare Datei
N. Hendrich
1089
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Static Linking: Aufgaben des Linkers
I
I
I
Zusammenführen der einzelnen (.o) Objektdateien in eine
vollständige kombinierte Objektdatei
Suchen der referenzierten Funktionen
Relozieren aller Speicherreferenzen
I
I
I
I
relocate symbols
int *xp=&x;
printf();
Compiler(-driver) kümmert sich um Aufruf der einzelnen Tools
I
I
N. Hendrich
für Daten
und Funktionen
nicht aufgerufene Funktionen werden eliminiert
external references
Präprozessor (cpp), Compiler (cc1),
Assembler (gas) und Linker (ld)
„Finetuning“ und Reihenfolge über Kommandozeilen-Parameter
1090
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Static Linking: Vorteile
I
I
Programm aus übersichtlichen Modulen zusammengesetzt
erlaubt den Aufbau von Funktionsbibliotheken,
z.B. mathematische Funktionen, Standard C-Library,
Datenstrukturen, TCP/IP, Grafik . . .
⇒ schnellere Entwicklung: nur geänderte Quelltexte müssen neu
compiliert werden, Linken ist viel schneller als Compilieren
⇒ kompakte Programme: das ausführbare Programm enthält nur
die tatsächlich benutzten Funktionen aus den Bibliotheken
N. Hendrich
1091
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Unix: Executable and Linkable Format (ELF)
I
I
Unix/Linux Standard für Objektdateien
einheitliches Dateiformat für
I
I
I
I
I
relozierbare Objektdateien .o
ausführbare Objektdateien „.exe“
„shared“ Objektdateien .so
ELF im Prinzip prozessor-/architektur-unabhängig
aber gegebene Objektdatei ist natürlich architektur-spezifisch
I
I
enthält Maschinenbefehle für Zielarchitektur
Infos sind im Header codiert
I
Microsoft nutzt COFF/PE („portable executable“) .exe .dll
I
Java Class-Format .class
N. Hendrich
1092
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
ELF Object File Format
I
ELF header
I
magic number, Typ (.o, .so, .exe),
Maschine, Byte-Order, usw.
Program header table
(required for executables)
I
Program Header Tabelle
.text section
I
.text Programmcode
.data section
I
.data Statische Variablen
I
I
.bss Daten
I
I
I
N. Hendrich
initiale Werte
unitialisierte statische Daten
„block started by symbol“
„better save space“
0
ELF header
.bss section
.symtab
.rel.txt
.rel.data
.debug
Section header table
(required for relocatables)
1093
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
ELF Object File Format (cont.)
I
.symtab Symboltabelle
I
I
I
.rel.text Relocation-Infos
I
I
I
Adressen aller Pointer, die beim
Linken angepasst werden müssen
.debug
I
N. Hendrich
alle Maschinenbefehle, die beim
Linken angepasst werden müssen
Adressen aller (Sprung-) Befehle, die
beim Linken angepasst werden müssen
.rel.data Relocation-Infos
I
I
Namen aller Funktionen und statischen
Variablen, Sektionsnamen und Offets
Hilfsinformationen fürs Debugging
0
ELF header
Program header table
(required for executables)
.text section
.data section
.bss section
.symtab
.rel.txt
.rel.data
.debug
Section header table
(required for relocatables)
1094
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Beispiel-Quellcode
m.c
int e=7;
a.c
extern int e;
int main() {
int r = a();
exit(0);
}
int *ep=&e;
int x=15;
int y;
int a() {
return *ep+x+y;
}
I
zwei Funktionen: main(), a()
I
zusätzlicher System-Code, Initialisierung und exit()
I
vier globale Variablen: e, *ep, x, y
N. Hendrich
1095
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Erzeugte ELF-Datei
Relocatable Object Files
system code
.text
system data
.data
Executable Object File
0
headers
system code
main()
m.o
a.o
N. Hendrich
main()
.text
int e = 7
.data
a()
.text
int *ep = &e
int x = 15
int y
.data
.bss
.text
a()
more system code
system data
int e = 7
int *ep = &e
int x = 15
uninitialized data
.symtab
.debug
.data
.bss
1096
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Zuordnung der externen Referenzen
m.c
int e=7;
Def of local
symbol e
int main() {
int r = a();
exit(0);
}
Def of
local
symbol
Ref to external
symbol exit
Ref to external ep
(defined in
libc.so)
I
N. Hendrich
symbol a
a.c
extern int e;
int *ep=&e;
int x=15;
int y;
Ref to
external
symbol e
int a() {
return *ep+x+y;
}
Defs of
local
symbols
x and y
Def of
Refs of local
local
symbols ep,x,y
symbol a
Beispiel: int e=7;
definiert und initialisiert Symbol e
int *ep=&e; definiert Symbol ep und
initialisiert mit der Adresse von e
1097
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
m.o Relocation-Infos
m.c
int e=7;
Disassembly of section .text:
int main() {
int r = a();
exit(0);
}
00000000 <main>: 00000000 <main>:
0:
55
pushl %ebp
1:
89 e5
movl
%esp,%ebp
3:
e8 fc ff ff ff call
4 <main+0x4>
4: R_386_PC32
a
8:
6a 00
pushl $0x0
a:
e8 fc ff ff ff call
b <main+0xb>
b: R_386_PC32
exit
f:
90
nop
Disassembly of section .data:
00000000 <e>:
0:
07 00 00 00
N. Hendrich
1098
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
a.o Relocation-Infos für .text
a.c
extern int e;
Disassembly of section .text:
int *ep=&e;
int x=15;
int y;
00000000 <a>:
0:
55
1:
8b 15 00 00 00
6:
00
int a() {
return *ep+x+y;
}
N. Hendrich
7:
a1 00 00 00 00
c:
e:
10:
12:
17:
89
03
89
03
00
18:
19:
5d
c3
e5
02
ec
05 00 00 00
pushl
movl
%ebp
0x0,%edx
3: R_386_32
ep
movl
0x0,%eax
8: R_386_32
x
movl
%esp,%ebp
addl
(%edx),%eax
movl
%ebp,%esp
addl
0x0,%eax
14: R_386_32
popl
%ebp
ret
y
1099
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
a.o Relocation-Infos für .data
a.c
extern int e;
int *ep=&e;
int x=15;
int y;
Disassembly of section .data:
00000000 <ep>:
0:
00 00 00 00
0: R_386_32
e
00000004 <x>:
4:
0f 00 00 00
int a() {
return *ep+x+y;
}
N. Hendrich
1100
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Erzeugtes ausführbares Programm .text
08048530 <main>:
8048530:
55
8048531:
89
8048533:
e8
8048538:
6a
804853a:
e8
804853f:
90
08048540 <a>:
8048540:
8048541:
8048546:
8048547:
804854c:
804854e:
8048550:
8048552:
8048557:
8048558:
8048559:
N. Hendrich
55
8b
08
a1
89
03
89
03
08
5d
c3
pushl
movl
call
pushl
call
nop
%ebp
%esp,%ebp
8048540 <a>
$0x0
8048474 <_init+0x94>
15 1c a0 04
pushl
movl
%ebp
0x804a01c,%edx
20 a0 04 08
e5
02
ec
05 d0 a3 04
movl
movl
addl
movl
addl
0x804a020,%eax
%esp,%ebp
(%edx),%eax
%ebp,%esp
0x804a3d0,%eax
popl
ret
%ebp
e5
08 00 00 00
00
35 ff ff ff
1101
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Erzeugtes ausführbares Programm .data
m.c
int e=7;
Disassembly of section .data:
int main() {
int r = a();
exit(0);
}
0804a018 <e>:
804a018:
07 00 00 00
0804a01c <ep>:
804a01c:
18 a0 04 08
0804a020 <x>:
804a020:
0f 00 00 00
a.c
extern int e;
int *ep=&e;
int x=15;
int y;
int a() {
return *ep+x+y;
}
N. Hendrich
1102
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Starke und schwache Symbole
p1.c
p2.c
strong
int foo=5;
int foo;
strong
p1() {
}
p2() {
}
weak
strong
I
strong: alle Prozeduren und initialisierte globale Daten
I
weak: nicht-initialisierte globale Daten
1. jedes starke Symbol darf nur einmal auftreten
2. ein schwaches Symbol wird einem starken Symbol zugewiesen
3. der Linker kann sich eines von mehreren Schwachen aussuchen
N. Hendrich
1103
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Linker-Quiz: Separate Quelldateien (C)
Link time error: two strong symbols (p1)
int x;
p1() {}
p1() {}
int x;
p1() {}
int x;
p2() {}
References to x will refer to the same
uninitialized int. Is this what you really want?
int x;
int y;
p1() {}
double x;
p2() {}
Writes to x in p2 might overwrite y!
Evil!
int x=7;
int y=5;
p1() {}
double x;
p2() {}
Writes to x in p2 will overwrite y!
Nasty!
int x=7;
p1() {}
int x;
p2() {}
References to x will refer to the same initialized
variable.
Nightmare scenario: two identical weak structs, compiled by different compilers
with different alignment rules.
N. Hendrich
1104
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Funktionsbibliotheken
I
Zugriff auf häufig benötigte Funktionen?
I
I
I
I
statische Funktionsbibliotheken (.a Archiv-Dateien)
I
I
I
N. Hendrich
Math, Strings, I/O, Threads, Speicherverwaltung, usw.
alle Funktionen in einer Quelldatei ist keine Lösung
jede Funktion in separater Quelldatei ist sehr mühsam
Sammlung von compilierten Funktionen mit Index
Linker sucht (strong) Symbole im Index
gefundene Funktionen und Daten werden ins Programm
eingebunden
1105
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Funktionsbibliotheken (cont.)
p1.c
p2.c
Translator
Translator
p1.o
p2.o
libc.a
static library (archive) of
relocatable object files
concatenated into one file.
Linker (ld)
p
executable object file (only contains code
and data for libc functions that are called
from p1.c and p2.c)
Ausführbares Programm gebaut aus
I
relozierbaren Modulen (.o), compiliert aus den Quelltexten (.c)
I
vordefinierten Funktionsbibliotheken (.a)
I
nur die verwendeten Funktionen landen im Programm
N. Hendrich
1106
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Statische Funktionsbibliotheken zusammenbauen
atoi.c
printf.c
Translator
Translator
atoi.o
printf.o
random.c
...
random.o
Archiver (ar)
libc.a
I
I
I
I
N. Hendrich
Translator
ar rs libc.a \
atoi.o printf.o … random.o
C standard library
alle Funktionen der Bibliothek einzeln compilieren
Archiver (ar) erzeugt den benötigten Index
erzeugte ELF Datei (.a) mit Objektcode für alle Funktionen
inkrementelles Update möglich (einzelne .c nach .o compilieren)
1107
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Wichtige Bibliotheken
I
libc.a: die C „Standard-Bibliothek“
I
I
I
libm.a: die C „Mathematik-Bibliothek“
I
I
I
I
N. Hendrich
226 Funktionen, ca 1 MByte
Gleitkommafunktionen (sin, cos, tan, log, exp, sqrt, . . . )
Funktionen anzeigen
I
I
900 Funktionen, ca. 8 MByte
I/O, Speicherverwaltung, Strings, Datum und Zeit, Zufallszahlen,
Integer-Arithmetik, Signale
ar -t /usr/lib/libm.a | sort
(32-bit)
ar -t /usr/lib64/libm.a | sort
(64-bit)
ar -t /usr/lib/x86_64-linux-gnu/libm.a | sort
Java/Python/usw. benutzen eigene Bibliotheken,
die wiederum auf libc/libm aufbauen
1108
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Funktionsbibliotheken verwenden
I
Linker bekommt Liste der .o und .a Dateien vom Compiler
I
alle Dateien werden nach fehlenden Referenzen durchsucht
I
gefundene Referenzen werden sofort gelinkt („reloziert“)
I
jede fehlende Referenz führt zum Abbruch
⇒ Reihenfolge der Module/Bibliotheken ist wichtig
⇒ Bibliotheken gehören ans Ende der Kommandozeile
I
Unix-Konvention
I
Bibliotheken heissen libXYZ.a
Linker-Kommandozeile ohne „lib“, sondern nur -lXYZ
Suchverzeichnisse mit -L <dir> Option angeben
I
gcc a.c b.c c.o d.o -L . -lbluetooth -lpthread -lm -lc
I
I
N. Hendrich
1109
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Loader: ELF-Module/Programme laden und ausführen
Executable object file for
example program p
ELF header
Program header table
(required for executables)
.text section
0
Process image
init and shared lib
segments
Virtual addr
0x080483e0
.data section
.bss section
.text segment
(r/o)
0x08048494
.symtab
.rel.text
.rel.data
.data segment
(initialized r/w)
0x0804a010
.debug
Section header table
(required for relocatables)
N. Hendrich
0x0804a3b0
.bss segment
(uninitialized r/w)
1110
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Dynamische Bibliotheken „Shared Libraries“
I
Programm wird zur Objektdatei compiliert
I
Bibliotheken werden erst beim Laden dazugelinkt
I
I
I
I
N. Hendrich
die Bibliotheken können von mehreren Prozessen gleichzeitig
benutzt werden, liegen aber (maximal) einmal im Speicher
signifikant effizienter als separat statische gelinkte Programme
Symbole werden entweder sofort (wie beim statischen Binden)
oder „lazy“ referenziert (erst beim ersten Aufruf)
Versionierung: unter Unix/Linux ist es möglich, mehrere
Versionen einer Bibliothek zu verwenden,
libopencv_core.so.2.3.1
1111
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Linker und Loader – Shared Libraries
m.c
a.c
Translators
(cc1, as)
Translators
(cc1,as)
m.o
a.o
Linker (ld)
Partially linked executable p
(on disk)
p
libc.so
Loader/Dynamic Linker
(ld-linux.so)
Fully linked executable
p’ (in memory)
N. Hendrich
Shared library of dynamically
relocatable object files
libc.so functions called by m.c
and a.c are loaded, linked, and
(potentially) shared among
processes.
P’
1112
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.5 Assembler-Programmierung - Linker und Loader
64-040 Rechnerstrukturen
Linker und Loader – Gesamtsystem
m.c
a.c
Translator
Translator
m.o
a.o
libwhatever.a
Static Linker (ld)
p
libc.so
libm.so
Loader/Dynamic Linker
(ld-linux.so)
p’
N. Hendrich
1113
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
ELF: Speicheraufteilung in Regionen
I
Header: Meta-Informationen
I
Stack: Funktionsaufrufe
I
Heap:
I
statische (globale) Daten
I
Code-Bereiche
I
Debug- und Relocation-Infos
I
N. Hendrich
dynamische angeforderte Daten
bisher noch nicht erklärt: wie funktioniert die
dynamische Speicherverwaltung im Heap?
1114
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Dynamic Memory Allocation
I
nicht alle Daten können statisch alloziert werden
I
I
I
I
I
Datenstrukturen dynamisch anlegen
I
I
I
I
I
I
N. Hendrich
Speicher ist begrenzt
viele Daten/Arrays werden nur zeitweise benötigt
viele Algorithmen basieren auf dynamischen Bäumen/Graphen
usw.
erst wenn die Daten benötigt werden
Speicher nach Benutzung wieder freigeben
Assembler, C/C++ benutzen die malloc-Bibliotheksfunktionen
Ursache für viele Programmierfehler
moderne Sprachen (Java, C# usw.) bieten automatische
Heap-Verwaltung mit einem „garbage-collector“
bequem, aber oft auch langsamer, weniger Kontrolle
1115
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Bryant: „Harsh Reality: Memory Matters“
I
I
viele Applikationen sind durch den verfügbaren Speicher
begrenzt, z.B. komplexe Graph-Algorithmen
Programmierfehler im Umgang mit dynamisch angefordertem
Speicher sind häufig und schwer zu beseitigen
I
I
I
Performance eines Programms hängt entscheidend von
effektivem Umgang mit dem Speicher ab
I
I
N. Hendrich
Effekt wird häufig erst spät und weit entfernt bemerkt
siehe wöchentliche Linux/Windows/Application Updates
Cache und Virtual Memory empfindlich gegen falsche
Datenstrukturen und Zugriffsmuster
effiziente Programmierung kann Wunder wirken
1116
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Linux: Speicherbereiche für ein Programm
I
Kernel bei höchsten Adressen
I
Stack wächst nach unten
I
Shared-Bibliotheken mittig
kernel virtual memory
stack
%esp
Memory mapped region for
shared libraries
Allocators request
additional heap memory
from the operating
system using the sbrk
function.
I
Heap (dynamische Daten)
I
globale statische Daten
I
Programmcode
I
Startup-Code ab Adresse 0
N. Hendrich
memory invisible to
user code
the “brk” ptr
run-time heap (via malloc)
uninitialized data (.bss)
initialized data (.data)
program text (.text)
0
1117
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Malloc: Funktionen
I
void* malloc( size_t size )
I
I
I
I
void free( void *p )
I
I
I
gibt den Speicherbereich *p ans Betriebssystem zurück
Pointer p von vorherigem Aufruf von malloc oder realloc
void* realloc( void *p, size_t size)
I
I
N. Hendrich
liefert Pointer auf Speicherbereich mit mindestens size Bytes,
ausgerichtet an 8-Byte Adressen
Aufruf mit size == 0 liefert NULL
liefert NULL, wenn nicht erfolgreich
ändert die Größe des Speicherbereichs *p
wenn erfolgreich, bleibt der Inhalt des Speicherbereichs
unverändert, bis zum Minimum der alten und neuen Größe
1118
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Malloc: Beispielcode
void foo(int n, int m) {
int i, *p;
/* allocate a block of n ints */
if ((p = (int *) malloc(n * sizeof(int))) == NULL) {
perror("malloc");
exit(0);
}
for (i=0; i<n; i++)
p[i] = i;
/* add m bytes to end of p block */
if ((p = (int *) realloc(p, (n+m) * sizeof(int))) == NULL) {
perror("realloc");
exit(0);
}
for (i=n; i < n+m; i++)
p[i] = i;
/* print new array */
for (i=0; i<n+m; i++)
printf("%d\n", p[i]);
free(p); /* return p to available memory pool */
}
N. Hendrich
1119
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Malloc: Speicherlayout
p1 = malloc(4)
p2 = malloc(5)
p3 = malloc(6)
free(p2)
p4 = malloc(2)
N. Hendrich
1120
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Malloc: Anforderungen
I
I
Programme können jederzeit malloc und free aufrufen
die Anzahl oder Größe der angeforderten Blöcke kann nicht von
der Speicherverwaltung beeinflusst werden
I
Anfragen müssen sofort und möglichst schnell erfüllt werden
I
dies erfordert ausreichende freie Speicherbereiche
I
I
N. Hendrich
einmal allozierte Blöcke stehen für weitere Anfragen nicht mehr
zur Verfügung, es sei denn, sie werden mit free() wieder
freigegeben
Vertiefung: eigenes malloc implementieren und testen :-)
1121
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Problem: Fragmentierung
p1 = malloc(4)
p2 = malloc(5)
p3 = malloc(6)
free(p2)
p4 = malloc(6)
oops!
I
N. Hendrich
Wir haben nur Platz für höchstens malloc(5).
1122
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Idee zur Implementierung von free()
p0 = malloc(4)
p0
5
free(p0)
Block size
data
I
Länge eines Blocks im Header gespeichert
I
mindestens ein extra-Wort pro Block
N. Hendrich
1123
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Freie Blöcke finden
4
5
I
2
Länge eines Blocks im Header gespeichert
I
I
I
I
N. Hendrich
6
Zusatz-/Verwaltungsdaten außerhalb des angeforderten Blocks
malloc und free kennen das Speicherlayout, und können
Blöcke suchen bzw. zurückgeben
doppelte verkettete Listen (vorwärts/rückwärts) und
Graphen sind effizienter als die gezeigte einfache Liste
Details: Bryant, O’Hallaron [BO14]
1124
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Freie Blöcke finden: Datenstruktur
I
wie erkennt man, ob ein Block belegt ist?
1 word
size
Format of
allocated and
free blocks
a
a = 1: allocated block
a = 0: free block
size: block size
payload
payload: application data
(allocated blocks only)
optional
padding
I
I
N. Hendrich
erfordert 1-bit extra,
z.B. das niederwertigste Bit im size Feld bei wortweiser
Allozierung (32-bit) und byte-weiser Adressierung
1125
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Freie Blöcke finden
I
first fit: Liste vom Anfang an durchsuchen, erster passender
Block wird zurückgeliefert. Linearer Zeitbedarf
p = start;
while ((p < end) ||
(*p & 1) ||
(*p <= len));
I
I
N. Hendrich
\\ not passed end
\\ already allocated
\\ too small
next fit: startet die Suche vom zuletzt gefundenen Block.
Fragmentierung häufig schlechter als bei first-fit.
best fit: gesamte Liste durchsuchen, Block mit kleinstem
Verschnitt zurückliefern. Weniger Fragmentierung, aber
langsamer als first-fit
1126
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Freie Blöcke finden (cont.)
4
4
6
2
p
void addblock(ptr p, int len) {
int newsize = ((len + 1) >> 1) << 1;
int oldsize = *p & -2;
*p = newsize | 1;
if (newsize < oldsize)
*(p+newsize) = oldsize - newsize;
}
// add 1 and round up
// mask out low bit
// set new length
// set length in remaining
//
part of block
addblock(p, 2)
4
N. Hendrich
4
4
2
2
1127
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Doppelt verkettete Listen (Bidirectional Coalescing)
1 word
Header
Format of
allocated and
free blocks
I
I
N. Hendrich
a
payload and
padding
Boundary tag
(footer)
4
size
4 4
size
4 6
a = 1: allocated block
a = 0: free block
size: total block size
a
payload: application data
(allocated blocks only)
6 4
4
size/allocated-Infos doppelt am Beginn und Ende des
Nutzdaten-Blocks. Liste kann vorwärts und rückwärts schnell
durchlaufen werden.
schnelles Verschmelzen benachbarter freier Blöcke
1128
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Linux: Speicherlayout
FF
Stack

C0
BF
Upper
2 hex
digits of
address
Stack


Dynamically allocated storage
When call malloc, calloc, new
DLLs
80
7F
Red Hat
v. 6.2
~1920MB
memory
limit
40
Heap
Dynamically Linked Libraries
Library routines (e.g., printf, malloc)

Linked into object code when first executed
Data
DLLs
Heap
08
00


3F
N. Hendrich
Runtime stack (8MB limit)
Heap
Data
Text


Statically allocated data
E.g., arrays & strings declared in code
Text


Executable machine instructions
Read-only
1129
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Linux: Speicherverwaltung
Initially
BF
Stack
80
7F
Some
Heap
Linked
BF
Stack
80
7F
BF
Stack
80
7F
More
Heap
BF
Stack
80
7F
Heap
Heap
40
3F
08
00
N. Hendrich
40
3F
Data
Text
08
00
DLLs
Data
Text
40
3F
08
00
DLLs
Data
Text
40
3F
08
00
DLLs
Heap
Data
Text
1130
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Linux: Beispiel für Text und Stack
Initially
BF
(gdb) break main
(gdb) run
Breakpoint 1, 0x804856f in main ()
(gdb) print $esp
$3 = (void *) 0xbffffc78
Stack
80
7F
Main

Address 0x804856f should be read
0x0804856f
40
3F
Stack

N. Hendrich
Address 0xbffffc78
08
00
Data
Text
1131
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Beispiel für Malloc
char big_array[1<<24]; /* 16 MB */
char huge_array[1<<28]; /* 256 MB */
int beyond;
char *p1, *p2, *p3, *p4;
int useless() {
int
{
p1
p2
p3
p4
/*
}
N. Hendrich
return 0; }
main()
= malloc(1
= malloc(1
= malloc(1
= malloc(1
Some print
<<28); /*
<< 8); /*
<<28); /*
<< 8); /*
statements
256
256
256
256
...
MB
B
MB
B
*/
*/
*/
*/
*/
1132
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.6 Assembler-Programmierung - Dynamische Speicherverwaltung
64-040 Rechnerstrukturen
Beispiel: Speicherbereiche
BF
$esp
p3
p1
Final malloc
p4
p2
beyond
big_array
huge_array
main()
useless()
Initial malloc
N. Hendrich
0xbffffc78
0x500b5008
0x400b4008
0x40006240
0x1904a640
0x1904a538
0x1904a524
0x1804a520
0x0804a510
0x0804856f
0x08048560
0x08048454
Stack
80
7F
Heap
40
3F
08
00
DLLs
Heap
Data
Text
1133
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Gruselkabinett: Memory-related Bugs
I
ungültige Pointer dereferenzieren
I
nicht existierende Variablen referenzieren
I
nicht-initialisierten Speicher lesen
I
Speicherbereiche überschreiben
I
freie Blöcke referenzieren
I
Blöcke mehrfach freigeben
I
Blöcke nicht freigeben: Speicherlecks
I
Details: Bryant, O’Hallaron [BO14]
I
Java: die meisten (dieser) Fehler sind unmöglich
N. Hendrich
1134
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Ungültige Pointer dereferenzieren
I
der „klassische“ scanf-Bug
scanf(“%d”, val);
I
lokale Variablen „verschwinden“ nach dem Rücksprung:
int *foo () {
int val;
return &val;
}
I
N. Hendrich
tückisch: direkt nach dem Rücksprung liegen die Daten noch
auf dem Stack, werden aber von späteren Funktionsaufrufen
überschrieben
1135
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Nicht initialisierten Speicher lesen
I
per malloc allozierter Speicher ist nicht initialisiert
/* return y = Ax */
int *matvec(int **A, int *x) {
int *y = malloc(N*sizeof(int));
int i, j;
for (i=0; i<N; i++)
for (j=0; j<N; j++)
y[i] += A[i][j]*x[j];
return y;
}
⇒ calloc aufrufen oder Bereich explizit initialisieren
N. Hendrich
1136
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Speicherbereiche überschreiben
I
versehentlich falsche Größe beim malloc
int **p;
p = malloc(N*sizeof(int));
for (i=0; i<N; i++) {
p[i] = malloc(M*sizeof(int));
}
I
off-by-one Fehler
int **p;
p = malloc(N*sizeof(int *));
for (i=0; i<=N; i++) {
p[i] = malloc(M*sizeof(int));
}
N. Hendrich
1137
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Speicherbereiche überschreiben (cont.)
I
Maximalgröße von Puffern nicht beachtet
char s[8];
int i;
gets(s);
/* reads “123456789” from stdin */
sehr häufiger Fehler, Einfallstor für Schadsoftware
I
Missverständnis der Pointerarithmetik
int *search(int *p, int val) {
while (*p && *p != val)
p += sizeof(int);
return p;
}
N. Hendrich
1138
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Speicherbereiche mehrfach freigeben
x = malloc(N*sizeof(int));
<manipulate x>
free(x);
y = malloc(M*sizeof(int));
<manipulate y>
free(x);
x = malloc(N*sizeof(int));
<manipulate x>
free(x);
...
y = malloc(M*sizeof(int));
for (i=0; i<M; i++)
y[i] = x[i]++;
N. Hendrich
1139
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Speicherlecks
I
Speicherbereiche nicht freigeben
foo() {
int *x = malloc(N*sizeof(int));
...
return;
}
I
N. Hendrich
nach dem Rücksprung bleibt der Speicher belegt,
aber es gibt keinen (gültigen) Pointer mehr
1140
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Speicherlecks (cont.)
I
Speicherbereiche nur teilweise freigeben
struct list {
int val;
struct list *next;
};
foo() {
struct list *head =
malloc(sizeof(struct list));
head->val = 0;
head->next = NULL;
<create and manipulate the rest of the list>
...
free(head);
return;
}
N. Hendrich
1141
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
gets aus Standard C Library
I
Puffer wird übergeben, aber Anzahl der gelesenen Zeichen
ist nicht limitiert
/* Get string from stdin */
char *gets(char *dest)
{
int c = getc();
char *p = dest;
while (c != EOF && c != '\n') {
*p++ = c;
c = getc();
}
*p = '\0';
return dest;
}
N. Hendrich
1142
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Verwundbarer Code
I
Puffer liegt auf dem Stack, ist viel zu klein
/* Echo Line */
void echo()
{
char buf[4];
gets(buf);
puts(buf);
}
/* Way too small! */
int main()
{
printf("Type a string:");
echo();
return 0;
}
N. Hendrich
1143
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Verwundbarer Code (cont.)
I
Verhalten
unix>./bufdemo
Type a string:123
123
unix>./bufdemo
Type a string:12345
Segmentation Fault
unix>./bufdemo
Type a string:12345678
Segmentation Fault
⇒ Array überschreibt den Stack
N. Hendrich
1144
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Verwundbarer Code: Stack
Stack
Frame
for main
Return Address
Saved %ebp
%ebp
[3][2][1][0] buf
Stack
Frame
for echo
N. Hendrich
/* Echo Line */
void echo()
{
char buf[4];
gets(buf);
puts(buf);
}
echo:
pushl %ebp
movl %esp,%ebp
subl $20,%esp
pushl %ebx
addl $-12,%esp
leal -4(%ebp),%ebx
pushl %ebx
call gets
. . .
/* Way too small! */
# Save %ebp on stack
#
#
#
#
#
#
Allocate space on stack
Save %ebx
Allocate space on stack
Compute buf as %ebp-4
Push buf on stack
Call gets
1145
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
unix> gdb bufdemo
(gdb) break echo
Breakpoint 1 at 0x8048583
(gdb) run
Breakpoint 1, 0x8048583 in echo ()
(gdb) print /x *(unsigned *)$ebp
$1 = 0xbffff8f8
(gdb) print /x *((unsigned *)$ebp + 1)
$3 = 0x804864d
Stack
Frame
for main
Return Address
Saved %ebp
%ebp
[3][2][1][0] buf
Stack
Frame
for echo
Stack
Frame
for main
Before call to gets
08 04 86 4d
bf ff f8 f8 0xbffff8d8
xx xx xx xx buf
Stack
Frame
for echo
8048648: call 804857c <echo>
804864d: mov 0xffffffe8(%ebp),%ebx # Return Point
N. Hendrich
1146
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Beispiele – Eingabe "123"
alles OK
Before call to gets
Stack
Frame
for main
Return Address
Saved %ebp
%ebp
[3][2][1][0] buf
Stack
Frame
for echo
N. Hendrich
Input = “123”
Stack
Frame
for main
08 04 86 4d
bf ff f8 f8 0xbffff8d8
00 33 32 31 buf
Stack
Frame
for echo
1147
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Beispiele – Eingabe "12345"
Array überschreibt den Stack
Stack
Frame
for main
Stack
Frame
for main
Return Address
Saved %ebp
%ebp
[3][2][1][0] buf
Stack
Frame
for echo
8048592:
8048593:
8048598:
804859b:
804859d:
804859e:
N. Hendrich
08 04 86 4d
bf ff 00 35 0xbffff8d8
34 33 32 31 buf
Stack
Frame
for echo
echo code:
push
call
mov
mov
pop
ret
Input = “12345”
Saved value of %ebp set
to 0xbfff0035
Bad news when later
attempt to restore %ebp
%ebx
80483e4 <_init+0x50> # gets
0xffffffe8(%ebp),%ebx
%ebp,%esp
%ebp
# %ebp gets set to invalid value
1148
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Beispiele – Eingabe "12345678"
Return Adresse überschrieben
Stack
Frame
for main
Return Address
Saved %ebp
%ebp
[3][2][1][0] buf
Stack
Frame
for echo
Stack
Frame
for main
Input = “12345678”
08 04 86 00
38 37 36 35 0xbffff8d8
34 33 32 31 buf
Stack
Frame
for echo
Invalid address
%ebp and return
address corrupted
No longer pointing to
desired return point
8048648: call 804857c <echo>
804864d: mov 0xffffffe8(%ebp),%ebx # Return Point
N. Hendrich
1149
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Beispiele – Eingabe "12345678" (cont.)
Return Adresse überschrieben
⇒ Rücksprung in Schad-Code
return
address
A
void foo(){
bar();
...
}
void bar() {
char buf[64];
gets(buf);
...
}
N. Hendrich
Stack
after call to gets()
foo stack frame
data
written
by
gets()
B
B
pad
exploit
code
bar stack frame
1150
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Puffer-Überläufe: Sicherheitslücken
I
I
Buffer-Overflow Bugs erlauben es Angreifern, beliebigen Code
auf den angegriffenen Rechnern auszuführen!
der Code wird vom Angreifer mitgeliefert
GET
/default.ida?NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN....NNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN%u9090%u6858%ucbd3%u780
1%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090%u909
0%u8190%u00c3%u0003%u8b00%u531b%u53ff%u0078%u0000%u00=a
HTTP/1.0" 400 325 "-" "-"
⇒ sorgfältig programmieren
⇒ verwundbare Bibliotheksfunktionen vermeiden
N. Hendrich
1151
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.7 Assembler-Programmierung - Puffer-Überläufe
64-040 Rechnerstrukturen
Assemblerebene – Zusammenfassung
I
Umsetzung von Programmen mit Kontrollstrukturen
I
Funktionsaufrufe, Parameter, lokale Variablen
I
Speicherlayout von strukturierten Daten und Arrays
I
Umsetzung objektorienter Konzepte
I
ELF-Dateiformat und statisches Linking
I
Programmcode, Stack, Heap, statische Variablen
I
Funktionsbibliotheken
I
Dynamische Speicherverwaltung im Heap
I
Puffer-Überläufe
N. Hendrich
1152
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.8 Assembler-Programmierung - Literatur
64-040 Rechnerstrukturen
Literatur
[BO14] R.E. Bryant, D.R. O’Hallaron:
Computer systems – A programmers perspective.
2nd new intl. ed., Pearson Education Ltd., 2014.
ISBN 978–1–292–02584–1. csapp.cs.cmu.edu
[TA14] A.S. Tanenbaum, T. Austin: Rechnerarchitektur –
Von der digitalen Logik zum Parallelrechner.
6. Auflage, Pearson Deutschland GmbH, 2014.
ISBN 978–3–86894–238–5
N. Hendrich
1153
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.8 Assembler-Programmierung - Literatur
64-040 Rechnerstrukturen
Literatur (cont.)
[PH14] D.A. Patterson, J.L. Hennessy: Computer Organization
and Design – The Hardware/Software Interface.
5th edition, Morgan Kaufmann Publishers Inc., 2014.
ISBN 978–0–12–407726–3
[PH11] D.A. Patterson, J.L. Hennessy: Rechnerorganisation
und -entwurf – Die Hardware/Software-Schnittstelle.
4. Auflage, Oldenbourg, 2011. ISBN 978–3–486–59190–3
[Hyd10] R. Hyde: The Art of Assembly Language Programming.
2nd edition, No Starch Press, 2010. ISBN 978–1–59327–207–4.
www.plantation-productions.com/Webster/www.artofasm.com
N. Hendrich
1154
MIN-Fakultät
Fachbereich Informatik
Universität Hamburg
13.8 Assembler-Programmierung - Literatur
64-040 Rechnerstrukturen
Literatur (cont.)
[IA64] Intel 64 and IA-32 Architectures Software Developer’s
Manual – Volume 1: Basic Architecture.
Intel Corp.; Santa Clara, CA.
www.intel.de/content/www/de/de/processors/
architectures-software-developer-manuals.html
N. Hendrich
1155
Herunterladen