Variablen und eingebaute Datentypen

Wie jede normale Programmiersprache verfügt auch Assembler über die Möglichkeit, Variablen unterschiedlichen Typs zu deklarieren. Das geht sogar so weit, daß man sich selbst Datentypen bauen kann (wie z. B. struct in C oder der Record in Pascal), um dann Variablen dieses Typs anzulegen.
Dieses Kapitel zeigt Ihnen, wie Sie mit Assembler Variablen verwenden.

TASM verfügt über die folgenden eingebauten Datentypen:

Datentypen
TASM-Bezeichnung ausgesprochen Größe in Bits Wertebereich mit/ohne Vorzeichen
DB Byte/Char 8 -128 bis +127 / 0 bis 255
DW Word 16 -32768 bis +32767 / 0 bis 65535
DD DoubleWord 32 -2.147.483.648 bis +2.147.483.647 / 0 bis 4.294.967.295
DQ QuadWord 64 -2^63 bis +2^63-1 / 0 bis 2^64-1
DP / DF FarPointer 48 -2^47 bis +2^47-1 / 0 bis 2^48-1
TByte TenByte 80 -2^79 bis +2^79-1 / 0 bis 2^80-1
packed BCD gepackte BCD 80 0 bis 99.999.999.999.999.999.999

Üblicherweise wird ein FarPointer für das verwendet, wovon er seinen Namen hat - als Adresszeiger. Aus diesem Grunde gilt in aller Regel eine vorzeichenlose Interpretation als Adresse.
Die Bezeichnung TenByte ist von mir erfunden - ein TByte ist normalerweise immer nur ein TByte.
Die gepackte BCD ist lediglich eine andere Interpretation eines TByte. Die beiden Datentypen spielen beim mathematischen Koprozessor eine Rolle.
Wie immer spielt Groß/Kleinschreibung keine Rolle.

Variablendeklaration

Wie schon in Kapitel über die Register besprochen, belegen Code, Daten und Stack eigene Segmente. Demzufolge müssen wir unsere Variablen (Daten) in ein Datensegment schreiben. Wie wird jetzt ein Datensegment angelegt? Ganz einfach: mit der Anweisung DATASEG (.DATA im MASM-Mode) (vergleichbar mit VAR in PASCAL). Alles, was hinter dieser Anweisung steht, wird als Datenvereinbarung betrachtet, solange, bis ein anderes Segment angelegt wird (z. B. für Code).

Die allgemeine Form einer Variablendeklaration sieht in Assembler so aus:
[VarName] Datentyp {[count dup] (? | Vorbelegung)}
Dröseln wir diese allgemeine Form auseinander:
Wie Sie sehen, ist der Variablenname optional, was bei mehrzeiligen Deklarationen ganz nützlich ist. Zudem können Sie auf diese Weise auch Daten ins Codesegment schreiben, beispielsweise einen Befehl, den ihr Assemblierer noch nicht kennt.
Der Datentyp ist z. B. eine der kurzen Buchstabenfolgen aus obiger Tabelle, also DB, DW usw.
In Assembler haben Sie die Möglichkeit, Variablen sofort bei ihrer Deklaration zu initialisieren (Zahlenwerte können in allen möglichen Zahlensystemen angegeben werden). Dies wird durch den Teil geregelt, der in geschweiften Klammern steht.
Möchten Sie die Variable unitialisiert belassen, dann muß nach dem Datentyp ein Fragezeichen stehen, also zum Beispiel.
MyVar db ?
Wird das Programm später gestartet, erhält MyVar den Wert, der gerade an der Stelle im Speicher steht, an die MyVar geladen wird.
Um MyVar gleich mit dem ASCII-Wert des Zeichens 'A' (65) zu initialisieren, ist folgender Code nötig:
MyVar db 65
oder
MyVar db 'A'
Diese Doppelinitialisierung mit Zeichen funktioniert allerdings nur beim Datentyp DB. Zum zweiten wird hier gezeigt, daß der Assemblierer keinen Unterschied zwischen Zahlenwerten im Byte-Bereich und deren Repräsentation als Zeichen macht.
Man kann bei einer Deklaration auch gleich mehrere Initialwerte angeben, beispielsweise:
MyVar db 65,115,115,101,109,98,108,101,114
oder
MyVar db 'Assembler'
oder
MyVar db 'A','s','s','e','m','b','l',101,114
oder
MyVar dw 45665,12315,6215,7801,43109,48
Um noch eine mehrzeilige Deklaration zu zeigen:
MyVar dw 45665
      dw 12315
      dw 6215
      dw 7801
      dw 43109
      dw 48
Über den Variablennamen wird dann jeweils das erste Element der Wertefolge angesprochen. Diese Konstrukte sind also mit einem Array vergleichbar.
Wie Sie sehen können, ist auch eine Mischinitialisierung möglich (Zeichen und Zahlen).
Um nun eine Reihe von Daten mit dem gleichen Wert zu initialisieren, gibt es folgendes beispielhaftes Konstrukt:
MyVar db 12 dup (?)
oder
MyVar db 24 dup ('m')
Es wird also ein 12 bzw 24 Byte großer Speicherbereich angelegt, der über den Namen MyVar angesprochen werden kann und entweder komplett uninitialisiert ist oder komplett aus dem Buchstaben 'm' besteht.

Zugriff auf die Variablen

Um innerhalb des Programmcodes auf den Variableninhalt zugreifen zu können, ist es nötig, den Variablennamen in eckige Klammern einzuschließen. Dies ist eine Eigenheit des IDEAL-Mode, die in meinen Augen die Lesbarkeit des Quelltextes erhöht. Beispielsweise wird so die Verwechselung mit Konstanten vermieden.
Beispiel:

mov [MyVar],'E'
Im MASM-Mode ist dies zwar auch möglich, hier hätte allerdings auch ein
mov MyVar,'E'
genügt, was im IDEAL-Mode zumindest zu einer Warnung führt.
Ist MyVar vom Typ DB, dann wird ihr der Inhalt 'E' zugewiesen (ist MyVar eine Zeichenkette, dann wird der erste Buchstabe verändert).
Ist MyVar nicht vom Typ DB (sondern vielleicht DW), dann gibt es eine Fehlermeldung. In diesem Fall müssten Sie den neuen Inhalt 'casten', also eine Datentypumwandlung vornehmen, doch dazu später mehr.

Geltungsbereich von Variablen

Variablen im Datensegment sind für das gesamte Programm verfügbar und können an jeder Stelle verwendet werden (mit Programm ist hier die gesamte Quelldatei mit allen über INCLUDE eingebundenen Dateien gemeint).
Um eine Variable für andere Programme verfügbar zu machen, ist eine zusätzliche Angabe notwendig

DATASEG
	msg db 20 dup(?)
        PUBLIC msg

Damit ein anderes Programm auf diese Variable zugreifen kann, ist in diesem Programm folgende Abgabe notwendig:

DATASEG
        EXTRN msg:byte

Zusätzlich zu PUBLIC und EXTRN gibt es noch die Direktive GLOBAL:

DATASEG
        GLOBAL msg:byte anz:word
        anz dw 800

GLOBAL arbeitet so, dass alles, was im gleichen Modul definiert ist, als PUBLIC gesetzt wird, alles, was nicht im gleichen Modul definiert ist, wird als EXTRN behandelt