Start AVR-KursStartseitenicht verfügbar

1. Ein erstes Assemblerprogramm


Voraussetzungen: AVR-Studio ist installiert und gestartet

Der Speicher des ATTiny2313:

Die CPU (central processing unit) des Chips kann verschiedene Speicherbereiche ansprechen. Darunter sind die allgemeinen Rechenregister (Register = Speicherstelle mit Sonderfunktionen) in denen und mit denen die CPU logische und arithmetische Funktionen ausführen kann. Diese Register sind in zwei Speicherbänke mit leicht unterschiedlichen Eigenschaften unterteilt. So kann man in die unteren Register R0 .. R15 keine konstanten Zahlenwerte laden sondern nur Inhalte von anderen Registern.

Der ATTiny2313 gehört wie seine Brüder zur Familie der RISC-Prozessoren. Diese Prozessorart zeichnet sich dadurch aus, dass sie einen sehr begrenzten Satz an Befehlen haben und dass die einzelnen Befehle in meist einem Prozessortakt abgearbeitet werden. Das liegt nicht zuletzt daran, dass Anweisung und Daten in einem Befehlswort (=2 Bytes) codiert werden und damit zusätzliche Speicherzugriffe wie beim PC (CISC-Prozessor) eingespart werden können. Bei einem ATMEL-Prozessor werden also tatsächlich bis zu 20 Millionen Befehle pro Sekunde abgearbeitet, wenn er mit 20 MHz getaktet wird.


Lege ein neues Projekt an. Über das Menü Project - New Project

rufst du den Dialog dazu auf. Wir erstellen unser erstes Projekt

 

 

 

 

 

 

Bei Location kann man ein beliebiges Verzeichnis wählen.

Wir werden die integrierte Plattform AVR Simulator zusammen mit dem Baustein ATTiny2313 nutzen.

Der Editor gibt uns ein leeres Formular vor, in das wir den ersten Programmtext schreiben werden.

ldi bedeutet "Lade den konstanten Zahlenwert nach dem Komma, in das Register R16". Das "i" kommt von "immediate" und bedeutet eben so viel wie "sofort, unmittelbar". Gemeint ist das so, dass die zu ladende Zahl direkt angegeben und nicht der Inhalt eines Speicherplatzes oder Registers ist.

Das Programm lädt also die Zahl 50 in das Register R16 und die 100 in das Register R17. Dabach werden die beiden Werte addiert und das Ergebnis in das Register R16 geschrieben. R16 steht vor dem Komma im Additionsbefehl und ist wie bei den Ladebefehlen das Ziel- oder Destination-Register. Nach dem Komma steht immer die Datenquelle oder Resource. Bei den Ladebefehlen stellen die konstanten Werte 50 und 100 die Datenquelle dar. Diese Information wird mit in den 16-Bit langen Code des Befehls integriert, wenn der Assembler das Programm übersetzt. Anders verhält es sich beim Additionsbefehl. Hier kommt einer der Summanden aus dem (Quellen-) Register R17. Auch R16 ist eigentlich zunächst Quelle, dann aber der Container für das Rechenergebnis:

R16 := R16 + R17

Diese Gleichung macht mathematisch gesehen keinen Sinn, wohl aber, wenn man weiß wie die CPU den Additionsbefehl abarbeitet. Die beiden Zahlenwerte aus R16 und R17 gelangen in das Rechenwerk, werden addiert und das Ergebnis wird wieder nach R16 transferiert. Allgemein mit Rd als Ziel- und Rr als Resourcenregister sieht das so aus:

Rd := Rd + Rr

Nachdem das Programm eingegeben ist wird es in Maschinensprache übersetzt, assembliert. Den Vorgang startest du mit der Schaltfläche: . Die Rückmeldung des Assemblers sollte so aussehen:

Wichtig ist die Mitteilung 0 errors und der grüne Punkt ganz links. Bei Warnungen warnings, wird er gelb und sollten tatsächlich schwerwiegende Fehler passiert sein, rot.

Unser Programm existiert nun in zwei Versionen. Da ist der dreizeilige Quelltext, den wir verfasst haben, die Datei "erstes.asm". Nach dem Übersetzen gibt es neben weiteren Dateien auch noch eine sogenannte HEX-Datei, die den Maschinencode enthält: "erstes.hex".

Hier sieht man, was der Assembler aus den drei Textzeilen gemacht hat. Die zweite Spalte der obigen Tabelle gibt die drei Befehlsworte zu je 2 Byte wieder, wie sie später im Flash-Speicher des ATTiny2313 stehen würden, wenn man das Programm mittels Pony-Prog an den Chip übermittelt hätte. Jeder Befehl wird während eines Prozessortakts abgearbeitet. Das ist anhand der ersten Spalte ersichtlich, welche die Werte des Programmzählers (program counter) wiedergibt.

