Sonntag, 26. Juli 2015

Arduino in Assembler programmieren

In diesem Artikel geht es um die Programmiersprache Assembler und wie man den Arduino mit Assembler programmiert. Da Assembler eine sehr hardwarenahe Programmiersprache ist kann mit Assembler effektiveren Code schreiben, als mit Hochsprachen wie C/C++.


Die Programmiersprache Assembler

Jedes Programm, egal auf welcher Plattform(Mikrocontroller, PC, ...), muss in sogenannten Maschinencode übersetzt werden. Das ist ein, für einen normalen Menschen unlesbarer, Kauderwelsch aus Zahlen und Buchstaben. Diese Übersetzung nimmt der Compiler der jeweiligen Programmiersprache vor. Und genau darin liegt der Vorteil von Assembler. Bei einem "normalen" Arduino C++ Programm muss der Compiler die "komplizierten" Anweisungen in mehrere Maschinenbefehle zerlegen, und erzeugt so den Maschinencode. Dabei ist nicht sichergestellt, dass der optimalste Weg der Übersetzung gewählt wurde. Die Programmiersprache Assembler hingegen ist einfach eine 1 zu 1 Übersetzung des unlesbaren Maschinencodes in, für Menschen lesbare, Wörter. Der Assembler Compiler übersetzt dann nur noch den Text 1 zu 1 in Maschinencode. Dabei kann man sein Programm so schreiben, dass der optimalste Weg gewählt wird. Dieser große Vorteil von Assembler stellt gleichzeitig auch den größten Nachteil von Assembler dar. Es ist kompliziert mit Assembler große Projekte zu realisieren, da man sich alle bekannten Funktionen von C++ wieder selbst "nachbauen" muss. Dadurch kann der Code sehr unübersichtlich werden. Aus diesem Grund wird mittlerweile Assembler oft nur noch verwendet, wenn es unbedingt nötig ist und ansonsten eine Hochsprache wie C/C++ verwendet.

Assembler mit dem Arduino

Um den Arduino in Assembler zu programmieren benötigt man eine IDE. Ich verwende das Atmel Studio, eine IDE von Atmel, dem Hersteller des Mikrocontroller des Arduino Uno. Wie man das Atmel Studio installiert und mit dem Arduino verbindet, habe ich bereits hier erklärt. Nun klickt man auf File > New > Project. Im erscheinenden Fenster muss man in der linken Spalte auf Assembler umschalten.
Nach der Auswahl seines Mikrocontrollers sieht man das gewohnte Textfeld. Der erste Schritt in einem Assemblerprogramm ist immer die include Datei seines Mikrocontrollers nachzuladen. Diese Datei enthält die wichtigen Informationen über einen Mikrocontroller bereit. Unter anderem auch die Befehle, welche der Mikrocontroller unterstützt. Da die Assembler Befehle immer eine 1 zu 1 Maschinencode Übersetzung haben und nicht jeder Mikrocontroller jeden Befehl kennt/mit ihm umgehen kann, kann man auch nicht jeden Assemblerbefehl mit jedem Mikrocontroller verwenden. Alle include Dateien der Mikrocontroller sind bereits im Atmel Studio enthalten. Man muss nur noch die richtige Datei auswählen.
Wie ihr dem Bild entnehmen könnt, befinden sich alle Dateien in einem Unterordner des Installationsverzeichnises des Atmel Studio. Der Name eures Mikrocontrollers kommt dann in der passenden Datei vor. Beispielsweise der ATmega328P des Arduino hat die include Datei mit dem Namen m328Pdef.inc. 
Um einen Port des Arduino(Erklärung hierzu) als Output beziehungsweise Input zu schalten, muss man die Information zunächst in ein Arbeitsregister kopieren. Der ATmega328P hat 32 Register, wobei auf die ersten 16 nicht jeder Assemblerbefehl zugreifen kann. Es ist also sinnvoll die Information 0b11111111 in das Register 16 zu speichern. Ein Arbeitsregister kann man sich wie eine Werkbank vorstellen. Die Informationen in diesem Fall 0b11111111 sind irgendwo in deiner Werkstatt gespeichert(Speicher des Mikrocontroller). Damit du sie jedoch weiterverwenden kannst musst du sie erst auf deine Werkbank legen(in ein Arbeitsregister laden). Sobald sie dann auf der Werkbank sind kannst du sie verwenden(die Pins des Ports als Outputs schalten). Der Befehl um eine Information in ein Arbeitsregister zu laden lautet ldi. ldi steht für Load Immediate. Dabei wird das zweite "Argument" in das erste geladen. Dementsprechend muss man erst das Register und dann den Inhalt angeben. Über den Befehl out kann man die Informationen eines Arbeitsregisters in eines der Register der Pins laden(DDR, PIN, PORT). Damit ist dann ein Pin als Output beziehungsweise Input definiert. 1 steht für Output, 0 für Input. 0b11111111 ist die binärschreibweise des Befehls "Alle Output". Daneben gibt es auch andere Schreibweisen, die jedoch dasselbe bedeuten. Über den Befehl in wird etwas in ein Register geladen. Auch hier gilt die Regel: Der Inhalt des zweiten Attributs wird in das erste Attribut kopiert. Mit diesem Wissen kann man jetzt die GPIOs des Arduino mit Assembler steuern. Mit dem folgenden Programm kann man LEDs, angeschlossen an Port B, über Buttons, angeschlossen an Port D, steuern.



Keine Kommentare:

Kommentar veröffentlichen