s'AVR Precompiler

© Eberhard Haug 2003-2017

Optimale Darstellung dieser Website
bei aktiviertem
"Active Scripting" (LED-Menü-Buttons).

Bildschirm-Auflösung 800x600 wird unterstützt

Besucher seit 6.1.2004:
 

WEBCounter by GOWEB

 

Strukturierte Assembler-Programmierung für Atmel® AVR®
(31.3.2016)

Nachdem ich in jüngeren Jahren für diverse µController u.a. reichlich komplexe Programme in Assembler-Sprache mit Sprachelementen für strukturierte Assembler-Programmierung[1] programmiert hatte und diese Tools zu schätzen wusste, habe ich mir neuerdings wieder eine solche Möglichkeit auch für modernere µController und Windows®-Umgebung gewünscht.

Dieses Konzept ist schon Jahrzehnte alt (und bewährt), wird aber "dank" Hochsprachen leider nur noch selten für aktuelle µController angeboten und wenn, dann für reichlich viel Geld.

Bereits im Jahr 2000 habe ich mich deshalb selbst ans (Pascal-) Programmieren gemacht und für die sehr schnellen SX-Mikrocontroller von Scenix/Ubicom[2] einen Precompiler (damals SXp genannt) erstellt.

Für die SX-µController war es auch noch wichtig, mit deren sehr kleinem Programmspeicher sparsam umzugehen und natürlich das Maximum an Ausführungsgeschwindigkeit heraus zu holen.

C-basierende und damit programmspeicherfressende Programme waren hierfür damals nicht wirklich eine Alternative.

Außerdem waren (und sind auch heute immer noch) Hochsprachen zum Programmieren von kleinen Mikrocontrollern nicht jedermanns Sache. Oder man will für Ausbildungszwecke bewusst auf Assemblersprache zurückgreifen.

s'AVR