Wenden wir uns nun dem Programmablauf zu. Als erstes müssen wir den Simulator starten, das erledigt ein Klick auf die Schaltfläche , die sich gleich rechts neben der Schaltfläche befindet, die den Assembler startet. Im Editorfenster erscheint ein gelber Pfeil, der die Stelle markiert, an der sich gerade der Programmzeiger (Programmzähler) befindet. Mit der Taste F11 bewegst du dich schrittweise durch das Programm. Bevor wir starten öffnen wir aber noch die Anzeige der Register in dem linken Fenster.

Ein Klick auf das Pluszeichen öffnet die Registerliste.


Und wenn du gerade beim Einstellen bist, korrigiere doch gleich noch die Taktfrequenz auf die 20 MHz, welche unser Testaufbau haben wird.

Der Inhalt der Register R16 und R17 vor dem Start des Programms. Die Registerinhalte werden hexadezimal wiedergegeben.

Taste F11:

0x32 = 50 dezimal befindet sich im Register R16

Taste F11:

R17 hat jetzt den Inhalt 100 = 0x64

Taste F11:

Das Register R16 hat nun den Inhalt 0x96 = 150. Wir ändern die zu addierenden Zahlenwerte:

Nachdem die drei Befehle abgearbeitet sind, haben wir erstens ein merkwürdiges Ergebnis und ferner ein dunkles Feld im Bit 0 des Statusregisters SREG.

0x2C = 44 Dezimal!

Der vermeintliche Fehler ist schnell entlarvt. Das C-Bit im SREG (Statusregister) bedeutet, dass beim Addieren ein Übertrag aus den MSBs (= most significant Bits = Bit 7) passiert ist. Also ist zum Wert 44 in R16 der Wert 256 (= Wert des Übertrags im Dualsystem von Byte zu Byte) zu addieren. Das gibt dann wie erwartet 100 + 200 = 300 = 0x012C.

Ein leicht erweitertes Programm trägt diesen Erkennissen Rechnung. Wir gruppieren unsere Variablen etwas um. Die Register R16 und R17 dienen jetzt als Zielort des Ergebnisses und als Vorgabe des Summanden S1. Weil 200 < 256 ist, wird das Highbyte in R17 auf Null gesetzt, das erledigt der clr-Befehl, clr wie "clear" = löschen. 200 = 0x00C8 steht in R17:R16, 100 = 0x0064 in R19:R18. Nach dem Addieren der Lowbytes werden die beiden Nullen der High-Bytes unter Berücksichtigung des Übertrags addiert: 0 + 0 + 1 = 1.

In Bitschreibweise sieht das folgendermaßen aus:

Highbyte
Lowbyte
             
1
1
0
0
1
0
0
0
             
0
1
1
0
0
1
0
0
Übertrag:
+
1
1
0
0
0
0
0
0
0
Summe:
1
0
0
1
0
1
1
0
0

Jetzt erweitern wir den Zahlenbereich bis 65535, so viel wie man mit 2 Bytes darstellen kann, (256 mal 256) -1.

Der Pseudobefehl .equ weist den Platzhaltern S1 und S2 die Zahlenwerte 1500 und 2027 zu. Die Verwendung von Assemblervariablen vereinfacht die Datenhaltung und verringert das Fehlerrisiko, weil die Daten nur an einer Stelle geändert werden müssen, um im gesamten Programm gleichartig zu wirken. Ein guter Grundsatz für Programmierer lautet: "Redundante Daten vermeiden!"

Eine weitere Empfehlung und guter Programmierstil ist es, ein Programm optimal zu dokumentieren. Das hilft einem selbst, wenn man nach ein paar Wochen oder Monaten selbst Änderungen daran durchführen muss und dann in seinen Kommentarzeilen (die nach einem ";" beginnen) nachlesen kann, warum man etwas gerade so gelöst hat. Noch hilfreicher sind Kommentare, wenn ein Anderer das Programm pflegen soll. Ohne Kommentare steht man erst mal im Wald, weil jeder Gedankengang des ursprünglichen Programmierers erst einmal nachvollzogen werden muss, bevor man Änderungen anbringen kann und kostet immens viel Zeit.

Die Ladebefehle des Programms wurden abgearbeitet. Der Pfeil steht auf dem nächsten auszuführenden Befehl.

Nachdem auch die beiden Additionsbefehle ausgeführt wurden, steht das Ergebnis im Registerpaar R17:R16.

0x0DC7 = 3527 dezimal - stimmt!

Überprüfen kann man das mit dem Casio fx-9750G PLUS.

Einschalten - Menü 1 - SHIFT MENU (=SET UP)

F2, wir erwarten Ergebnisse im Dezimalmodus, EXIT

F1, Wir haben eine Basisumwandlung vor

F2, wir werden eine Zahl im Hexadezimalmodus eingeben.

Das tun wir dann auch D C 7, mit EXE abschließen.

Das Ergebnis: 3527 - stimmt!

Umgekehrt geht's auch:

SHIFT MENU F3 F1 5 8 7 9 1 EXE

58791 = 0xE5A7

Nach Ausschalten des Rechners stellt sich der Modus automatisch wieder in die Position "Comp" um.


Start AVR-KursAn den Seitenbeginnnicht verfügbar