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