Da ich vor Kurzem für verschiedene Projekte einen etwas aktuelleren und preisgünstigen µC benötigt hatte und immer noch gerne maschinennah in Assembler-Sprache programmiere, habe ich das bewährte Konzept des Precompilers für strukturierte Assembler-Programmierung für die AVR-Mikrocontroller von Atmel umgeschrieben (und den Precompiler nun s'AVR genannt), mit dem sich AVR-Assembler-Programme nicht nur deutlich schneller, sondern auch noch sehr viel übersichtlicher und auf Anhieb zuverlässiger erstellen lassen.

Und mehr Programmierspaß macht es auch noch!

Precompiler

Da das Programm aus dem s'AVR-Quellprogramm nicht direkt einen Maschinen-Code (also z.B. eine HEX- oder OBJ-Datei) erzeugt, sondern zunächst ein strukturloses (und deutlich längeres) "flaches" AVR-Assembler-Quellprogramm, ist es kein echter Compiler sondern ein Precompiler.

Es handelt sich bei s'AVR auch nicht um Assembler-Macro-Befehle, womit sich ein strukturiertes Assembler-Programm ebenfalls realisieren lassen würde, aber bei Weitem nicht so elegant.

Das erzeugte "flache" Assembler-Quellprogramm wird (ohne dass man es überhaupt anschauen müsste) mit dem vorhandenen AVR-Assembler anschließend in Maschinen-Code assembliert und dann wie gewohnt mit einem geeigneten Programmier-Tool in den AVR-µC programmiert.

Das hört sich alles vielleicht etwas kompliziert an, ist es aber nicht. Man muss einfach nur einmal damit gearbeitet haben und will dann strukturierte Assembler-Programmierung nicht mehr missen.

nach oben


s'AVR-Anweisungen

Das sind die derzeit von s'AVR unterstützten Anweisungen zur strukturierten AVR-Assembler-Programmierung in aller Kürze:

----------------------------------------------------------------------
IF Bedingung [THEN]    ; erste Abfrage (THEN ist nicht zwingend nötig)
    BefehlsFolge
ELSEIF Bedingung [THEN]; weitere Abfrage(n), mehrfach optional
    BefehlsFolge
ELSE                   ; letzte Verzweigung, optional
    BefehlsFolge
ENDI                   ; Ende der IF-Struktur
----------------------------------------------------------------------
LOOP                   ; Endlosschleife
    BefehlsFolge       ; verlassen der LOOP-Schleife nur mittels EXIT,
                       ; EXITIF, Assembler-Sprung- und Branch-
                       ; Befehlen, RET, Interrupt oder Reset
ENDL                   ; Ende der LOOP-Schleife
----------------------------------------------------------------------
WHILE Bedingung        ; Abfrage zu Beginn der WHILE-Schleife
    BefehlsFolge
ENDW                   ; Ende der WHILE-Schleife
----------------------------------------------------------------------
REPEAT                 ; Beginn der Schleife
    BefehlsFolge
UNTIL Bedingung        ; Abfrage am Ende der REPEAT-Schleife
----------------------------------------------------------------------
FOR RegisterZuweisung  ; Schleife mit Register-Initialisierung
    BefehlsFolge
ENDF                   ; dekrementieren des Schleifenzählers und
                       ; überprüfen auf den Wert Null
----------------------------------------------------------------------
EXIT                        ; verlassen einer Strukturebene
EXITIF Bedingung            ; bedingtes Verlassen einer Strukturebene
EXITIF Bedingung TO Adresse ; bedingter Sprung aus einer Struktur-
                            ; ebene heraus
----------------------------------------------------------------------
 

"BefehlsFolge" sind entweder reine AVR-Assembler-Befehle oder weitere s'AVR-Anweisungen, die beliebig tief geschachtelt werden können. Letzteres ist natürlich eine wichtige Anforderung an eine strukturierte Programmierung.

"Bedingung" steht für Vergleiche (mindestens ein AVR-Register), Register- und Port-Bit-Abfragen oder Statusregister-Flag-Abfragen.

"RegisterZuweisung" gibt die Zahl der FOR-Schleifendurchgänge an.

Das spezifizierte FOR-Schleifenregister kann bereits vorher (bei Erreichen der FOR-Schleife) geladen sein oder die Zuweisung ist Teil des Befehls. Das FOR-Schleifenregister kann entweder mit einer Konstanten oder dem Inhalt eines anderen AVR-Registers geladen werden.

Beta-Version verfügbar

Im Moment gibt es eine Beta-Version von s'AVR für Windows®, die von mir bereits ausgiebig getestet wurde und auch laufend für aktuelle AVR-Projekte verwendet wird.

Damit lassen sich ohne Einschränkungen auch für ATtiny strukturierte Assembler-Programme erstellen.
Für alle anderen 8-Bit-AVR-µC gilt das natürlich ebenso.

Handbuch

Ein ausführliches Handbuch mit einigen s’AVR-Beispielen steht ebenfalls zur Verfügung[3], nämlich hier vorab zum Download.

Ausprobieren?

Interessierte AVR-Assembler-Programmierer mögen sich gerne bei mir mit einer kurze E-Mail an nebenstehene E-Mail-Adresse melden, damit ich ihnen das (sehr kompakte) Programm zum eigenen Test zukommen lassen kann (bitte angeben, ob als ZIP- oder als 7Z-Datei) - kostenlos versteht sich.
Lediglich um einen Erfahrungsbericht bitte ich.

Sofern es keine Einwände bezüglich Funktionstüchtigkeit gibt, soll das s’AVR-Programm allgemein zum Download zur Verfügung stehen.

Umstieg = Aufstieg

Bereits bestehende AVR-Assembler-Quellprogramme können nachträglich  (auch nur teilweise) sehr einfach mit s'AVR-Befehlsstrukturen erweitert werden. Das macht den Umstieg - oder besser den Aufstieg - zu s'AVR besonders einfach.

Der vorsichtige Programmierer fängt bei der Umstellung auf s’AVR mit ein paar wenigen Strukturen an und lässt die bisherigen Assembler-Befehle als Kommentar im Quellprogramm stehen. Außerdem legt er eine Sicherungskopie des ursprünglichen Programms an.

Anhand der von s’AVR erzeugten Ausgabedatei (*.asm) kann man dann direkt eventuelle Unterschiede (wenn überhaupt) zwischen dem ursprünglichen Assembler-Programm und dem von s’AVR erzeugten erkennen.

Natürlich ist es deutlich einfacher, ein s’AVR-Programm von Anfang an strukturiert zu schreiben anstatt ein bestehendes AVR-Assembler-Programm mühsam umzuschreiben.

Als Entwicklungsumgebung kann Atmel®-Studio dienen (im Handbuch ist das Einbinden ausführlich beschrieben), muss aber nicht.

Bei Bedarf ist selbst ein Programmaufruf per DOS-Kommandoschnittstelle nebst Übergabe von Parametern möglich. Diese wird aber eigentlich nur zum Einbinden in andere Programme (wie z.B. Atmel®-Studio) verwendet.

Bin gespannt, ob es bei den Lesern meiner Website Interesse an einem solchen Programmier-Tool gibt. Ich selbst erstelle meine AVR-Assembler-Programme inzwischen ausschließlich strukturiert für s’AVR.

nach oben


s’AVR-Beispiel (Auszug)

Hier ist ein sehr einfacher Auszug aus einem größeren s'AVR-Testprogramm - in der strukturierten Form kurz und übersichtlich:

LOOP                  ; main loop

    .

    .

    .

    ; Test FOR, WHILE and REPEAT

    clr rval          ; test value zero

    ldi rtst,0xB0     ; start B.0 test

    FOR rchk := #16   ; loop 16 times

        rcall chkok

    ENDF

    ldi rtst,0xC0     ; start C.0 test

    ldi rchk,1

    WHILE rchk <= #16 ; count from 1 through 16

        rcall chkok

        inc rchk

    ENDW

    ldi rtst,0xD0     ; start D.0 test

    REPEAT            ; continue counting from 17 until 32

        rcall chkok

        inc rchk

    UNTIL rchk == #32

ENDL                  ; main loop (forever)

 

Alles was in diesem Beispiel nicht rot markiert ist, ist reine AVR-Assemblersprache und wird von s’AVR nicht angetastet!

 

Die blauen Markierungen der Assembler-Befehle stammen von Visual Assist des Atmel-Studio 7.

 

In dem aufgerufenen Unterprogramm werden Details des jeweiligen Tests dynamisch (abhängig von den jeweiligen Schleifenparametern) auf einem LCD angezeigt.

 

Und hier folgt, was s'AVR beim Compilieren (das geht schneller als ein Mausklick) daraus erzeugt[4] hat:

 

    ;01// LOOP        ; main loop

_L1:

    .

    .

    .

_L231:

    ; Test FOR, WHILE and REPEAT

    clr   rval         ; test value zero

    ldi   rtst,0xB0    ; start B.0 test

    ;02// FOR rchk := #16 ; loop 16 times

    LDI   rchk,16

_L289:

    rcall chkok

    ;02// ENDF

    DEC   rchk

    BREQ  _L290

    RJMP  _L289

_L290:

    ldi   rtst,0xC0    ; start C.0 test

    ldi   rchk,1

    ;02// WHILE rchk <= #16; count from 1 through 16

_L292:

    CPI   rchk,16

    BRLO  _L293

    BREQ  _L293

    RJMP  _L294

_L293:

    rcall chkok

    inc   rchk

    ;02// ENDW

    RJMP  _L292

_L294:

    ldi   rtst,0xD0   ; start D.0 test

    ;02// REPEAT      ; continue counting from 17 until 32

_L296:

    rcall chkok

    inc   rchk

    ;02// UNTIL rchk == #32

    CPI   rchk,32

    BREQ  _L297

    RJMP  _L296

_L297:

    ;01// ENDL        ; main loop (forever)

    RJMP  _L1

 

Die ursprünglichen s’AVR-Anweisungen sind in der Ausgabe-Datei optional als Kommentar erhalten (oben rot markiert).

 

Anhand der Angaben 01//, 02// etc. in den auskommentierten s’AVR-Anweisungen erkennt man die augenblickliche Strukturebene des Programms bzw. die absolute Verschachtelungstiefe, die man im "flachen" Assemblerprogramm sonst nicht erkennen kann.

 

Warum manche der AVR-Assembler-Befehle von s’AVR genau so und nicht anders (möglicherweise etwas optimaler) generiert wurden, steht im Handbuch beschrieben.

 

Auffallend an diesem einfachen (und in kürzester Zeit geschriebenen Testprogramm) ist, dass s'AVR allein im Hauptprogramm (also innerhalb der LOOP/ENDL-Schleife) aufgrund von vielen IF-Abfragen nahezu 300 Sprungzieladressen erzeugt hat, wogegen das s’AVR-Hauptprogramm aufgrund der strukturierten Programmierung überhaupt keine Adressen benötigt - wenn das keine Erleichterung ist!

 

In den aufgerufenen Unterprogrammen (natürlich ebenfalls mit s'AVR-Anweisungen geschrieben) kommen in diesem Beispiel nochmals weitere ca. 30 von s'AVR erzeugte Sprungzieladressen dazu.

 

nach oben


Warenzeichen:

    Atmel® und AVR® sind registrierte Warenzeichen von Atmel Corporation
    Windows® ist ein registriertes Warenzeichen von Microsoft Corporation


[1] u.a. mit einem Macro-Assembler von Quelo für die 68000-Familie und Strukta von Rolf-Dieter Klein für den Z80, damals beide lauffähig unter CP/M.

Für die 68000-Familie gibt es auch heute noch ein wunderbares Software-Paket namens EASy68k (Editor/Assembler/Simulator 68k), das unter Windows® läuft, strukturierte Assembler-Programmierung und sogar einen Simulator unterstützt.

EASy68k unterstützt ähnliche (etwas komplexere) Strukturen wie s’AVR, nämlich:
IF-THEN-ELSE-ENDI (aber kein ELSEIF), WHILE-DO-ENDW, REPEAT-UNTIL-DO, FOR-TO/DOWNTO-DO-ENDF und DBLOOP-UNLESS (eine Kombination von REPEAT und FOR). LOOP-ENDL, EXIT und EXITIF werden von EASy68k nicht unterstützt.

[2] Ubicom wurde 2012 von Qualcomm übernommen.
Die SX-Bausteine sind inzwischen nicht mehr verfügbar.

[3] Handbuch derzeit nur in Deutsch, eine englische Ausgabe wird bei Bedarf folgen.

[4] Die erzeugte Ausgabedatei schaut man normalerweise nur im Fehlerfall an, da in dieser für den Assembler erzeugten Assembler-Quelldatei (*.asm) ggf. auch Fehlermeldungen und andere Hinweise enthalten sind, aber vielleicht auch zum Debuggen, was dank s'AVR dann vermutlich nicht mehr so oft nötig ist.