CHIP‑8: Teil 2, in welchem das eigentliche Programm vorgestellt wird

Stehen geblieben waren wir bei diesem Computerprogramm für den CHIP‑8:

A2 1E C2 01 32 01 A2 1A D0 14 70 04 30 40 12 00 60 00 71 04 31 20 12 00 12 18 80 40 20 10 20 40 80 10

Es erzeugt ein Zufallslabyrinth so wie dieses hier:

Wie geht das? Wie können ein Haufen Zahlen so etwas erzeugen?

Sie können es natürlich nicht allein, sondern nur, wenn sie einem Computer gefüttert werden, der genau mit diesen Zahlen umgehen kann. Zentral an so einem Computer ist die Recheneinheit (die kann rechnen), dazu kommen der Arbeitsspeicher und Ein- und Ausgabemöglichkeiten. Gesteuert wird das ganze vom Steuerwerk. Ausgabemöglichkeiten für den CHIP‑8 sind der Bildschirm und ein Tonsignal, Eingabemöglichkeiten eine eingeschränkte Tastatur, aber die brauchen wir hier gar nicht. Das kann man sich so vorstellen:

Weil das Laden und Speichern von Daten im Arbeitsspeicher relativ langsam ist, gibt es in manchen Prozessoren spezielle Zwischenspeicher, die bequemer zugänglich sind, Register genannt. Der CHIP-8-Prozessor hat 16 solche Register, mit V0 bis VF bezeichnet. Manche davon haben zusätzliche Funktionen. Insgesamt sieht der Speicher des Systems zum Beispiel so aus:

  • Der Abeitsspeicher ist in Byte-große Häppchen aufgeteilt.
  • Jedes Häppchen kriegt eine fortlaufende Nummer, die Adresse.
  • Die Nummern 0 bis 1FF sind für Kram reserviert.
  • Wenn ein Programm, zum Beispiel MAZE, geladen wird, dann kommt es ab Adresse (hexadezimal) 200 in den Arbeitsspeicher – ich habe das in der Grafik schon mal erledigt.
  • Der interne Programmzähler wird auf 200 gesetzt, das heißt, da wird das Programm beginnen.

Der erste Befehl lautet A21E, dann kommt C201, und so weiter. Aus einem Handbuch zum CHIP‑8 habe ich mir herausgesucht, wofür diese und die anderen Befehle stehen. Meistens stehen die ersten vier Bit, also die erste Ziffer, für die Art des Befehls, quasi das Verb (setze, hole, springe, erhöhe); die anderen zwölf Bit, also Ziffern zwei bis vier, sind Adressen- oder Zahlenangaben, quasi Akkusativ- oder Dativobjekte. Hier sind die Übersetzungen der Befehle:

Also: In Adresse 200–201 steht A21E, das heißt: Schreibe 21E in das I‑Register. Das I steht für Memory Index Pointer, lese ich; später wird mir klar werden, was das bedeutet. Danach wird der Programmzähler erhöht, die Adresse 202–203 wird ausgewertet, wo das C201 bedeutet, dass letztlich in V2 zufällig eine 0 oder eine 1 geschrieben wird. In Adresse 204–205 wird mit 3201 überprüft, ob in V2 – dem Register, in das wir eben geschrieben haben – eine 1 steht: Wenn ja, dann wird die nächste Zeile übersprungen.

Wichtig ist D014 an Adresse 208–209: Hier wird auf den Bildschirm gemalt! Und zwar an die Koordinaten (V0, V1) – in diese Register schreiben wir alsol zumindest in diesem Programm die Position, an die etwas gezeichnet werden soll! Was gezeichnet wird, war mir da noch nicht klar. Gut, vielleicht hätte ich die Anleitung lesen sollen…

Dann wird in Viererschritten die x‑Koordinate erhöht, bis zu dem Höchstwert 40 (=dezimal 64, so viele Pixel gibt es hier in der Breite), dann wieder von vorne angefangen, aber mit jeweils erhöhtem y‑Wert, bis am Ende an der Adresse 218–219 der Befehl 1218 erreicht wird, der besagt, dass das Programm zur Adresse 218 springen soll: eine Endlosschleife.

