Assembler-Direktiven, bedingte Assemblierung und Pseudo-Instruktionen

   END    ORG    $INCLUDE    DB und DW    DATA und BIT    EQU oder SET    IF und IFDEF
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.

zurück zum Anfang
Seite zurück Startseite
Erik Buchmann
EMail an: Owner@ErikBuchmann.de