Pfad: Home =>
AVR-Assembler gavrasm => Einführung
Hier werden die besonderen Features des gavrasm-Assemblers vorgestellt.
Die Beispiele compilieren nicht unbedingt auch auf anderen Assemblern. Im
einzelnen werden vorgestellt:
- Aufruf des Assemblers auf der Kommandozeile
- Aufruf des Assemblers mit einer Batch oder in einer Shell
- Hilfsprogramm zum Aufruf unter Windows
- Verwendung von IF-ELSE-ENDIF
- Verwendung von EXIT
- Verwendung von Makros
- Verwendung von besonderen literalen Konstanten
- Verwendung von Trennzeichen in Konstanten
Besondere Hinweise für Linux-User:
- Die Datei "gavrasm" muss das Attribut "Ausführbar"
gesetzt haben, damit sie gestartet werden kann!
- gavrasm wird nur noch in der i386-64 Version kompiliert zur Verfügung
gestellt. Wer andere Versionen benötigt, kann diese mit dem Free-Pascal-
Compiler aus den Quelldateien kompilieren!
Beim Aufruf in einer Kommandozeile geht man am besten so vor:
- Man öffnet eine Kommandozeile (Win: meistens unter
Start/Programme/Zubehör/Eingabeaufforderung) oder Shell (Linux-KDE) und wechselt
mit cd [Pfad] in das Verzeichnis mit dem Quelltext.
- Das Assemblieren wird mit [gavrasm-pfad]gavrasm -optionen quelltext[.asm]
gestartet.
Wird gavrasm ohne die Option -x gestartet, verwendet es die intern gespeicherten
Symbole des ausgewählten AVR-Typs. Die Typdefinition erfolgt mit der
Direktive .include "8515def.inc", die Include-Datei wird nicht
gelesen und angegebene Pfadinformationen werden ignoriert.
Wird gavrasm mit der Option -x gestartet, dann werden nicht die intern
gespeicherten Symbole verwendet. Die angegebene Headerdatei muss dann
tatsächlich vorhanden und lesbar sein. Befinden sich alle verwendeten
INCLUDE-Dateien im Pfad des Quelltextes, dann braucht man nur den Namen der
Include-Dateien (z.B. "8515def.inc") anzugeben. Andernfalls muss dem
Namen der korrekte Pfad hinzugefügt werden (z.B. in Windows mit
installiertem Studio
"C:\Programme (x86)\Atmel\Assembler2\appnotes\8515def.inc" oder bei Linux
"/home/gerd/avrasm/def/8515def.inc"). Im Falle der Verwendung neuerer
Studio-Installationen enthalten die Include-Dateien C-ähnliche Konstrukte.
Diese werden von gavrasm ignoriert und es wird nur mit einer Warnung darauf
hingewiesen.
Die Parameteroptionen sind in der Datei Liesmich.Txt generell aufgelistet.
Hier einige ausführlichere Erläuterungen:
- Die Option -a ist nur unter Linux sinnvoll zu verwenden. Sie schaltet
die Ausgabe der einzelnen Zeilennummern während des Kompiliervorganges aus.
- Die Option -b ist sinnvoll, um bei Fehlermeldungen eine ausführlichere
Kommentierung der Parameter einer Instruktion zusätzlich zu erhalten. Sie
funktioniert nur, wenn gleichzeitig die Option -e gewählt wird (z.B. -eb).
- Die Option -l schaltet die Erzeugung der List-Datei generell aus. Nur für
Puristen sinnvoll, die unbedingt knappen Plattenplatz sparen wollen.
- Die Option -q sperrt generell die Ausgabe von Meldungen auf der
Kommandozeile. Die einzigen Nachrichten sind INCLUDEs, die Pass-Information
und der Erfolg/Misserfolg des Kompiliervorganges (Anzahl Fehler).
- Die Option -s schaltet die Ausgabe der verwendeten Symbole in der
List-Datei an, sofern die Listausgabe nicht mit der Direktive .NOLIST im Quellcode
ausgeschaltet ist. Alle Symbole werden am Ende der Datei sortiert nach ihrem Typ
- R: Register,
- L: Label oder Marke,
- C: EQU-Konstante,
- V: SET-Variable,
- M: Lokales Makro-Symbol (Label/Marke in einem Makro),
- G: Globalisiertes Makro-Symbol
geordnet ausgegeben. Dabei erhält man als zusätzliche Information,
wie oft das Symbol definiert wurde (nDef, sinnvoll bei Variablen), verwendet wird
(nUsed) und den letzten Wert des Symbols in dezimalem und hexadezimalem Format.
- Die Option -w erlaubt das Wrap-Around, also Sprünge vorwärts über
das Ende des Flash-Programmspeichers hinaus (an den Anfang des Adressraums) bzw.
rückwärts vor den Beginn des Speichers (an das Ende des Adressraums).
Die Option ist nur sinnvoll, wenn der AVR einen über 4k großen Flash
verfügt und damit einen sehr langen Adressraum hat, der mit relativen
Sprüngen nicht mehr direkt überbrückt werden kann. Das Wrap-Around
funktioniert in gavrasm auch mit den relativen Branch-Instruktionen (z.B. BRCC
oder BREQ). Weil das manche andere Assembler aber nicht beherrschen, sind solche
Quelltexte nicht mit anderen Assemblern kompilierbar!
- Die Optionen -?, -h, -d und -t veranlassen gavrasm ausschließlich zur
Ausgabe der gewünschten Informationen (-? und -h: zulässige Optionen,
-d: implementierte Direktiven, -t: zulässige AVR-Typen und deren Eigenschaften).
Eine gleichzeitig angegebene Quelldatei wird dabei ignoriert und nicht assembliert!
An den Seitenanfang
Um sich die wiederholte Prozedur der Eingabe von Pfadnamen zu ersparen, kann der
Assembler-Aufruf in einer Batchdatei erfolgen. Unter Win wird dazu eine neue
Textdatei erzeugt, mit folgenden Zeilen versehen
REM Batch-Aufrufdatei
[Laufwerk]:
CD [Pfad-zur-Sourcedatei]
[gavrasm-pfad]\gavrasm [-optionen] quelldatei[.asm]
PAUSE
Die Textdatei wird mit der Endung ".bat" in einem beliebigen Verzeichnis gespeichert.
Wer mag, kann eine Verknüpfung auf diese Batchdatei auf den Desktop legen.
Sie kann durch Anklicken gestartet werden und steuert den Kompilierprozess. Die
Pause-Anweisung bewirkt, dass sich das Fenster erst nach einer Taste schließt.
Unter Linux schreiben wir folgendes Shell-Script:
#!/bin/bash
cd [Pfad-zur-Sourcedatei]
[Pfad-zu-gavrasm]/gavrasm [-optionen] Quelldatei[.asm]
read key
und speichern es mit der Endung .sh irgendwo ab. Wer mag, kann sich eine
Verknüpfung zu dieser Shelldatei auf dem KDE-Desktop erzeugen (Neu erstellen/
Verknüpfung mit Programm, dabei Ausführung in einem Terminalprogramm
wählen) und anschließend die Ausführungrechte setzen. Die Zeile
mit read key bewirkt, dass man die Ausgabe im Terminal verfolgen kann, bevor sich
das Terminal schließt.
An den Seitenanfang
Wenn Du in einer Fensterumgebung arbeitest, könntest Du müde werden
beim Schreiben von Batchdateien. Hier ist was einfaches als Ersatz.
Auf vielfachen Wunsch habe ich ein Windows-Programm geschrieben, das menuegesteuert
Batchdateien erzeugt, den Assembler aufruft und in einem Editorfenster Dateien
anzeigen kann. Einige neue Schmankerl sind:
- Die Source- und Include-Dateien lassen sich auch editieren, dabei werden
Zeile und Spalte angezeigt (anders als bei den anderen simplen Windows-Editoren).
- Der Editor arbeitet auch mit Tab-Zeichen.
- Mit Include eingebundene Dateien werden automatisch erkannt und
können editiert werden. Das funktioniert auch rekursiv mit bis zu maximal
fünf Include-Dateien.
- Wird nach dem Assemblieren die List-Datei angezeigt, können Fehler im
Quelltext komfortabel gesucht werden. Auf Wunsch werden die Dateien, in denen
der Fehler auftrat, in den Editor geladen und direkt die fehlerhafte Stelle
angesteuert.
- Es können jetzt beliebig viele Dateien gleichzeitig angeschaut und
editiert werden.
Mehr über die Features und über die Bedienung gibt es in der
Lies-Mich-Datei.
Das Programm läuft nur unter Windows (sorry, Linuxer) und steht gepackt unter
diesem Link zum Download zur Verfügung.
An den Seitenanfang
Die zusätzlichen Direktiven .IF, .ELSE und .ENDIF ermöglichen es, je
nach den Einstellungen im Kopf einer Quelldatei oder nach festgestellten
Rechenergebnissen Programmteile zu kompilieren oder nicht. Die IF-Bedingung
wird während der Kompilation geprüft. Ist sie erfüllt, wird
der folgende Quellcode assembliert. Wenn nicht, wird die Kompilierung des
Quellcodes erst nach der .ELSE- oder der .ENDIF-Direktive wieder fortgesetzt.
Achtung: Fehlen beide Anweisungen, wird der Rest des gesamten Quelltextes nicht
mehr kompiliert!
Als Anwendungsbeispiel:
.EQU taktfrequenz=40000000
.IF taktfrequenz>4000000
.EQU teiler=4
.ELSE
.EQU teiler=2
.ENDIF
Ein Blick auf die Symbolliste zeigt, dass die Konstante "Teiler" nach
dem Kompilieren auf 2 gesetzt ist. Wird die Taktfrequenz im Kopf z.B. auf
10.000.000 umdefiniert, wird der Teiler auf 4 gesetzt. Allgemein vermeidet
man dadurch, dass für jede Änderung von minimalen Parametern eigene
Änderungen im Quelltext, außer im Kopf, vorgenommen werden
müssen.
Als typische Anwendung kann ein Quelltext z.B für verschiedene Typen von
AVRs geschrieben werden. Weil sich die Interruptvektoren bei jedem Typ an einer
anderen Stelle befinden, kann der Vektorbereich spezifisch kompiliert werden.
;
; Definiere Prozessor im Kopf
;
.EQU aTyp=2313 ; Prozessor ist ein 2313
;.EQU aTyp=2323 ; Prozessor wäre ein 2323
;.EQU aTyp=8515 ; Prozessor wäre ein 8515
;
; Abschnitt mit den Int-Vektoren
;
.CSEG
.ORG $0000
rjmp Main ; für alle Typen gleich
rjmp IntVecInt0 ; External Int Vector, wird verwendet
.IF aTyp == 2313
; Int-Vektoren für 2313
reti ; IntVecInt1 ; External Int Vector, nicht verwendet
reti ; Timer1Capt, nicht verwendet
reti ; Timer1/Comp, nicht benutzt
reti ; Timer1/Ovf, nicht benutzt
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
reti ; UartRX, nicht benutzt
reti ; UartUdre, nicht benutzt
reti ; UartTx, nicht verwendet
.ENDIF
.IF aTyp == 2323
; Int-Vektoren für 2323
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
.ENDIF
.IF aTyp == 8515
; Int-Vektoren für 8515
reti ; IntVecInt1 ; External Int Vector, nicht verwendet
reti ; Timer1Capt, nicht verwendet
reti ; Timer1/CompA, nicht benutzt
reti ; Timer1/CompB, nicht benutzt
reti ; Timer1/Ovf, nicht benutzt
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
reti ; SpiStc, nicht verwendet
reti ; UartRX, nicht benutzt
reti ; UartUdre, nicht benutzt
reti ; UartTx, nicht verwendet
reti ; AnaComp, nicht verwendet
.ENDIF
;
; Interrupt-Service-Routine INT0
;
IntVecInt0:
[...]
reti
;
; Interrupt-Service-Routine TC0-Overflow
;
IntVecTC0Ovf:
[...]
reti
;
; Hauptprogramm
;
Main:
[...]
Es ist klar ersichtlich, dass bei einer Umstellung des Quellcodes für
einen anderen Prozessor alle Änderungen sehr umfangreich und deshalb
fehlerträchtig sind. Vergisst man die Sache mit den unterschiedlichen
Interruptvektoren, ergibt sich ein nettes Fehlersuch-Problem. Mit dem
dargestellten Quellcode ist die Umstellung des Programmes für einen
anderen Typ ein Leichtes.
Selbstverständlich können die Bedingungen der .IF-Direktive auch
komplexer formuliert sein, wie z.B. hier:
.IF (aTyp == 2313) || (aTyp == 8515)
Verschachtelte IF-Direktiven sindin beliebiger Tiefe implementiert.
An den Seitenanfang
Überschreitet eine Größe einen zulässigen Wertebereich,
dann bricht man die Assemblierung mit einer Fehlermeldung gerne ab, damit
kein Unsinn auf den AVR losgelassen wird. Mit der Direktive .EXIT kann man
das erreichen:
.EQU taktfrequenz=4000000
.EQU teiler=64
.EXIT (taktfrequenz/teiler)>65535
Damit ist z.B. sichergestellt, dass auch bei anderen Taktfrequenzen kein
16-Bit-Zählerüberlauf zu befürchten ist, ohne dass es der
Assemblerprogrammierer merkt.
An den Seitenanfang
Makros werden vom Assembler gespeichert und erst beim Aufruf ihres Namens
in den Code eingefügt, z.B. so
.MACRO mtest
.nop
.ENDM
;
; Hier wird das Makro eingefügt
;
mtest
Der Code im Makro ist mittels übergebenen Parametern variierbar. Die
Parameter heißen @0 bis @9. Z.B. so
;
; Register global definieren
;
.DEF rmp,R16
.MACRO mtest
ldi @0,@1 ; Erwartet Register als ersten Param, Konstante als zweiten
clr @0
.ENDM
;
; Makro einfügen
;
mtest rmp,50
Die Verwendung von Makros weist bei diesem Assembler die Besonderheit auf,
dass alle im Makro definierten Marken nur innerhalb des entsprechenden
Makros gültig sind. Das verhindert, dass bei mehrfacher Verwendung
des Makros Konfusion auftritt. Global definierte Symbole sind von innerhalb
des Makros zugänglich, daher darf auch bei allen Makro-internen
Symbolen kein Namenskonflikt auftreten. Wegen der lokalen Definition
von Marken innerhalb des Makros ist es normalerweise nicht möglich,
interne Marken außerhalb des Makros zu verwenden. Um dennoch eine
Exportmöglichkeit zu haben, kann man mit der Direktive
.SETGLOBAL Marke1[, Marke2, ...]
den Wert nach außerhalb des Makros exportieren. Die so gebildete
Variable wird zu Beginn jedes Aufrufs des Makros jeweils auf den aktuellen
Wert gesetzt.
Mit diesem Instrumentarium ist die Möglichkeit gegeben, umfangreiche
Bibliotheken für immer wiederkehrende Aufgaben zu schreiben. Weil
der Code nur dann eingefügt wird, wenn das Makro auch tatsächlich
im Code aufgerufen wird, wird kein Platz verschwendet.
An den Seitenanfang
gavrasm ermölicht die Verwendung von ASCII-Kontrollzeichen in Zeichenkonstanten,
also z.B.
.DB "Dies ist die erste Zeile.\m\jDies ist die zweite Zeile."
Ein '\'-Zeichen wird mit zwei '\' eingefügt. Im Gegensatz zu anderen
Assemblern werden ';' in Zeichenketten richtig erkannt und behandelt.
An den Seitenanfang
Der Assembler erlaubt die Verwendung des Punktes als Trennzeichen in Konstanten,
wie z.B.
.EQU abc = 0b0001.0010
.EQU def = 0x0FFF.FFFF
Versuchen Sie diesen Quellcode niemals mit einem anderen Assembler zu assemblieren!
An den Seitenanfang
©2003-2011 by
http://www.avr-asm-tutorial.net