Programmiersprachen - Wie sag ich's meinem Computer
Wie den meisten bereits bekannt sein dürfte, benötigt jeder Mikrocontroller und jeder Mikroprozessor zum arbeiten ein Programm. Dieses muss nun von einem Entwickler erst einmal erstellt werden. Jeder der sich mit Controllern, wie z.B. dem ATMega 8 auf diesen Seiten, beschäftigt, muss erst einmal ein Programm erstellen, damit dieser etwas tut.
Zu Beginn des Computerzeitalters, wurden Programme auf Lochkarten gestanzt, welche dann von der Rechenmaschine ausgelesen und abgearbeitet wurden. Später konnte man schon Papierstreifen einsetzen, welches schon eine Vereinfachung war. Diese Systeme dienten aber nur dazu, den Rechner in Maschinensprache zu programmieren. Die Maschinensprache ist die Sprache, die jeder Controller und Prozessor direkt versteht. Die Befehle in Maschinensprache sind ganz kleine Anweisungen, welche durch eine Kombination im Binärcode dargestellt wird. Ein Programm, welches z.B. eine kleine Addition ausführt könnte so aussehen:
Befehl im Binärcode |
Funktion |
0001 0011 | Lade Wert 3 in Arbeitsregister |
0010 0010 | Addiere den Wert 2 dazu |
0011 0001 | Gebe Ergebnis an Gerät 1 aus |
Nun kann sich niemand so einen Zahlenjungle merken. Daher hat man sich für die einzelnen Binärfolgen Abkürzungen überlegt, welches die Befehle ungefähr beschreiben. Somit könnte unser Programm so aussehen:
Befehl |
Funktion |
LD 3 |
Lade Wert 3 in Arbeitsregister |
ADD 2 |
Addiere den Wert 2 dazu |
OUT 1 |
Gebe Ergebnis an Gerät 1 aus |
Hier haben wir nun im Grunde die erste Programmiersprache, die Assemblersprache. Hiermit lassen sich schon einigermaßen verständliche Programme schreiben. Um diese Programme dann in Maschinensprache umzuwandeln, benötigt man nun aber einen Übersetzer. Den Assembler. Der Assembler macht aus den Befehlsreihen wieder die Binärreihen, die unser Prozessor zum arbeiten benötigt.
Diese Form der Programmierung hat einen entscheidenden Vorteil. Hier kann man wirklich alles aus dem Prozessor heraus holen, da man diesen komplett kontrollieren kann. Aber gerade dieser Vorteil ist auch ein großer Nachteil. Man kann dem Prozessor z.B. nicht einfach sagen 'Gebe "Temperatur zu niedrig" auf dem Terminal aus, sondern, man muss ihm noch sagen, wo, in welcher Form, mit welcher Geschwindigkeit und dann auch nicht als ganzen Text, sondern immer ein Zeichen nach dem anderen. Auch um alle anderen Eigenschaften eines Prozessors muss sich der Programmierer kümmern.
Da die Assemblerprogrammierung auf Dauer sehr Zeitintensiv und sehr komplex ist, hat man so genannte Hochsprachen entwickelt welche Standardaufgaben eines Prozessors in kleine Module, so genannte Routinen, packt und wo dann später in einem Programm nur noch ein Befehl nötig ist. Die Ausgabe von "Temperatur zu niedrig" kann dann evtl. durch einen Befehl wie 'PRINT "Temperatur zu niedrig"' erfolgen und der Prozessor gibt den Text auf den Terminal aus.
Damit die CPU auch das macht, was sie soll bei einer entsprechenden Anweisung ist ein System nötig, welches die Anweisungen vom Benutzer in Maschinensprache umwandelt. Also einen Übersetzer. Hier unterscheidet man zwei große Gruppen:
Interpreter
Zum Einen kann man so genannte Interpreter. Hier wird jeder Befehl übersetzt und in einer kleinen Bibliothek nachgesehen, wo im Programmspeicher sich die entsprechende Routine für z.B. 'PRINT' befindet. Diese wird dann aufgerufen. Trifft der Interpreter wieder auf diese Anweisung, muss der Interpreter wieder 'PRINT' erkennen, nachschauen, wo sich diese befindet und ausführen. Diese Prozedur kostet verständlicherweise recht viel Zeit.
Interpreter haben aber auch den Vorteil, dass man 'Live' programmieren kann. Man also nicht nach jeder Änderung eines Programms, dass Programm übersetzen und in den ROM des Prozessors schreiben muss. Sehr beliebt waren Interpreter in der großen Zeit der Heimcomputer mit dem C64, Amstrad/Schneider CPC, Sinclair Spectrum usw. Diese Computer hätten wohl nie so einen immensen Erfolg gehabt, wenn man erst einmal ein Entwicklungssystem benötigt hätte um auch nur dass Ergebnis von '2+3' ausrechnen zu können.
Compiler
Will man schnellere Programme schreiben, sich aber Assembler nicht antun möchte, hat man noch die Möglichkeit, auf einen Compiler zurück zu greifen. Compiler arbeiten, im Gegensatz zu den Interpretern, nicht dauerhaft auf einem Rechnersystem, sondern werden nur ausgeführt wenn diese benötigt werden.
Bei einem Compiler wird unsere 'PRINT'-Anweisung im endgültigen Maschinenprogramm durch ein Sprungbefehl ersetzt. Somit entfällt hier das wiederholte erkennen und nachschlagen der entsprechenden Anweisung. Das endgültige Maschinenprogramm, welches vom Compiler erstellt wurde, besteht dann zum größten Teil aus einer Reihe von Sprungbefehlen. Zum Maschinenprogramm wird nur noch die Befehlsbibliothek hinzugefügt (gelinkt) und das Programm kann im Controller seinen Dienst aufnehmen. Es arbeitet dann um einiges Schneller, als ein gleichwertiges Programm welches durch einen Interpreter ausgeführt wird.
Das zufügen von Bibliotheken, birgt auch noch einen immensen Vorteil. Dadurch ist es möglich, dass man Bibliotheken hinzufügen kann, die für spezielle Aufgaben gedacht sind. Soll der Controller z.B. ein bestimmtes Display ansteuern, wird einfach eine Bibliothek eingebunden, welche die Funktionen dieses Displays enthält.
Auf dem Markt gibt es etliche verschiedene Compiler, für diverse Programmiersprachen. Welchen Compiler man verwendet, hängt im groben vom persönlichen Geschmack ab. Einige Programmiersprachen möchte ich hier kurz vorstellen.
Die gängigsten Programmiersprachen
Basic
Die Programmiersprache mit dem größten Bekanntheitsgrad ist wohl Basic (Beginners All Surpose Instruction Code). Wie der Name schon sagt, ist Basic eine sehr leicht zu erlernende Programmiersprache. Die meisten Befehle erklären sich fast von alleine. Dies war wohl auch der Grund, warum die meisten Heimcomputer Basic in einer Interpreter-Version 'On-Board' hatten.
Für den AVR ist die bekannteste Basic-Version BASCOM, welches auch auf diesen Seiten verwendet wurde. BASCOM stellt dabei einen Compiler da, welches man beim entwickeln auch schnell merkt. Man muss jedes Mal, bevor das Programm übertragen werden kann, das Programm erst kompilieren lassen.
Beispiel:
Dim Cnt
For Cnt=1 To 10 Print "Durchlauf:";Cnt Next |
Pascal
Pascal gibt es nur in Compiler-Versionen. Interpreter sind aufgrund der Struktur auch gar nicht möglich. Bei Pascal wird man automatisch angehalten, strukturiert programmieren. Durch diesen 'Zwang' ist es auch möglich, dass ein sehr kompakter Code erzeugt wird.
Beispiel:
Procedure CountLoop Var Cnt:Byte; Begin For Cnt:=1 To 10 Do Begin Write('Durchlauf:',Cnt); End; End; |
C
Sehr weit verbreitet hat such auch die Sprache C. Auf dem AVR gibt es auch diverse C-Varianten. Auch die meisten Programme auf dem PC wurden in dieser Sprache entwickelt. C ist in der Struktur ähnlich wie Pascal, wirkt für dem Anfänger aber teilweise etwas 'kryptisch' bedingt dadurch, dass die Sprache viel mit Sonderzeichen arbeitet.
Beispiel:
Void CntLoop(Void) { Byte Cnt;
for (Cnt=1; Cnt<=10; Cnt++) { Printf('Durchlauf:',Cnt); } } |