HOAsm, der HaDes Object Assembler
Eingabeformat
Das HaDes Object Assembler Format interpretiert jede Eingabedatei
als eine Ansammlung von Linker-Symbolen, die als Plain Text geschrieben
sind - also Dezimal- bzw. Hexadezimalwerte für Datensymbole
(entsprechend globalen Variablen) und Assemblertext für
Codesymbole (entsprechend Funktionen).
Die Eingabedatei wird assembliert und der erzeugte Objektcode in
HaDes Objects (HO-Datei) abgelegt.
Überblick
Die Struktur einer HOA-Datei lässt sich leicht an einem
Beispiel zeigen, das alle wichtigen Syntaxelemente enthält. Alle
Befehle
des HaDes Befehlssatzes können
hierbei verwendet werden.
Die Eingabe des Assemblercodes wird durch die bequemen Makros und
sonstige Komfortfunktionen erleichtert.
@inc "incl.hoa" @def sp "r3" @mac rem { div @1, @2, @3 mod @1 @} @data my_var_name { #1, #12h, #0x12, #-12 @} @code my_func_name { @ldef temp "r5" load @temp, @sp, #2 @call rem @temp r3 r4 loop: dec @temp bnez @temp, #loop ret r2 @}
Details
Besonders hervorzuheben sind folgende Funktionen:
- Volle Unterstützung von Objects. Eine Assemblerdatei
besteht bei Hoa aus einer Ansammlung von Code- und Datenblöcken,
die jeweils zu Symbolen umgewandelt werden.
- Verknüpfungen zu anderen Symbolen (diese
entsprechen externen Linker-Referenzen und treten vor allem bei
Funktionsaufrufen auf) werden folgendermaßen notiert: jal
@ret, *codename bzw. für Datensymbole load r2, r0,
*d*dataname. Im letzten Beispiel würde übrigens
eine Warnung ausgegeben, wenn man die Referenz auf das Datensymbol
nicht mit dem Register r0 verknüpft. Allerdings kann das auch
gewollt sein, wenn man z.B. auf ein Array über einen variablen
Index (der in einem Register gehalten wird) zugreifen möchte.
- Weak linking. Optional ist das Statement @weak
symname #DEFAULT_LABEL irgendwo innerhalb des Codeblocks erlaubt.
Dann werden die Referenzen auf symname mit der
Weak-Linking-Adresse #DEFAULT_LABEL (die ein Label sein muss)
versehen. Das geht nur (und macht auch nur Sinn) für Codesymbole.
Dies führt dazu, dass der Linker, falls das Symbol symname
nicht gefunden wird, keinen Fehler ausgibt, sondern einfach eine
Referenz auf die Weak-Linking-Adresse #DEFAULT_LABEL setzt.
- Labels gelten auch nur code-block-intern. (Der
Linker würde sich sowieso beschweren, und es würde auch nicht
funktionieren). Damit kann man aber zumindest für Labels in
anderen Funktionen auch den gleichen Namen wiederverwenden.
- Mit Hilfe lokaler Defines @ldef name
"replaced-by-text", die nur innerhalb eines Symbols (genau gesagt,
bis zum nächsten @}) gelten, können lokale
Registervariablen in Codesymbolen angenehm benannt werden.
- Volle Unterstützung von Includes. Man kann seinen
Code über mehrere Dateien verteilen und dann alles
zusammeninkludieren, wobei die andere Datei im Volltext eingefügt
wird.
- Ausserdem werden sämtliche Pseudoinstructions wie
LDUI, LDSI, LD, JMP, und vor allem natürlich INC und DEC
unterstützt.
- Arithmetik mit zwei Operanden. Zusätzlich zur
nativen Drei-Adress-Arithmetik der HaDes XP wird auch
Zwei-Adress-Arithmetik unterstützt, was manchmal Schreibaufwand
sparen kann. Dies funktioniert für alle arithmetischen, logischen
und Condition-Check (Sxx)Operationen, und zwar jeweils in der
Register- bzw. Immediate-Version. Letztlich wird nur der WOP auf den
AOP kopiert.
Es geht nun also nicht nur wie schon immer
add r1, r2, r3 bzw. add r1, r2, #87
sondern auch
add r1, r2 bzw. add
r1, #87
was dann nichts anderes bedeutet als
add r1, r1, r2 bzw. add r1, r1, #87.
HLink, der HaDes Linker
Die Aufgabe des HaDes Linkers ist es, Objektcode, der u. U. in
unterschiedlichen Programmiersprachen geschrieben wurde, zu einem
einheitlichen Programm zusammenzubinden. Dabei werden externe
Referenzen (z.B. Funktionsaufrufe und globale Variablen) aufgelöst
und nicht benötigter Code wird entfernt. Hierzu wird wie folgt
vorgegangen:
- Alle Symbole aus den Eingabe-Objektdateien (HO) werden
eingelesen.
- Das Codesymbol __init wird gesucht. Es muss stets
vorhanden sein, da das erzeugte Programm von hier aus starten
wird. (Die HAL stellt eine
zweckmäßige Implementierung von __init bereit, die
nach der Initialisierung des "Betriebssystems" eine benutzerdefinierte main-Funktion
aufruft.)
- Von __init ausgehend werden rekursiv alle Symbolreferenzen
verfolgt und die entsprechenden Symbole als benutzt markiert.
Fehlt eines der referenzierten Symbole und ist es nicht für weak
linking markiert, wird ein Fehler ausgegeben.
- Alle benutzten Symbole werden der Reihe nach auf
aufeinanderfolgende Adressen reloziert. (Codesymbole werden
jedoch vor den Datensymbolen angeordnet, um vom Speicherschutz-Feature
der HaDes XP Gebrauch machen zu können.)
- Die nunmehr bekannten Adressen der Symbole werden bei
allen Symbolreferenzen eingetragen. Weak-Linking Symbole
werden ggf. auf ihre Defaultadresse resolviert.
- Die Ausgabe-Programmdatei (HIX) wird erzeugt,
indem der Code aller Symbole aneinandergehängt wird.
Auch die Debuginformationen aller verwendeten Symbole werden vereinigt
und in der Debug-Datenbank (HDB) abgelegt. Diese wird vom Emulator
verwendet, um das Debugging von HaDes-Programmen zu vereinfachen.
|