Unklar waren mir erst die letzten 8 Byte, also die letzten vier Zeilen oben. Meine Interpretation der Zeilen als Befehl machte keinen Sinn. Und das muss sie auch gar nicht: diese Zahlen sollen gar nicht als Befehle interpretiert werden, der Programmzähler wird nie auf ihre Adressen gesetzt, diese Zahlen sind einfach nur Zahlen. Das heißt…

Erinnert ihr euch an das I‑Register, den Memory Index? Und an die Zeile, an die irgendetwas an die Koordinaten (V0,V1) geschrieben werden soll? Tatsächlich passiert bei Ausführung des Befehls D014 Folgendes: “D” kann man sich als “display” merken; “01” bedeutet, dass die x/y‑Koordinaten in V0 und V1 stehen, und die “4” bedeutet, dass an diese Stelle 4 Byte, also 4*8 bit gezeichnet werden sollen – und zwar genau diese 4 Byte, die sich an der Stelle befinden, auf die der Memory Index verweist. Das ist entweder 21E (in Zeile 200–201 festgelegt) oder 21A (in Zeile 206–207 überschrieben). An diesen Stellen – den letzten acht Byte des Programms – werden zwei kleine Bildchen definiert, sogenannte Sprites.

Ab Adresse 21A stehen folgende 4 Bytes:

hex 80, also bin 10000000
hex 40, also bin 01000000
hex 20, also bin 00100000
hex 10, also bin 00010000

Ab Adresse 21E stehen folgende 4 Bytes:

hex 20, also bin 00100000
hex 40, also bin 01000000
hex 80, also bin 10000000
hex 10, also bin 00010000

Und diese Bytes, also eigentlich diese Bits, werden als kleine Bildchen interpretiert:

Diese Bildchen (Sprites) sind immer 8 Pixel breit, aber sie können bis zu 15 Pixel hoch sein – hier sind sie 4 Pixel hoch, weil sie aus vier Byte bestehen. Das Labyrinth braucht nur die linke Hälfte der Sprites, deswegen wird das nächste Sprite ja auch vier Pixel versetzt gezeichnet und überlagert damit die leeren Pixel des Vorgängers.

Und jetzt kann man experimentieren. Die letzten acht Byte des Programmcoes definieren die beiden Sprites. Wenn ich die ersetze durch 80 40 40 80 10 20 20 10, dann sehen die beiden Sprites so aus:

Dann ist das Zufallslabyrinth gar keines mehr:

Oder man setzt den Memory Index Pointer auf 200 statt auf 21A? Dann werden die ersten vier Byte einmal als zwei Befehle, einmals als Sprite interpretiert.

Vielleicht kommt man mal so weit mit einer 12. Klasse? Da macht man Maschinensprache, aber typische Aufgaben wie Multiplikation durch wiederholte Addition und solche Sachen.

Anhang: Warum macht man das so umständlich, mit 3201 statt “if (v2==0)”, wie man das aus Java kennt? Tatsächlich sind diese Zahlen die einzige Sprache, die ein Prozessor versteht, auch heute noch. Alles andere, das auf einem Rechner läuft, wird – vielleicht über mehrere Zwischenstufen – in genau solche Zahlen übersetzt, also in Maschinensprache. Allerdings sind moderne Prozessoren in manchen Aspekten komplexer aufgebaut als der recht primitive CHIP‑8.

5 Antworten auf „CHIP‑8: Teil 2, in welchem das eigentliche Programm vorgestellt wird“

  1. Interessant! Labyrinthe finde ich immer wieder spannend. Diese Art eines zu generieren kannge ich noch gar nicht…

    Zum Thema “Computer auf untester Ebene verstehen” finde ich diese Videoreihe über einen diskret aufgebauten 8‑Bit-Computer sehr gut:
    https://www.youtube.com/watch?v=HyznrdDSSGM&list=PLowKtXNTBypGqImE405J2565dvjafglHU
    Das geht sogar noch einen Schritt weiter und erklärt erst die Hardware und gegen Ende dann auch wie ein Computer die Maschinensprache tatsächlich interpretiert.

  2. Sehr cool. Ich habe erst mal nur reingeschaut, um zu gucken, ob ich überhaupt eine Chance habe, das zu kapieren. Alles Elektrische liegt mir fern, Elektronisches um so mehr. Aber ja, machbar, danke.

  3. Das macht direkt Lust, selber einen Emulator zu schreiben, in Java, in meinem Fall. Das mit dem Stack muss ich mir noch anschauen, aber klingt machbar.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.