Pfad:
Home =>
AVR-Assembler gavrasm => Einführung
(This page in English:
)
Hier werden die besonderen Features des gavrasm-Assemblers vorgestellt.
Die Beispiele compilieren nicht unbedingt auch auf anderen Assemblern. Im
einzelnen werden vorgestellt:
- 1 Aufruf des Assemblers auf der Kommandozeile
- 2 Aufruf des Assemblers mit einer Batch oder in einer Shell
- 3 Hilfsprogramm zum Aufruf unter Windows
- 4 Verwendung von IF-ELSE-ENDIF
- 5 Verwendung von EXIT
- 6 Verwendung von Makros
- 7 Verwendung von besonderen literalen Konstanten
- 8 Verwendung von Trennzeichen in Konstanten
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.
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.
"C:\avrtools\appnotes\8515def.inc" oder "/home/gerd/avrasm/def/8515def.inc").
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 aufgelistet.
- 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
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 dezimaler und hexadezimaler Form.
- 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 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. Das geht bei Windows und Linux
unterschiedlich.
Unter Windows wird dazu eine neue Textdatei angelegt, in Assemble_de.bat umbenannt
(und ja: dadurch ändert sich der Dateityp!), mit der rechten Maustaste im
Kontextmenue "Bearbeiten" im Editor geöffnet und 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
Assemplierprozess. Die Pause-Anweisung am Ende bewirkt, dass sich das Fenster
erst nach Drücken einer Taste schließt, damit wir die wertvollen
Infos von gavrasm auch sehen können.
Seit gavrasm-Version 3.4 gibt der Assembler beim Beenden den Fehlerstatus
zurück. Dieser kann mit der Variable errorlevel ausgewertet werden. Der Code
in der Batch kann so aussehen:
REM
REM Testet Rueckgabewert vom Assembler
REM
[Laufwerk]
CD [Pfad zur Sourcedatei]
[gavrasm-pfad\]gavrasm -optionen Quelldatei[.asm]
If errorlevel 1 Goto Fehler
REM Kein Fehler, weitere Instruktionen hierhin
goto ende
:Fehler
REM Fehler aufgetreten, weitere Instruktionen hierhin
echo Fehlerbehandlung!
notepad.exe Quelldatei.err
:ende
pause
Nach dem Klicken auf die Batchdatei assembliert gavrasm die angegebene Quelldatei
und kehrt mit errorlevel 1 zurück.
Da beim Assemblieren ein Fehler gefunden wurde, öffnet die Batchdatei den
Editor mit der .err-Datei. Mit deren Hilfe kann man jetzt Fehler im Quellcode
ausbessern.
Natürlich kann man auch jeden anderen Editor aufrufen.
An den Seitenanfang
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.
2.2.1 Linux-Shell mit Fehlerauswertung
Seit Version 3.4 von gavrasm gibt der Assembler beim Beenden den Fehlerstatus
zurück. Das kann dazu genutzt werden um in der Shell zu verzweigen. Der
Code kann so aussehen:
#!/bin/bash
# Diese Batch ruft gavrasm auf und verzweigt
cd [Pfad-zur-Sourcedatei]
[Pfad-zu-gavrasm/]gavrasm [-optionen] Quelldatei[.asm]
if [ "$?" = "0" ]; then
# Dieser Zweig wird ausgeführt wenn kein Fehler auftritt
echo "Shell: Kein Fehler beim Assemblieren"
else
# Dieser Zweig wird ausgeführt wenn ein Fehler auftritt
echo "Shell: Fehler beim Assemblieren"
# Aufruf des Editors mit der Fehlerdatei von gavrasm
kwrite "fehler.err"
fi
Im Beispiel ruft die Shell eine fehlerhafte Assemblerdatei auf. Die Ausgabe der
Shell sieht dann so aus:
Statt des Zweigs mit ohne Fehler wird jetzt der Editor KWrite aufgerufen und
die Fehlerdatei Quellcode.err angezeigt.
Natürlich kann auch jeder andere vorhandene Editor aufgerufen werden.
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 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
; Int-Vektoren für 2313
.IF aTyp == 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
; Int-Vektoren für 2323
.IF aTyp == 2323
rjmp IntVecTC0Ovf ; TC0-Overflow, verwendet
.ENDIF
; Int-Vektoren für 8515
.IF aTyp == 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)
Verschaltelte IF-Direktiven sind wegen der Unübersichtlichkeit und
wegen möglicher Fehlerquellen allerdings nicht 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-2014 by
http://www.avr-asm-tutorial.net