Assembler - Variablen
Transcription
Assembler - Variablen
Assembler - Variablen Dr.-Ing. Volkmar Sieh Department Informatik 3: Rechnerarchitektur Friedrich-Alexander-Universität Erlangen-Nürnberg SS 2008 logo Assembler - Variablen– 1/30– 2008-04-21 Variablen Variablen haben Namen, Typ und Geltungsbereich Name: für den Programmierer hilfreich; für die Semantik ohne Bedeutung (Umbenennung wäre möglich; z.B. var0, var1, ...) Typ: definiert mögliche Inhalte und Größe (z.B. 8-Bit-Zeichen, 32-Bit-Int-Zahlen) definiert mögliche Operationen (Vergleiche, „+”, „-”, ...) Geltungsbereich: für den Programmierer hilfreich; für die Semantik ohne Bedeutung (Ausnahme: Rekursion (später); alle Variablen könnten ansonsten global sein) Assembler - Variablen– 2/30– 2008-04-21 logo Variablen 1. Vereinfachung: Namen durch Nummern ersetzen: int global; int var0; static int module; static int var1; void func(int parameter) { void func(int var2) { int func_auto; int var3; static int func_static; static int var4; { { int block_local; int var5; for (int for_l = 0; ...) for (int var6 = 0; . ... ... } } } } logo Assembler - Variablen– 3/30– 2008-04-21 Variablen 2. Vereinfachung: Typ durch „generischen” Typ (Sequenz von Bits) ersetzen (Beispiel: soll nur die Idee vermitteln; funktioniert in Hochsprache so nicht!): int func(float x) { int y; bit32 func(bit32 x) { bit32 y; y = 10 * sin(x); return y; } int(y) = 10 * sin(float(x)); return int(y); } logo Assembler - Variablen– 4/30– 2008-04-21 Variablen 3. Vereinfachung: Geltungsbereiche auflösen: int global; static int module; void func(int parameter) { int func_auto; static int func_static; { int block_local; for (int for_local = 0; ...) ... } } Assembler - Variablen– 5/30– 2008-04-21 int global; int module; int parameter; int func_auto; int func_static; int block_local; int for_local; void func() { for (for_local = ... } logo Variablen 4. Vereinfachung: Man verwendet immer Variablen fester Länge (vielfach 8-Bit-Elemente „Bytes”). Variablen mit weniger Bits (z.B. vom Typ boolean) verschenken Speicherplatz Variablen mit vielen Bits (z.B. 32-Bit-Integer-Variablen) werden auf mehrere Teil-Variablen aufgeteilt. Teil-Variablen bekommen aufeinander folgende Nummern. ggf. Aufteilen beim Schreiben, Zusammenfügen beim Lesen Beispiel: 32-Bit-Integer-Variable wird aufgeteilt in 4-Byte-Variablen: 10001011011100100110011001100111 <=> 10001011-01110010-01100110-01100111 Assembler - Variablen– 6/30– 2008-04-21 logo Variablen 4. Vereinfachung: „große” Variablen durch Seqenzen von „kleinen” ersetzen (Beispiel: soll nur die Idee vermitteln; funktioniert in Hochsprache so nicht!): int func(short int x) { int func(bit8 x0, x1) { int y; bit8 y0, y1, y2, y3; y = 10 * x; return y; } {y0,y1,y2,y3} = 10 * {x0,x1}; return {y0,y1,y2,y3}; } logo Assembler - Variablen– 7/30– 2008-04-21 Byte-Order Frage: Welche Bits werden im ersten, zweiten, usw. Byte gespeichert (Byte-Order)? Big-Endian (Most Significant Byte First, Network-Byte-Order): Little-Endian (Least Significant Byte First): logo Assembler - Variablen– 8/30– 2008-04-21 Variablen Größen verschiedener Datentypen (typische Werte für C, C++, Java, Pascal): Character 1 Byte (z.T. 2 bzw. 4 Bytes) Short Integer 2 Byte Integer 4 Byte (z.T. 2 Bytes) Long Integer 4 Byte (z.T. 8 Bytes) Long Long Integer 8 Byte Single Precision Float 4 Byte Double Precision Float 8 Byte Pointer 4 Byte (z.T. 2 bzw. 8 Bytes) logo Assembler - Variablen– 9/30– 2008-04-21 Variablen Vordefinierte Standard-Typen in C/C++ (#include <inttypes.h>): int8_t, uint8_t int16_t, uint16_t int32_t, uint32_t int64_t, uint64_t intptr_t 1 Byte 2 Byte 4 Byte 8 Byte 2/4/8 Byte (je nach CPU) Vordefinierte Standard-Typen in Java: byte short int long 1 2 4 8 Byte Byte Byte Byte logo Assembler - Variablen– 10/30– 2008-04-21 Variablen - Adressen Endergebnis: Zum Speichern und Wiedergeben von Variablen reichen eine eindeutige Zahl als „Bezeichner”/„Adresse” sowie logo die Kenntnis der Byte-Order! Assembler - Variablen– 11/30– 2008-04-21 Variablen - Speicher Hauptspeicher bietet genau diese Funktionalität: Speichern von Werten in durchnummerierten Speicherzellen logo Assembler - Variablen– 12/30– 2008-04-21 Variablen - Adressen logo Assembler - Variablen– 13/30– 2008-04-21 Variablen - Symbolische Adressen len from to LDA #16 STA 15 LDX 15 DECX LDA 16,X STA 32,X DECX BPL ... EQU 15 EQU 16 EQU 32 LDA #16 STA len LDX len DECX LDA from,X STA to,X DECX BPL ... logo Assembler - Variablen– 14/30– 2008-04-21 Variablen - Symbolische Adressen x y z p array EQU EQU EQU EQU EQU 192 193 195 199 201 ; ; ; ; ; int8_t-Variable x hat Adresse 192 int16_t-Variable y hat Adresse 193 int32_t-Variable z hat Adresse 195 Pointer-Variable p hat Adresse 199 Array array hat Adresse 201 nachträgliches Einfügen oder Löschen von Variablen mühsam und sehr fehleranfällig äquivalente Schreibweise mit „Pseudo-Operationen”: x y z p array ORG RMB RMB RMB RMB RMB 192 ; Startadresse der Variablen 1 2 4 2 20 Assembler - Variablen– 15/30– 2008-04-21 logo Variablen - Symbolische Adressen Schreibweise i80x86-GNU-Assembler: x: .data .global x .zero 1 y: z: /* Datensegment */ /* globale int8_t-Variable x */ /* lokale int16_t-Variable y */ .zero 2 .global z .zero 4 p: /* globale int32_t-Variable z */ /* lokale Pointer-Variable p */ .zero 4 array: /* lokale Array-Variable array */ .zero 20 logo Read-only-Variablen auch im Programmsegment möglich. Assembler - Variablen– 16/30– 2008-04-21 Variablen - Strukturen Moderne Programmiersprachen kennen Strukturen / Records Arrays sowie Kombinationen davon. Zur Speicherung von Variablen dieser Typen müssen mehrere (normalerweise aufeinander folgende) Speicherzellen verwendet werden. Beispiel: zur Speicherung eines Charakters benötigt man ein Byte zur Speicherung eines Arrays bestehend aus N Charakters benötigt man N Byte (die Struktur geht verloren) Assembler - Variablen– 17/30– 2008-04-21 logo Variablen - mehrdimensionale Arrays Speicher ist „eindimensionales” Array Problem: wie speichert man mehrdimensionale Arrays? Array mit N Zeilen und M Spalten enthält insgesamt N ∗ M Elemente. Diese werden von 0 bis N ∗ M − 1 durchnummeriert => eindimensionales Array. Beispiel: zweidimensionales Array eindimensionales Array int f1[10][5]; int i; int j; int f2[10 * 5]; int i; int j; ... = f1[i][j]; ... = f2[i * 5 + j]; logo Assembler - Variablen– 18/30– 2008-04-21 Variablen - Strukuren C-Struktur struct { int8_t c; int16_t i; double f; } x; /* 1 Byte */ /* 2 Bytes */ /* 8 Bytes */ Abbildung auf Speicher Adresse N +0 N +1 N +2 N +3 ... N + 10 Inhalt x.c x.i (erstes Byte) x.i (zweites Byte) x.f (erstes Byte) ... x.f (achtes Byte) Assembler - Variablen– 19/30– 2008-04-21 logo Variablen - Strukuren C-Struktur struct { int8_t c; int16_t i; double f; } x; /* 1 Byte */ /* 2 Bytes */ /* 8 Bytes */ GNU-Assembler für i80x86: x: .data .global x .zero 11 x.c: x.i: x.f: Assembler - Variablen– 20/30– 2008-04-21 .data .global x.c .zero 1 .global x.i .zero 2 .global x.f .zero 8 logo Variablen - Alignment Zugriff auf 2-Byte-Werte (bzw. 4-Byte-, 8-Byte-Werte) schneller, wenn diese an geraden (bzw. durch 4, 8 teilbaren) Adressen beginnen (manche Architekturen erfordern korrekte Startadressen – sonst „Bus Error”). => „Alignment” Erreichbar durch das (automatische) Einfügen von „Dummy”-Variablen. logo Assembler - Variablen– 21/30– 2008-04-21 Variablen - Alignment Beispiel (ohne Alignment): /* 4*N+0 */ int8_t c; /* 4*N+1 */ int16_t s; /* <- kein passendes Alignment */ Beispiel (mit Alignment): /* 4*N+0 */ int8_t c; /* 4*N+1 */ int8_t dummy; /* 4*N+2 */ int16_t s; /* <- passendes Alignment */ logo Assembler - Variablen– 22/30– 2008-04-21 Variablen - Operationen Folgende „Speicher-Operationen” stehen i.a. zur Verfügung: datum = load(address); store(address, datum); Die load- bzw. store-Funktionalität des Speichers ist auch per CPU-Operation verfügbar direkt als Teil von komplexeren CPU-Operationen logo Assembler - Variablen– 23/30– 2008-04-21 Variablen - Register Register bieten gleiche Funktionalität wie Hauptspeicher: Speichern von Werten in durchnummerierten Registern logo Assembler - Variablen– 24/30– 2008-04-21 Variablen - Register Ähnlich Speicherzellen; aber: nur wenige Register verfügbar schnellerer Zugriff => meist für temporäre Variablen (einfache Datentypen) verwendet logo Assembler - Variablen– 25/30– 2008-04-21 Variablen - Register Register der i80x86-CPU: %eax, %ebx, %ecx, %edx, %edi, %esi, %ebp, %esp (je 32 Bit) z.T. auch als %ax, %bx, %cx, %dx, %di, %si, %bp, %sp ansprechbar (je 16 Bit) z.T. auch als %ah, %bh, %ch, %dh, %al, %bl, %cl, %dl, ansprechbar (je 8 Bit) Condition-Code/Flags-Register %eflags (32 Bit) Program-Counter/Instruction-Pointer %eip (32 Bit) logo Assembler - Variablen– 26/30– 2008-04-21 Variablen - Register Register der i80386-CPU: logo Assembler - Variablen– 27/30– 2008-04-21 Variablen - Register Register des m68x05-Mikro-Controllers: Akkumulator (A) (8 Bit) Index-Register (X) (8 Bit) Stack-Pointer (5 Bit) Condition-Code/Flags-Register (5 Bit) Program-Counter/Instruction-Pointer (12 Bit) logo Assembler - Variablen– 28/30– 2008-04-21 Variablen - Speicher-/Register-Zugriffe Zugriff auf Variablen im Speicher (i80x86): 1-Byte-Werte: movb address, ...; movb ..., address 2-Byte-Werte: movw address, ...; movw ..., address 4-Byte-Werte: movl address, ...; movl ..., address Zugriff auf Variablen in Registern (i80x86): 1-Byte-Werte: movb %reg, ...; movb ..., %reg 2-Byte-Werte: movw %reg, ...; movw ..., %reg 4-Byte-Werte: movl %reg, ...; movl ..., %reg Beispiel (i80x86): movw %ax, 16 # Kop. int16_t-Wert im Reg. %ax nach Adresse 1 logo movl 4, %esp # Kop. int32_t-Wert von Adresse 4,5,6,7 nach S Assembler - Variablen– 29/30– 2008-04-21 Variablen - Speicher-/Register-Zugriffe Speicher-/Register-Transfers (m68x05): 1-Byte-Werte: LDr address; STr address 2-/4-Byte-Werte: – Beispiel (m68x05): sta lda ldx stx 16 4 7 9 # # # # Kop. Kop. Kop. Kop. Byte-Wert Byte-Wert Byte-Wert Byte-Wert im Akku nach Adresse 16 von Adresse 4 nach Akku von Adresse 7 ins Index-Reg. vom Index-Reg. nach Adresse 9 logo Assembler - Variablen– 30/30– 2008-04-21