Als typischer Vertreter einer einfachen Registermaschine hat die Minimaschine einen Akkumulator, der bei Rechenoperationen vor der jeweiligen Operation den ersten Operanden und nach Ausführung der Operation das Ergebnis beinhaltet. Bei Speicheroperationen ist er Ziel oder Quelle. Entsprechend ist die Maschine als Ein-Adress-Maschine konzipiert, d. h. die Befehle haben einen Adressteil (in der Regel Speicheradresse oder direkt verwendete Zahl); bei speziellen Befehlen wird der Adressteil nicht benutzt.
Der Assembler erlaubt sowohl absolute Adressierung, d. h. Angabe betroffener Speicherzellen als konkrete Zahlenwerte, als auch symbolische Adressierung. Dabei wird als Adressteil eine Marke (Bezeichner) angegeben; diese Marke ist an anderer Stelle (Programm oder Daten) vereinbart. Der Assembler berechnet dann die Adresse automatisch.
Die Adressierungsarten im Detail:
Durch das Einschalten der Erweiterungen werden neben dem Stackpointerregister und zusätzlichen Befehlen auch weitere Adressierungsarten um Zugriff auf auf dem Stack gespeicherte Werte ermöglicht.
Assemblerprogramme haben einen sehr einfach strukturierten Aufbau. Ein Assemblerprogramm besteht aus einer Folge von Befehlszeilen. Jede Befehlszeile besteht aus einer optionalen Marke, dem Befehl und einem optionalen (vom Befehl abhängenden) Adressteil. Leere Zeilen oder Zeilen, die nur eine Marke enthalten, sind ebenfalls möglich.
Das Zeichen "#" leitet einen Kommentar ein. Kommentare gehen grundsätzlich bis zum Ende der Zeile.
# Algorithmus, um ein Produkt mittels wiederholter Addition zu berechen. LOADI 0 STORE Produkt # Ergebnis vorbesetzen Start: # Start der Wiederholung LOAD Faktor1 JMPNP Ende # Beenden, wenn der Zähler kleiner als 0 geworden ist SUBI 1 # Zähler erniedrigen STORE Faktor1 LOAD Produkt ADD Faktor2 STORE Produkt # Ergebnis erhöhen JMP Start Ende: HOLD # Maschine anhalten # Datenteil Faktor1: WORD 5 # Der erste Faktor dient als Zähler für die Wiederholung der Addition Faktor2: WORD 4 # Der zweite Faktor wird fortwährend addiert Produkt: WORD 0 # Platz für das Ergebnis
In EBNF lässt sich die Syntax der Assemblersprache kurz zusammenfassen. Die Erweiterungen sind kursiv dargestellt.
Programm = {Zeile} . Zeile = [Markenvereinbarung] [Befehl] . Markenvereinbarung = Marke ":" . Marke = ( "A" .. "Z" | "a" .. "z" ) { "A" .. "Z" | "a" .. "z" | "0" .. "9" | "_" | "$" } . Befehl = Operation [ Adresse | "(" Adresse ")" | $Adresse | Adresse(SP) | @Adresse(SP) | $Adresse(SP) ]. Operation = OperationGroß | OperationKlein . OperationGroß = "HOLD" | "RESET" | "NOOP" | "LOAD" | "LOADC" | "STORE" | "ADD" | "SUB" | "MUL" | "DIV" | "DIVU" | "MOD" | "MODU" | "CMP" | "MULH" | "MULHU" | "AND" | "OR" | "XOR" | "NOT" | "SHL" | "SHR" | "SHRA" | "JMPP" | "JMPNN" | "JMPN" | "JMPNP" | "JMPZ" | "JMPNZ" | "JMPV" | "JMPC" | "JMP" | "JGT" | "JGE" | "JLT" | "JLE" | "JEQ" | "JNE" | "JHI" | "JHS" | "JLO" | "JLS" | "ADDI" | "SUBI" | "MULI" | "DIVI" | "DIVUI" | "MODI" | "MODUI" | "CMPI" | "MULHI" | "MULHUI" | "LOADI" | "ANDI" | "ORI" | "XORI" | "SHLI" | "SHRI" | "SHRAI" | "JSR" | "RTS" | "PUSH" | "POP" | "RSV" | "REL" | "CALL" | "RETURN" | "WORD" . OperationKlein = "hold" | "reset" | "noop" | "load" | "loadc" | "store" | "add" | "sub" | "mul" | "div" | "divu" | "mod" | "modu" | "cmp" | "mulh" | "mulhu" | "and" | "or | "xor | "not | "shl | "shr | "shra" | "jmpp" | "jmpnn" | "jmpn | "jmpnp" | "jmpz" | "jmpnz" | "jmpv" | "jmpc" | "jmp | "jgt" | "jge" | "jlt" | "jle" | "jeq" | "jne" | "jhi" | "jhs" | "jlo" | "jls" | "addi" | "subi" | "muli" | "divi" | "divui" | "modi" | "modui" | "cmpi" | "mulhi" | "mulhui" | "loadi" | "andi" | "ori" | "xori" | "shli" | "shri" | "shrai" | "jsr" | "rts" | "push" | "pop" | "rsv" | "rel" | "call" | "return" | "word" . Adresse = Marke | Zahl | HexZahl . HexZahl = "0" ("x" | "X" ) ( "0" .. "9" | "A" .. "F" | "a" .. "f" ) { "0" .. "9" | "A" .. "F" | "a" .. "f" } . Zahl = ( "0" .. "9" ) { "0" .. "9" } .
Die mit "#" eingeleiteten Kommentare treten im Syntaxdiagramm nicht auf, da sie entsprechend den Leerzeichen, Tabulatoren oder Zeilenwechseln bereits bei der Zerlegung des Quelltextes in Terminalsymbole abgearbeitet werden.
Die folgende Tabelle beschreibt die Befehle der Minimaschine geordnet nach Funktionsgruppen. Wiedergegeben sind nur die großgeschriebenen Varianten der Befehlsmnemonics.
Speicherbefehle | |
LOAD adresse | Lädt den Wert von der angegebenen Adresse in den Akkumulator. |
LOADI zahl | Lädt die angegebene Zahl in den Akkumulator, negative Werte sind möglich, Adressen sind nicht zulässig. |
STORE adresse | Speichert den Wert im Akkumulator an der angegebenen Adresse. |
Arithmetikbefehle | |
ADD adresse | Addiert den Wert von der angegebenen Adresse zum Akkumulator. |
SUB adresse | Subtrahiert den Wert der angegebenen Adresse vom Akkumulator. |
MUL adresse | Multipliziert den Wert von der angegebenen Adresse zum Akkumulator. |
DIV adresse | Dividiert den Wert im Akkumulator durch den Wert der angegebenen Adresse. |
MOD adresse | Dividiert den Wert im Akkumulator durch den Wert der angegebenen Adresse und speichert den Rest im Akkumulator. |
DIVU adresse | Dividiert den Wert im Akkumulator durch den Wert der angegebenen Adresse vorzeichenlos. |
MODU adresse | Dividiert den Wert im Akkumulator durch den Wert der angegebenen Adresse vorzeichenlos und speichert den Rest im Akkumulator. |
MULH adresse | Multipliziert den Wert von der angegebenen Adresse zum Akkumulator und speicher die oberen 16 Bit im Akkumulator. |
MULHU adresse | Multipliziert den Wert von der angegebenen Adresse zum Akkumulator vorzeichenlos und speicher die oberen 16 Bit im Akkumulator. |
CMP adresse | Vergleicht den Wert der angegebenen Adresse mit dem Akkumulator und setzt Null- und Negativflag entsprechend. |
ADDI zahl | Addiert den angegebenen Wert zum Akkumulator. |
SUBI zahl | Subtrahiert den angegebenen Wert vom Akkumulator. |
MULI zahl | Multipliziert den angegebenen Wert zum Akkumulator. |
DIVI zahl | Dividiert den Wert im Akkumulator durch den angegebenen Wert. |
MODI zahl | Dividiert den Wert im Akkumulator durch den angegebenen Wert und speichert den Rest im Akkumulator. |
DIVUI zahl | Dividiert den Wert im Akkumulator durch den angegebenen Wert vorzeichenlos. |
MODUI zahl | Dividiert den Wert im Akkumulator durch den angegebenen Wert vorzeichenlos und speichert den Rest im Akkumulator. |
MULHI zahl | Multipliziert den angegebenen Wert zum Akkumulator und speicher die oberen 16 Bit im Akkumulator. |
MULHUI zahl | Multipliziert den angegebenen Wert zum Akkumulator vorzeichenlos und speicher die oberen 16 Bit im Akkumulator. |
CMPI zahl | Vergleicht den angegebenen Wert mit dem Akkumulator und setzt Null- und Negativflag entsprechend. |
Bitmanipulationsbefehle | |
AND adresse | Bitweise logische Und-Verknüpfung des Werts der angegebenen Adresse mit dem Akkumulator. |
OR adresse | Bitweise logische Oder-Verknüpfung des Werts der angegebenen Adresse mit dem Akkumulator. |
XOR adresse | Bitweise logische Exklusiv-Oder-Verknüpfung des Werts der angegebenen Adresse mit dem Akkumulator. |
NOT | Bitweise logische Invertierung des Werts im Akkumulator. |
SHL adresse | Die Bitfolge im Akkumulator wird um die unter der angegebenen Adresse gespeicherten Anzahl Bits nach links geschoben. Frei werdende Bits werden mit 0-Werten belegt. |
SHR adresse | Die Bitfolge im Akkumulator wird um die unter der angegebenen Adresse gespeicherten Anzahl Bits nach rechts geschoben. Frei werdende Bits werden mit 0-Werten belegt. |
SHRA adresse | Die Bitfolge im Akkumulator wird um die unter der angegebenen Adresse gespeicherten Anzahl Bits nach rechts geschoben. Frei werdende Bits werden mit dem ursprünglich vordersten Bit belegt (Vorzeichenerhalt). |
ANDI zahl | Bitweise logische Und-Verknüpfung der angegebenen Zahl mit dem Akkumulator. |
ORI zahl | Bitweise logische Oder-Verknüpfung der angegebenen Zahl mit dem Akkumulator. |
XORI zahl | Bitweise logische Exklusiv-Oder-Verknüpfung der angegebenen Zahl mit dem Akkumulator. |
SHLI zahl | Die Bitfolge im Akkumulator wird um die angegebene Anzahl Bits nach links geschoben. Frei werdende Bits werden mit 0-Werten belegt. |
SHRI zahl | Die Bitfolge im Akkumulator wird um die angegebene Anzahl Bits nach rechts geschoben. Frei werdende Bits werden mit 0-Werten belegt. |
SHRAI zahl | Die Bitfolge im Akkumulator wird um die angegebene Anzahl Bits nach rechts geschoben. Frei werdende Bits werden mit dem ursprünglich vordersten Bit belegt (Vorzeichenerhalt). |
Sprungbefehle | |
JMPP adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation positiv (> 0) war, d. h. weder N noch Z-Flag sind gesetzt. |
JMPNN adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht negativ (≥ 0) war, d. h. das N-Flag ist nicht gesetzt. |
JMPN adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation negativ (< 0) war, d. h. das N-Flag ist gesetzt. |
JMPNP adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht positiv (≤ 0) war, d. h. das N-Flag oder das Z-Flag ist gesetzt. |
JMPZ adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation null (= 0) war, d. h. das Z-Flag ist gesetzt. |
JMPNZ adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht null (≠ 0) war, d. h. das Z-Flag ist nicht gesetzt. |
JMPV adresse | Springt zur angegebenen Adresse, wenn die letzte Operation einen vorzeichenbehafteten Überlauf verursacht hat, d. h. das V-Flag ist gesetzt. |
JMPC adresse | Springt zur angegebenen Adresse, wenn die letzte Operation einen vorzeichenlosen Überlauf verursacht hat, d. h. das C-Flag ist gesetzt. |
JMP adresse | Springt zur angegebenen Adresse. |
Alternative Notation der Sprungbefehle | |
JGT adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation positiv (> 0) war, d. h. weder N noch Z-Flag sind gesetzt. |
JGE adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht negativ (≥ 0) war, d. h. das N-Flag ist nicht gesetzt. |
JLT adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation negativ (< 0) war, d. h. das N-Flag ist gesetzt. |
JLE adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht positiv (≤ 0) war, d. h. das N-Flag oder das Z-Flag ist gesetzt. |
JEQ adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation null (= 0) war, d. h. das Z-Flag ist gesetzt. |
JNE adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht null (≠ 0) war, d. h. das Z-Flag ist nicht gesetzt. |
JOV adresse | Springt zur angegebenen Adresse, wenn die letzte Operation einen vorzeichenbehafteten Überlauf verursacht hat, d. h. das V-Flag ist gesetzt. |
JOC adresse | Springt zur angegebenen Adresse, wenn die letzte Operation einen vorzeichenlosen Überlauf verursacht hat, d. h. das C-Flag ist gesetzt. |
Bedingte Sprungbefehle für vorzeichenlose Arithmetik | |
JHI adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation positiv (> 0) war, d. h. weder C noch Z-Flag sind gesetzt. |
JHS adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht negativ (≥ 0) war, d. h. das C-Flag ist nicht gesetzt. |
JLO adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation negativ (< 0) war, d. h. das C-Flag ist gesetzt. |
JLS adresse | Springt zur angegebenen Adresse, wenn das Ergebnis der letzen Operation nicht positiv (≤ 0) war, d. h. das C-Flag oder das Z-Flag ist gesetzt. |
Sonstige Befehle | |
HOLD | Hält den Prozessor an. Dieser Befehl hat keine Adresse. |
RESET | Setzt den Prozessor auf den Startzustand zurück. Dieser Befehl hat keine Adresse. |
NOOP | Tut einfach nichts (NO OPeration). Dieser Befehl hat keine Adresse. |
LOADC | Lädt den Wert des Carry-Flags in den Akkumulator (1 für WAHR, 0 für FALSE). Dieser Befehl hat keine Adresse. |
Den Stackpointer verändernde Befehle | |
JSR | Springt zu der angegebenen Adresse und speichert den Folge-PC auf dem Stack (Unterprogrammaufruf). Der Stackpointer wird dazu um 1 erniedrigt. |
RTS | Springt zu der Adresse in der Speicherzelle, auf dei der Stackpointer zeigt (Unterprogamrücksprung). Der Stackpointer wird anschließend um 1 erhöht. |
PUSH | Erniedrigt den Stackpointer um 1 und speichert den Akkumulatorwert an der nun durch den Stackpointer gegebenen Adresse. |
POP | Lädt den Inhalt der durch den Stackpointer gegebenen Adresse in den Akkumulator und erhöht den Stackpointer um 1. |
RSV | Erniedrigt den Stackpointer um den im Adressteil gegebenen Wert (Platz reservieren). |
REL | Erhöht den Stackpointer um den im Adressteil gegebenen Wert (Platz freigeben). |
CALL | Alternative Notation zu JSR. |
RETURN | Alternative Notation zu RTS. |
Speicherorganisation | |
WORD zahl | Besetzt eine Speicherzelle mit der angegebenen Zahl, negative Werte sind möglich. |