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