Supervisor Calls
Bei Supervisor Calls oder Syscalls handelt es sich um Funktionen, die das Betriebssystem bereitstellt, um bestimmte Aufgaben zu erledigen. Jeder Syscall hat eine eigene Nummer, über die Sie ihn aufrufen. Die Nummern mit den dazugehörigen Namen liefert auf dem RasPi das Kommando cat /usr/include/arm-linux-gnueabihf/asm/unistd-common.h im Terminal. Um in Assembler einen Syscall auszuführen, verwenden Sie den Befehl svc #0. Sie dürfen Syscalls aber auch aus Hochsprachen heraus aufrufen. Dabei muss die Nummer des Syscalls im Register r7 liegen. Je nach Syscall befinden sich in den Registern r0 bis r6 die zugehörigen Parameter. Der Rückgabewert des Calls landet grundsätzlich im Register r0. Die Dokumentation der einzelnen Syscalls rufen Sie im Terminal mit man 2 Name auf. Die 2 gibt dabei an, dass Sie in der Dokumentation nur in Sektion 2 suchen wollen.
Ab Zeile 22 beginnt das eigentliche Blink-Programm: Es setzt zunächst den Modus für GPIO21 auf Output. Dann lädt es den Wert für die Wartezeit ins Register r2 (Zeile 24). In Zeile 25 speichert es die Bitkombination zum Ein- und Ausschalten von GPIO21 im Register r1.
Die GPIO-Register arbeiten nach einem recht einfachen Muster, jedes hat eine bestimmte Aufgabe – GPIO setzen, GPIO löschen, Pullup aktivieren und so weiter. Jedes einzeln Bit in den Registern entspricht einem GPIO-Pin. Setzen Sie das Bit, das GPIO21 entspricht, im Register GPFCLR0 (Register zum Löschen von GPIOs), geht die GPIO auf 0. Daher lädt das Programm die Kombination für die GPIO21 ins Register r1.
Nun brauchen Sie das Register r0 später nur noch abwechselnd in die Register GPFSET0 und GPFCLR0 der GPIO zu schieben. Genau das erledigen die Zeilen 27 und 34. Hierbei bedeutet das Kommando so viel wie: Speichere den Inhalt von r1 an die Speicheradresse, die sich ergibt, wenn man den Inhalt von r0 zur Konstante aus GPFSET0 respektive GPFCLR0 addiert. Die zwei Warteschleifen zählen den Wert in r0 so lange hoch, bis er den Wert aus TIME (r2) erreicht.
Dieses Verfahren, eine Wartezeit zu erzeugen, ist nicht besonders geschickt, weil tatsächlich ein CPU-Kern kontinuierlich zählt. Sie können sich mit dem Kommando top die CPU-Auslastung ansehen, wenn das Programm läuft. Ein CPU-Zeit-optimiertes Programm würde mit Timern und Interrupts arbeiten, wäre dann allerdings erheblich komplizierter.
Zu guter Letzt steht in Zeile 40 ein unbedingter Sprungbefehl, der zum Label loop zurückspringt und so das Programm bis in alle Ewigkeit ausführt.
Tipps zum Weitermachen
Nun stecken Sie schon ziemlich tief in der Assembler-Programmierung. Wenn Sie sich von Grund auf mit dem Thema beschäftigen möchten, empfiehlt sich ein englischsprachiges Tutorial, das Sie bei Thinkgeek finden [4]. Es erläutert die Grundlagen von Anfang bis Ende und gibt zusätzlich viele hilfreiche Tipps.
Einfache Beispiele, wie die aus diesem Artikel, geben Sie einfach mit einem Editor wie Nano ein. Sollten Sie komplexere Projekte bearbeiten, sollten Sie sich hier nach einem etwas leistungsfähigeren Editor umsehen.
Um die Dateien auf den Raspberry Pi zu bekommen, gibt es diverse Möglichkeiten. Der Autor bindet dazu unter Ubuntu im Dateimanager den RasPi per SSH ein. Das ist ein einfacher Weg, der im LAN meist klappt. Bei komplexeren Projekten hat es wenig Sinn, alle Dateien von Hand zu bauen. Selbst das altmodische Make spart hier viel Zeit und Arbeit.
Bevor Sie anfangen eine Funktion zu implementieren, sehen Sie immer vorab einmal in die Liste der Syscalls. In vielen Fällen findet sich dort bereits etwas Geeignetes. Bei den Syscalls dürfen Sie getrost davon ausgehen, dass sie keine Fehler beinhalten, was gerade in der Assembler-Programmierung viel wert ist.
Fazit
Dieser recht kurze Artikel konnte nur an der Oberfläche der Assembler-Programmierung kratzen, viele Details bleiben offen. Aber der Einstieg in diese Programmiersprache fällt nicht schwer, die einzelnen Kommandos sind nicht kompliziert. Haben Sie sich erst einmal ein wenig mit der CPU-Architektur beschäftigt, lässt sich der Sinn dahinter leicht verstehen.
Der knifflige Teil beginnt, sobald Sie anfangen, mit Assembler typische Probleme zu lösen, die man sonst in Hochsprachen angeht. Dann kommen schon für ein kleines Programm schnell ein paar Hundert Kommandos zusammen. Dem stehen dafür als Vorteile ein minimaler Footprint des Codes und eine (bei korrekter Programmierung) maximale Ausführungsgeschwindigkeit gegenüber. (agr)
Der Autor
Martin Mohr hat die komplette Entwicklung der modernen Computertechnik live miterlebt. Nach dem Studium entwickelte er überwiegend Java-Applikationen. Mit dem RasPi erwachte seine alte Liebe zur Elektronik wieder.
Glossar
- Return Code
-
Unter Linux geben Programme einen Return Code zurück, um den Status beim Beenden anzuzeigen. Diesen Wert speichert die Bash in der Variablen
$?, die Sie mitecho $?auslesen. - BCD
-
Binary Coded Decimal. Stellt jede dezimale Ziffer von 0 bis 9 durch jeweils 4 Bit dar, also in einem Halbbyte (Nibble).
- ALU
-
Arithmetisch-logische Einheit einer CPU. In der ALU führt der Rechner alle Berechnungen und Vergleiche innerhalb der CPU aus.





