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 ): 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; /*