Wie schreibe ich ein Toy-Programm? Zurück

Unterschiedliche Darstellung der Toy-Befehle

Binär Hexadezimal Assembler
0000 xxxx xxxx xxxx xxxx $0yyy STO z
0001 xxxx xxxx xxxx xxxx $1yyy LDA z
0010 xxxx xxxx xxxx xxxx $2yyy BRZ z
0011 xxxx xxxx xxxx xxxx $3yyy ADD z
0100 xxxx xxxx xxxx xxxx $4yyy SUB z
0101 xxxx xxxx xxxx xxxx $5yyy OR   z
0110 xxxx xxxx xxxx xxxx $6yyy AND z
0111 xxxx xxxx xxxx xxxx $7yyy XOR z
1000 xxxx xxxx xxxx xxxx $8yyy NOT
1001 xxxx xxxx xxxx xxxx $9yyy INC
1010 xxxx xxxx xxxx xxxx $Ayyy DEC
1011 xxxx xxxx xxxx xxxx $Byyy ZRO
1100 xxxx xxxx xxxx xxxx $Cyyy NOP
1101 xxxx xxxx xxxx xxxx $Dyyy NOP
1110 xxxx xxxx xxxx xxxx $Eyyy NOP
1111 xxxx xxxx xxxx xxxx $Fyyy NOP

