Assembler - Variablen Dr.-Ing. Volkmar Sieh Department Informatik 3: Rechnerarchitektur Friedrich-Alexander-Universität Erlangen-Nürnberg SS 2008 Assembler - Variablen 1/30 2008-04-21
Variablen Variablen haben Namen, Typ und Geltungsbereich Name: Typ: für den Programmierer hilfreich; für die Semantik ohne Bedeutung (Umbenennung wäre möglich; z.b. var0, var1,...) 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
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;....... } } } } 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) { bit32 func(bit32 x) { int y; bit32 y; y = 10 * sin(x); return y; } } int(y) = 10 * sin(float(x)); return int(y); Assembler - Variablen 4/30 2008-04-21
Variablen 3. Vereinfachung: Geltungsbereiche auflösen: int global; static int module; int global; int module; int parameter; int func_auto; int func_static; int block_local; int for_local; void func(int parameter) { void func() { int func_auto; static int func_static; { int block_local; for (int for_local = 0;...) for (for_local =...... } } } Assembler - Variablen 5/30 2008-04-21
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
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}; 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): 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) Assembler - Variablen 9/30 2008-04-21
Variablen Vordefinierte Standard-Typen in C/C++ (#include <inttypes.h>): int8_t, uint8_t 1 Byte int16_t, uint16_t 2 Byte int32_t, uint32_t 4 Byte int64_t, uint64_t 8 Byte intptr_t 2/4/8 Byte (je nach CPU) Vordefinierte Standard-Typen in Java: byte 1 Byte short 2 Byte int 4 Byte long 8 Byte Assembler - Variablen 10/30 2008-04-21
Variablen - Adressen Endergebnis: Zum Speichern und Wiedergeben von Variablen reichen sowie eine eindeutige Zahl als Bezeichner / Adresse 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 Assembler - Variablen 12/30 2008-04-21
Variablen - Adressen Assembler - Variablen 13/30 2008-04-21
Variablen - Symbolische Adressen len EQU 15 from EQU 16 to EQU 32 LDA #16 LDA #16 STA 15 STA len LDX 15 LDX len DECX DECX LDA 16,X LDA from,x STA 32,X STA to,x DECX DECX BPL... BPL... Assembler - Variablen 14/30 2008-04-21
Variablen - Symbolische Adressen x EQU 192 ; int8_t-variable x hat Adresse 192 y EQU 193 ; int16_t-variable y hat Adresse 193 z EQU 195 ; int32_t-variable z hat Adresse 195 p EQU 199 ; Pointer-Variable p hat Adresse 199 array EQU 201 ; 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 : ORG 192 ; Startadresse der Variablen x RMB 1 y RMB 2 z RMB 4 p RMB 2 array RMB 20 Assembler - Variablen 15/30 2008-04-21
Variablen - Symbolische Adressen Schreibweise i80x86-gnu-assembler:.data /* Datensegment */ x:.global x /* globale int8_t-variable x */.zero 1 y: /* lokale int16_t-variable y */.zero 2 z:.global z /* globale int32_t-variable z */.zero 4 p: /* lokale Pointer-Variable p */.zero 4 array: /* lokale Array-Variable array */.zero 20 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
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 f2[10 * 5]; int i; int i; int j; int j;... = f1[i][j];... = f2[i * 5 + j]; Assembler - Variablen 18/30 2008-04-21
Variablen - Strukuren C-Struktur struct { int8_t c; /* 1 Byte */ int16_t i; /* 2 Bytes */ double f; /* 8 Bytes */ } x; Abbildung auf Speicher Adresse Inhalt N + 0 x.c N + 1 x.i (erstes Byte) N + 2 x.i (zweites Byte) N + 3 x.f (erstes Byte)...... N + 10 x.f (achtes Byte) Assembler - Variablen 19/30 2008-04-21
Variablen - Strukuren C-Struktur struct { int8_t c; /* 1 Byte */ int16_t i; /* 2 Bytes */ double f; /* 8 Bytes */ } x; GNU-Assembler für i80x86:.data.data x:.global x x.c:.global x.c.zero 11.zero 1 x.i:.global x.i.zero 2 x.f:.global x.f.zero 8 Assembler - Variablen 20/30 2008-04-21
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. 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 */ 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 Assembler - Variablen 23/30 2008-04-21
Variablen - Register Register bieten gleiche Funktionalität wie Hauptspeicher: Speichern von Werten in durchnummerierten Registern 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 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) Assembler - Variablen 26/30 2008-04-21
Variablen - Register Register der i80386-cpu: 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) 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 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 16 # Kop. Byte-Wert im Akku nach Adresse 16 lda 4 # Kop. Byte-Wert von Adresse 4 nach Akku ldx 7 # Kop. Byte-Wert von Adresse 7 ins Index-Reg. stx 9 # Kop. Byte-Wert vom Index-Reg. nach Adresse 9 Assembler - Variablen 30/30 2008-04-21