(→Compiler: Compiler0.jpg -> Compiler1.png) |
|||
Zeile 4: | Zeile 4: | ||
seltsamer Form doch nur ein 1:1 Bild der Bits und Bytes ist, wie sie dann im Speicher stehen. Und das sind feststehende Daten (wie z.B. Umrechnungs-Tabellen), und | seltsamer Form doch nur ein 1:1 Bild der Bits und Bytes ist, wie sie dann im Speicher stehen. Und das sind feststehende Daten (wie z.B. Umrechnungs-Tabellen), und | ||
das übersetzte Programm. | das übersetzte Programm. | ||
− | |||
− | |||
− | Die Code-Erzeugung geschieht meistens in mehreren Schritten, die oft auch explizit in | + | {| |
+ | |[[Bild:Compiler1.png]] | ||
+ | |- | ||
+ | |<div align="center">Schematischer Ablauf der Compilerung anhand der Beispiele BASCOM, FASTAVR und GCC</div> | ||
+ | |} | ||
+ | |||
+ | Die Code-Erzeugung geschieht meistens in mehreren Schritten, die oft auch explizit in einem sogenannten [[make|"makefile"]] stehen können. | ||
; Precompilerung: Es werden die Anweisung aufgelöst, mit denen der Sourcecode eigentlich erst vollständig wird, wie Makros und symbolische Namen. Meistens sind solche Anweisungen an bestimmten vorangestellten Zeichen erkennbar, wie z.B. "#" (C/C++) und "$" (BasCom). | ; Precompilerung: Es werden die Anweisung aufgelöst, mit denen der Sourcecode eigentlich erst vollständig wird, wie Makros und symbolische Namen. Meistens sind solche Anweisungen an bestimmten vorangestellten Zeichen erkennbar, wie z.B. "#" (C/C++) und "$" (BasCom). | ||
; Compilierung: Der eigentliche Compile-Vorgang, bei dem oft erstmal nur "Objects" erzeugt werden (Das ist zwar schon Maschinencode, aber noch mit vorläufigen Sprung- und Datenadressen). | ; Compilierung: Der eigentliche Compile-Vorgang, bei dem oft erstmal nur "Objects" erzeugt werden (Das ist zwar schon Maschinencode, aber noch mit vorläufigen Sprung- und Datenadressen). |
Version vom 3. Dezember 2005, 21:37 Uhr
Inhaltsverzeichnis
Compiler
Das, was letzlich ein Micro-Controller tut, wird ausschließlich durch das bestimmt, was wir in den Program-Flash reinladen. Üblicherweise ist das eine "*.HEX" Datei, die in etwas seltsamer Form doch nur ein 1:1 Bild der Bits und Bytes ist, wie sie dann im Speicher stehen. Und das sind feststehende Daten (wie z.B. Umrechnungs-Tabellen), und das übersetzte Programm.
Schematischer Ablauf der Compilerung anhand der Beispiele BASCOM, FASTAVR und GCC
|
Die Code-Erzeugung geschieht meistens in mehreren Schritten, die oft auch explizit in einem sogenannten "makefile" stehen können.
- Precompilerung
- Es werden die Anweisung aufgelöst, mit denen der Sourcecode eigentlich erst vollständig wird, wie Makros und symbolische Namen. Meistens sind solche Anweisungen an bestimmten vorangestellten Zeichen erkennbar, wie z.B. "#" (C/C++) und "$" (BasCom).
- Compilierung
- Der eigentliche Compile-Vorgang, bei dem oft erstmal nur "Objects" erzeugt werden (Das ist zwar schon Maschinencode, aber noch mit vorläufigen Sprung- und Datenadressen).
- Linken
- bindet diese Objekte zusammen und ersetzt die verschieblichen Adressen durch absolute Werte
Und eventuell noch
- Konvertieren
- um die endgültige "HEX" File zu erhalten
Varianten der Programmentwicklung
"Echte" Compiler
Das sind zum Beispiel Assembler, Bascom, GCC. Die verhalten sich genau so wie in der Darstellung und erzeugen mehr oder weniger direkt den Maschinen-code für einen ganz konkreten Controller. "FastAVR", den ich aber mangels besserer Kenntnis hier nur erwähnen will, ist wohl eher ein Programm-Generator.
Program-Generator
Es gibt auch die Gruppe der "Programm-Generatoren". Die erstellen als Ergebnis einen Source-Code eine anderen Sprache, den man dann nochmals übersetzen muß. Bei einigen Micro-Controller-Compilern ist es auch so, daß die als Zwischen- oder Nebenprodukt Assemblercode herstellen, den man noch überarbeiten könnte, wenn man das will. Die Tücke dabei ist, daß das aber nicht umgekehrt geht, d.h. bei jeder Änderung der ursprünglichen Source muß man solche Anpassungen nochmal machen.
Virtual Machines
Compiler dieser Kategorie (JAVA) erzeugen ebenfalls Maschinencode, aber für eine Maschine, die es eigentlich garnicht gibt. Auf dem Zielsystem (Prozessor, Controller) läuft dann ein Programm, daß diesen Code zum Laufzeitpunkt auf den realen Maschinencode umsetzt. Der Gedanke ist ja nicht schlecht: Ich kann für alle möglichen Rechner EINE Applikation entwickeln, daß dann ohne weiteres auf jedem x-beliebigen Computer ablaufen kann, für den es dieses "Umsetz"-Programm gibt.
"Basic" Controller
(PICAXE) Auch hier wird in zwei Teilen kompiliert /übersetzt: Erstmal ein Basic-Dialekt in eine Art "Token"-Format (kann man als "Kürzel" bezeichnen). Dieses Format wird dann auf den Controller geladen und hier läuft dann als "Firmware" ein Interpreter, der diese Token dann für den RISC-Controller aufbereitet.
Source Code
Recht grob, aber doch, besteht jedes Programm für jeden Compiler (mit unterschiedlicher Gewichtung) aus drei Teilen:
Definition des Zielsystems
Man muß dem Compiler sagen, für welchen Controller er den Code generieren soll. Meistens durch "Kommandozeilen-Parameter" (GCC) oder "$Regfile= xxx " (Bascom). Die Absicht ist, daß man den restlichen Source-Code nicht ändern muß, wenn man einen anderen Controller verwenden will. Das ist aber schon recht theoretisch, denn so standardisiert, wie es bei den PCs ist (durch das Betriebssystem), sind die Microcontroller beileibe nicht.
Definition der Daten
Hier wird definiert, mit welchen Daten das Programm arbeiten soll. Beim Assembler kann man das auch bleibenlassen, der ist da nicht so heikel, im anderen Extrem, bei den ++ Objekt-orientierten Sprachen, muß hier bereits recht detailliert beschrieben werden, was man braucht und wie man mit diesen Daten im restlichen Programm denn umgehen will.
- Einzelfelder: eines oder mehrere Byte, die zusammen eine bestimmten Datentyp bilden
- Arrays: das sind ein- oder mehrdimensionale Tabellen, wobei die Elemente Einzelfelder, aber auch Strukturen sein können
- Strukturen: Zusammenfassung von Einzelfeldern oder anderen Strukturen zu zusammenhängenden Einheiten
Befehle
Das eigentliche Programm in Form von mehr oder weniger symbolischen und/oder abstrakten Anweisungen. Auch hier gibt es Unterscheidungen
- Anweisungen
Variable = ausdruck
- Verzweigung
GOTO CALL /GOSUB ... RETURN
- Vergleiche
IF (Bedingung) THEN ... ELSE .... END IF
- Auswahl Befehle
SELECT CASE ..... END SELECT
- Wiederholungs-Schleifen
Wichtige Unterscheidung ist, ob die Schleifenbedingung VOR oder NACH den enthaltenen Anweisungen geprüft wird
DO .. WHILE
WHILE ... WEND FOR .. NEXT