Es gibt vier unterschiedliche Möglichkeiten ein Toy-Programm zu schreiben: Die Befehle können sowohl in binärer und in hexadezimaler Schreibweise, als auch in Assembler (= Mnemonic, vgl. Tabelle Befehlssatz des ToyProcessors") kodiert werden. Außerdem gibt es noch die Möglichkeit Pseudo-C-Code zu verfassen.

Die Tabelle "Unterschiedliche Darstellung der Toy-Befehle" umfasst die Binär-, Hexadezimal- und Assemblervarianten. Die "xxxxxxxxxxxx" kodieren die Adresse für den jeweiligen OP-Code in binär, "yyy" stehen für die Adresse in hexadezimal und "z" gibt die Adresse als Dezimalzahl an.

Wir werden nun das Programmieren mit den Toy-Befehlen an einigen Beispielen üben. Am Ende dieses Absatzes werden wir dann noch auf die Einschränkungen des Pseudo-C-Codes eingehen.

Binär-, Hexadezimal- und Assemblerprogrammierung

Format: Das Toy-Programm sollte in einem simplen Texteditor geschrieben werden. Die Textdatei sollte die Endung *.toy bekommen.

Code: Die einzelnen Befehle werden alle untereinander in jeweils neue Zeilen geschrieben. In den RAM werden sie in der gleichen Reihenfolge geschrieben, angefangen bei der nullten Speicherzelle. Wie man der Tabelle "Unterschiedliche Darstellung der Toy-Befehle" entnehmen kann, sind die verschiedenen Varianten (binär, hexadezimal und Assembler) äquivalent, daher können diese im Source-Code gemischt werden. Beispielsweise liefern somit die folgenden drei Toy-Programme zum Subtrahieren der Werte aus RAM[11] und RAM[22] dasselbe Ergebnis:

Binär Hexadezimal   Assembler   Gemischt
0001 0000 0000 1011   $100B LDA 11 0001 0000 0000 1011
0100 0000 0001 0110 $4016 SUB 22 $4016
0000 0000 0000 1011 $000B STO 11 STO 11

RAM-Settings: Um mit konkreten Werten zu rechnen, können diese direkt in den RAM geschrieben und die RAM-Adresse für die jeweiligen Rechenoperationen benutzt werden. Angenommen, wir würden bei unserem Beispiel gerne 42 von 84 abziehen, so sähe das ganze wie in der folgenden Tabelle aus: Die ersten zwei Zeilen des jeweiligen Programms setzen RAM[11]=84 und RAM[22]=42, das Ergebnis wird wie oben in RAM[11] gespeichert. Die einzige Einschränkung bezüglich RAM-Setting ist, dass Werte nur in Speicherzellen geschrieben werden dürfen, welche eine höhere Nummer als die Anzahl an OP-Codes im Toy-Programm haben. Es wäre hier also nicht erlaubt gewesen, die Speicherzellen 0, 1 oder 2 zu beschreiben, da das Toy-Programm insgesamt 3 OP-Codes beinhaltet.

Binär Hexadezimal   Assembler   Gemischt
: 0000 0000 0000 1011 : 0000 0000 0101 0100   : $00B : $054 : 11 : 84 : $00B : $054
: 0000 0000 0000 1011 : 0000 0000 0101 0100 : $016 : $02A : 22 : 42 : 22 : 42
0001 0000 0000 1011 $100B LDA 11 0001 0000 0000 1011
0100 0000 0001 0110 $4016 SUB 22 $4016
0000 0000 0000 1011 $000B STO 11 STO 11

Endlosschleife: Um zu verdeutlichen, dass ein Prozessor niemals aufhört zu arbeiten, muss jedes Toy-Programm in einer Endlosschleife enden. Dies kann durch das Hinzufügen eines "ZRO" (= Setze den ACCU auf Null) und eines "BRZ <einen Befehl davor>" (= Springe zum Befehl davor, d.h. zu ZRO, falls der ACCU Null ist) am Ende des Toy-Programms erreicht werden.

Binär Hexadezimal   Assembler   Gemischt
: 0000 0000 0000 1011 : 0000 0000 0101 0100   : $00B : $054 : 11 : 84 : $00B : $054
: 0000 0000 0000 1011 : 0000 0000 0101 0100 : $016 : $02A : 22 : 42 : 22 : 42
0001 0000 0000 1011 $100B LDA 11 0001 0000 0000 1011
0100 0000 0001 0110 $4016 SUB 22 $4016
0000 0000 0000 1011 $000B STO 11 STO 11
1011 0000 0000 0000 $B000 ZRO 1011 0000 0000 0000
0010 0000 0000 0011 $2003 BRZ 3 $2003

Kommentare: Kommentare können mit "#" gesetzt werden. Wir kommentieren hier nun zur Veranschaulichung die Assembler-Variante unteres Toy-Programms - für die anderen Varianten funktioniert das Kommentieren analog:

#RAM-Settings
:11:84 #RAM[11] wird auf den Wert 84 gesetzt
:22:42 #RAM[22] wird auf den Wert 42 gesetzt

#Subtraktion der beiden Werte
LDA 11 #Lädt 84, den Wert aus RAM[11]
SUB 22 #Subtrahiert davon 42, den Wert aus RAM[22]
STO 11 #Speichert das Ergebnis in RAM[11]

#Endlosschleife
ZRO   #Setzt den Accu auf Null
BRZ 3 #Springt zurück zum ZRO Befehl in RAM[3]

Variablen: Im Assemblercode können anstatt RAM-Settings auch Variablen deklariert werden. Diese werden dann vom ToyProcessor automatisch in Speicherzellen nach den OP-Codes geschrieben. Variablen werden wie folgt deklariert: "<Variablenname> = <Wert>". Variablennamen dürfen aus Groß- und Kleinbuchstaben, sowie Zahlen bestehen, müssen jedoch mit einem Buchstaben beginnen und aus mindestens 3 Zeichen bestehen. Die zugewiesenen Werte dürfen Binär-, Dezimal- oder Hexadezimalzahlen sein. Sollten RAM-Settings und Variablendeklarationen gleichzeitig in einem Toy-Programm vorkommen, so ist darauf zu achten, dass die Variablen direkt hinter dem Programm abgelegt werden. Ist das Programm z.B. 3 Zeilen lang (Adresse 0-2) und man nutzt 2 Variablen, so ist der nächste freie Speicherbereich bei Adresse 5. Des Weiteren sollte der Assembler mit Variablen und später auch Labels nicht mehr mit binärem oder hexadezimalem Code gemischt werden. Sollte man dennoch mischen wollen, so ist auf den Speicherbereich der Variablen zu achten. Hier das obige Beispiel mit Variablendeklarationen anstatt den RAM-Settings:

#Variablendeklarationen
varA = 84 #Deklariere eine Variable mit dem Namen a und dem Wert 84
varB = $2A #Deklariere eine Variable mit dem Namen b und dem Wert 0x2A = 42

#Subtraktion der beiden Variablenwerte
LDA varA #Lädt die Variable a mit dem Wert 84
SUB varB #Subtrahiert davon die Variable b mit dem Wert 42
STO varA #Speichert das Ergebnis in Variable a

#Endlosschleife
ZRO   #Setzt den Accu auf Null
BRZ 3 #Springt zurück zum ZRO Befehl in RAM[3]

Labels: Labels dienen als Anhaltspunkte, wohin ein Sprungbefehl im Code zurückkehren muss. Labels können also anstatt der RAM-Adresse des Befehls, zu dem zurückgesprungen werden soll, angegeben werden. Labels werden im Stil von: "<Labelname>:" deklariert. Labelnamen dürfen Groß- und Kleinbuchstaben und Zahlen enthalten, müssen aber auch mit einem Buchstaben beginnen und aus mindestens 3 Zeichen bestehen. Sollte man vorhaben, Code zu mischen (nicht empfehlenswert), so ist darauf zu achten, dass ein Label auf die Adresse direkt hinter dem Label zeigt, sprich die nächste Anweisung. Labels werden nicht nicht als Anweisung gezählt. Unsere Endlosschleife könnten wir mit Hilfe von Labels also wie folgt gestalten:

#Endlosschleife
loop:
    ZRO      #Setzt den Accu auf Null
    BRZ loop #Springt zurück zum ZRO Befehl, da dieser nach dem Label "loop" kommt