ws-Assembler - Syntax und Befehle

Inhaltsverzeichnis[Verbergen]

1. Kommentare

So wie jede andere Programmiersprache auch, habe ich natürlich auch eine Syntax für Kommentare eingebaut. Wir müssen nur eine Raute (#) hinschreiben und alles was danach bis zum Zeilenende folgt ist ein Kommentar. Aufpassen müssen wir deshalb auch bei Strings, da der Kompiler leider nicht erkennen kann ob die Raute innerhalb oder außerhalb des Strings steht, so dass wir besser keine Raute in Strings verwenden.

2. Die Befehle

Wie bei jeder Sprache gibt es natürlich eine Reihe von Befehlen, aus denen man sein Programm zusammenstellen kann. Wir werden uns jetzt einfach alle Befehle einmal kurz anschauen. Manche Befehle erwarten einen Parameter andere wiedrum nicht. Erkennen können wir das, wie nur unschwer zu eraten an der Spalte Argument. Wenn ein Datentyp dasteht dann ist das Argument Pflicht, ist es in eckigen Klammern dann ist es optional und wenn nur ein '-' drinnen steht, dann darf man kein Argument angeben.

2.1. Der Stack

Der Stack kann theoretisch beliebig viele Zahlen mit unterschiedlichen Bitbreiten aufnehmen. In der Praxis wird dies natürlich durch den Interpreter eingeschränkt. Solange man aber in einem gewissen Rahmen bleibt sollte es keine Probleme geben. Für die Verwendung des Stacks gibt es ein paar Befehle, die eigentlich selbsterklärend sein sollten.

BefehlArgumentBeschreibung
push Integer Eine Zahl auf den Stack legen.
pushs String Einen String auf den Stack legen (Wird Null-terminiert).
pop - Den obersten Wert vom Stack entfernen.
duplicate - Den obersten Wert auf dem Stack duplizieren.
swap - Die obersten beiden Werte vertauschen.

Zu beachten ist vielleicht noch das Strings immer in doppelte Anführungszeichen ('"') geschrieben werden müssen und keine solchen Anführungszeichen beinhalten dürfen, selbst wenn sie escaped sind.

2.2. Heap Zugriff

Da man im Stack bei zu vielen Werten schnell den Überblick verlieren kann gibt es noch einen Heap, auf dem man Werte besser auch etwas länger speichern kann. Mit den vorhandenen Befehlen kann man direkt auf eine bestimmte Stelle im Heap schreiben und auch wieder von ihr lesen. Der Paramater gibt dabei die zu verwendende Speicherstelle an.

BefehlArgumentBeschreibung
store [Integer] Einen Wert an die angegebene Stelle in den Heap schreiben.
retrieve [Integer] Den Wert der angegebenen Adresse im Heap holen.

Das die Argumente eingeklammert sind liegt daran das sie optional sind. Sollte man sie weglassen, dann wird einfach der oberste Wert des Stacks als Adresse genommen und anschließend vom Stack entfernt.

2.3. Ein-/Ausgabe

Um mit dem Anwender auch kommunizieren zu können gibt es noch vier Befehle mit denen man Zahlen und Ascii-Zeichen einlesen und auch ausgeben kann:

BefehlArgumentBeschreibung
putc - Als Ascii-Zeichen ausgeben.
putn - Als Zahl ausgeben.
getc [Integer] Ein Zeichen einlesen.
getn [Integer] Eine Zahl einlesen.

Beim Einlesen kommt das Zeichen oder die Zahl in den Heap. Die Addresse ist dabei wieder entweder der oberste Wert am Stack oder das optional übergebene Argument.

2.4. Arithmetische Operationen

Für die verschiendensten Berechnungen gibt es noch die vier Grundrechenarten plus dem Modulo. Das Argument der Befehle ist immer optional. Das heißt wenn kein Parameter angegeben wird, dann wird die Operation auf die beiden obersten Element des Stacks angewendet, ansonsten wird der entsprechende Operator auf das oberste Element das Stacks und den Parameter angewendet. Der zuletzt genannete Parameter steht dabei immer auf der rechten Seite. Alle auf dem Stack beteiligten Werte werden entfernt und der neue Wert wird wieder auf den Stack gelegt.

BefehlArgumentBeschreibung
add [Integer] Addieren
sub [Integer] Subtrahieren
mul [Integer] Multiplizieren
div [Integer] Dividieren (Ganzzahldivision)
mod [Integer] Modulo

2.5. Programmfluss

Um den Programmfluss zu steuern gibt es die Möglichkeit sogenannte Labels anzulegen. Diese sind einfach eine Namensstring gefolgt von einem Doppelpunkt. Dannach kann man mit den bereitgestellten Sprungbefehlen zu den Angegebenen Labels springen.

BefehlArgumentBeschreibung
- Label: Ein Sprungziel oder eine Unterroutine markieren.
call Label Subroutine aufrufen.
jmp Label Sprung zu Label.
jz Label Sprung zu Label wenn der oberste Wert am Stack null ist.
jn Label Sprung zu Label wenn der oberste Wert am Stack negativ ist.
return - Subroutinen beenden und zum Aufrufer zurückspringen.
exit - Das Programm beenden.

Bei den bedingten Sprüngen darf man nicht übersehen, dass der oberste Wert am Stack dabei gelöscht wird. Wenn man mit 'call' zu einem Label springt, dann springt man mit 'return' wieder zu der Stelle im Code nach dem Aufrufer zurück.

2.6. Include

Da es doch immer wieder verwendete Funktionen gibt und auch lange Dateien recht leicht unübersichtlich werden können, habe ich noch einen Include-Befehl eingebaut mit dem man andere ws-asm Dateien einbinden kann. Diese Dateien sollten auf '.wsal' enden, was für "ws-assembler library" steht. Da es keine Suchpfade oder sonst irgendetwas in der Art gibt müssen alle Includedateien im selben Verzeichnis wie das Verzeichnis in dem man sich beim Kompilieren befindet sein oder die Pfadangabe relativ dazu sein.

BefehlArgumentBeschreibung
include String/Filename Eine Quellcodedatei einbinden.

Wenn man den Namen ohne Anführungszeichen angibt, dann darf man nur die üblichen Zeichen für Dateinamen (A-Za-z_0-9) verwenden. Dabei darf man auch keine Dateiendung angeben, da diese automatisch mit .wsal ergänzt wird. Wenn man den Namen hingegen in Anführungszeichen setzt darf man auch Pfadangaben verwenden und muss aber auch die Dateiendung angeben.

Aktualisiert ( Dienstag, 09. Februar 2010 um 15:14 Uhr )