|
Diese Seite ist mit Vorsicht zu genießen: Assemblerdirektiven
sind im höchsten Maße abhängig vom verwendeten Assembler, da sie
Einfluss auf die Assemblierung selbst nehmen. Dennoch sind
Assemblerdirektiven ein mächtiges und elegantes Werkzeug, sei es
um den Quellcode zu strukturieren oder leicht an veränderliche
Hardware anzupassen.
|
Vorbemerkungen
|
|
Wie schon Eingangs erwähnt sind diese Assembler - Anweisungen nicht
Bestandteil des Instruction Set des MCS-51 Prozessors, sondern des
Assemblers. Sie legen fest, auf welche Weise etwas assembliert wird,
nicht das Programm selbst! Viele dieser Controls haben
einen fast kosmetischen Charakter. Dennoch
|
sollten sie möglichst
oft eingesetzt werden, da sie den Quellcode zu strukturieren helfen.
Auf dieser Seite wird nicht auf alle, sondern nur auf die wichtigsten
Assemblerdirektiven des ASEM-51 eingegangen. Die meisten dieser Anweisungen
werden in der gleichen oder zumindest ähnlichen Form auch von
anderen Assemblern unterstützt.
|
END
|
|
Die sicherlich leichteste Assemblerdirektive ist END. Sie besagt
nichts anderes, als dass an genau dieser Stelle der Quelltext zu
Ende ist. END muss in jedem Assemblerprogramm genau einmal vorkommen.
Anderenfalls gibt es Fehlermeldungen vom Assembler.
Syntax: END
|
ORG
|
|
ORG dient dazu, die genaue Position festzulegen, an der
die auf diese Anweisung folgenden Instruktionen in das
ROM oder Flash-ROM des Controllers geschrieben werden sollen.
Dies ist dann erforderlich, wenn per indirekter Adressierung auf
festgelegte Programmspeicher-Adressen zugegriffen werden soll
oder bestimmte Adressen im Controller 'hart' verdrahtet sind.
Beispielsweise wird die ORG-Anweisung benötigt, um
die Einsprungadressen der Interrupts mit dem Programmcode
zu verknüpfen.
Es ist Aufgabe des Programmierers, dafür zu sorgen, dass
der Assembler die ORG-Anweisungen auch umsetzen kann. Werden
diese Anweisungen an Stellen im Code eingebracht, die schon hinter den
angegebenen Adressen liegen - beispielsweise ORG 0h
mittem im Quellcode und nicht an erster Stelle - so werden sie ignoriert.
Syntax: ORG Adresse
|
ORG 003h
; Ext. Int 0
reti
ORG 00Bh
; Timer 0
reti
ORG 013h
; Ext. Int 1
reti
ORG 01Bh
; Timer 1
reti
ORG 01Bh
; serial Int
reti
|
$INCLUDE
|
|
Die $INCLUDE-Anweisung dient dazu, Textdateien
an der Stelle der Include-Anweisung einzubinden. Dies geschieht völlig
unabhängig vom Inhalt der Dateien, und ist für den Assembliervorgang
vollständig transparent - dem Assembler ist es daher egal, ob Code
in der Hauptdatei steht oder aus einer anderen Datei eingebunden wurde.
Dies hat wesentliche Auswirkungen auf Symbole und Sprungmarken:
so dürfen auch in verschiedenen Dateien niemals Sprungmarken mit den
selben Namen vorhanden sein! Andersherum lassen sich auch Sprungziele
anspringen, die nicht in der Hauptdatei, sondern in einem Include
definiert sind. $INCLUDE wird zumeist eingesetzt, um wiederverwendbare
Code-Bibliotheken zu erstellen und in die Programme einzubinden.
Syntax: $INCLUDE (Dateiname)
|
; Registersatz des 89C2051
$INCLUDE (89C1051.MCU)
; Programmbibliothek
; an Stelle 30h
ORG 30h
$INCLUDE (misc.lib)
|
DB und DW
|
|
Diese Anweisungen dienen dazu, Speicherstellen
im Programmspeicherdes Controllers mit den angegebenen
Werten zu belegen. So bekommt man Datenfelder in
das ROM des Controllers, auf die mit dem MOVC-Befehl
zugegriffen werden kann. DB belegt dabei genau
ein Byte, DW ein Datenwort bzw. zwei Bytes.
Um auf solche Tabellen zugreifen zu können, muss man ihnen
eine Sprungmarke, also ein Label, davorstellen. Die Label-Adresse
bekommt man mit mov DPTR,#label in das DPTR-Register.
Syntax: db Wert1,Wert2, ... ,Wertn
Syntax: dw Wert1,Wert2, ... ,Wertn
|
Datenfeld:
db 10,20,30
db 255
db 1,'Testtext',0
dw 10,20,30,10000
dw 0C800h
getDataFromAccPos:
mov DPTR,#Datenfeld
movc a,@A+DPTR
ret
|
DATA und BIT
|
|
Wo DB und DW Daten im Programmspeicher belegen, dienen DATA und BIT
dazu, Bytes oder Bits im RAM des Controllers zu bezeichnen.
Die solchermaßen mit einem Namen versehenen Bits und Bytes lassen sich
ebenso verwenden wie Variablen. Auch die Register in der SFR wie PCON,
IE oder SP werden mit diesen Assemblerdirektiven benannt. Das
nebenstehende Beispiel ist ein Ausschnitt aus der mit $INCLUDE
eingebundenen 89C1051.MCU.
Syntax: Bezeichner DATA Adresse
Syntax: Bezeichner BIT Adresse
|
; Registerdefinition
SP DATA 081H
DPL DATA 082H
DPH DATA 083H
PCON DATA 087H
TCON DATA 088H
TMOD DATA 089H
; ...
AIN0 BIT 090H
AIN1 BIT 091H
RI BIT 098H
TI BIT 099H
RB8 BIT 09AH
TB8 BIT 09BH
; ...
|
EQU oder SET
|
|
EQU und SET sind in jeder Hinsicht identisch und dienen beide dazu,
einem Bezeichner einen Wert zuzuordnen. Diese Werte lassen sich dann im
Programmcode wie Konstanten einsetzen.
Mit diesen Konstanten kann man beispielsweise den Quellcode zentral
konfigurieren und sogar rechnen.
Syntax: Bezeichner EQU Wert
Syntax: Bezeichner SET Wert
|
; Konfigurieren
Timer_High EQU 227
Timer_Low EQU 123
Laenge EQU 10
; Quellcode-Ausschnitt
mov TH0,#Timer_High
mov TL0,#Timer_Low
mov R0, #Feld+Laenge
|
IF und IFDEF
|
|
IF, IFDEF oder IFNDEF sind Befehle zur bedingten Assemblierung. Dies
bedeutet, dass der Assemblercode zwischen IF[[N]DEF] und ENDIF nur dann
assembliert wird, wenn die IF-Bedingung wahr ist.
Bei IF ist die
Bedingung ein logischer Ausdruck, beispielsweise
IF Jahr=2001, wenn dem Bezeichner 'Jahr' vorher mit
SET oder EQU ein Wert zugewiesen wurde.
Die Bedingung bei IFDEF oder IFNDEF ist, ob der dahinter angegebene
Bezeichner definiert oder nicht definiert ist. Damit ist IFDEF ideal, um
beispielsweise Debugging-Code einzubauen, der im fertigen Code leicht zu
aktivieren oder zu deaktivieren ist.
Jeder IF-Block muss
mit einem ENDIF abgeschlossen sein.
Syntax:
IF Ausdruck
IFDEF Bezeichner
IFNDEF Bezeichner
ELSE
ENDIF
|
; Konfigurieren
Debug EQU 1
Baud EQU 1200
; Quellcode-Ausschnitt
IF Baud=600
Load EQU 152
ENDIF
IF Baud=1200
Load EQU 204
ENDIF
IF Baud=2400
Load EQU 230
ENDIF
mov TH1,#Load
mov TL1,#Load
IFDEF Debug
mov a,#123
call debug_function
ELSE
mov a,#213
call final_function
ENDIF
|
|
Dies war nur ein kleiner Teil der Vielzahl möglichen Assemblerdirektiven
des ASEM-51 - jedoch meiner Meinung nach der wesentliche. Was ich
verschwiegen habe, sind hauptsächlich Befehle zur Einstellung
der Segmenttypen und zur
Formatierung der vom Assembler erzeugten Listen und Logfiles.
|