Wie können die nur 16 Instuktionen des RIM Loaders den Lochsreifen verarbeiten und erst die Startsequenz (leader), dann Adressen und Daten und schliesslich die Schlusskennung (trailer) verarbeiten?
Register
Die PDP-8 hat nur ein einziges universelles Register in der CPU, den AC (Akkumulator). Ausserdem gibt es das sogenannte Link Bit (L).
Die DEC Dokumentation zeigt normalerweise den AC die Bitpositionen aufsteigend (links ist das höherwertigste Bit “0”, rechts dann das niederwertigste), was bei mir für einige Verwirrung gesorgt hat. Drum hier mal die für mich logischere Notation mit dem Link bit als dreizehntes Bit “ganz links” (da wir später nach links schieben):
1 1 L 1 0 9 8 7 6 5 4 3 2 1 0
So weit – so gut…
Erste RALly…
Eine weitere Hürde ist die Bedeutung der Mnemonics und der damit verbundenen Aktionen zu verstehen. Ich habe als ausführlichste Quelle das “PDP-8 Programming Manual MACRO-8” zu Rate gezogen. Da wird RAL wie folgt erklärt:
Rotate AC and L left. C(AC) and C(L) are rotated left one place.
C(ACi) => C(ACi-1)
C(AC0) => C(L)
C(L) => C(AC11)
Die Rotation erfolgt über das Link Bit. Unklar ist für mich, ob das L als dreizehntes Bit fungiert, oder eine Kopie des (im Falle von Links-Schieben) höchstwertigen Bits im AC ist. Ich vermute folgendes:
1 1 L 1 0 9 8 7 6 5 4 3 2 1 0 a b c d e f g h i j k l m
Nach RAL:
1 1 L 1 0 9 8 7 6 5 4 3 2 1 0 b c d e f g h i j k l m a
Lass uns das testen! 🙂
Tests in simh
simh (github) ist ein Programm, welches viele alte Minicomputer teilweise inklusive Peripherie emulieren kann. Nach der Installation des simh Pakets kann ich den PDP-8 Emulator mit pdp8 starten und lande dann am simh Prompt.
Für den Test brauchen wir diese 4 Instruktionen:
CLL CLA 7300 / L=0 AC=0 IAC 7001 / AC++ RAL 7004 / Rotation nach links HLT 7402 / Halt
Und für simh folgende Kommandos:
- id – interactive deposit: Werte im Speicher deponieren, akzeptiert auch Mnemonics
- ex – examine: Register, Flags, Speicherinhalte anzeigen
- go – Programm starten
Testlauf:
PDP-8 simulator V3.8-1 sim> id 20-30 20: cll cla 21: iac 22: ral 23: ral 24: ral 25: hlt 26: sim> sim> ex l,ac,20-26 L: 0 AC: 0000 20: 7300 21: 7001 22: 7004 23: 7004 24: 7004 25: 7402 26: 0000
Das Programm liegt also ab 0020 im Speicher, und wir springen es an:
sim> go 20 HALT instruction, PC: 00026 (AND 0) sim> ex l,ac L: 0 AC: 0010
Wie erwartet ist der Wert im AC jetzt 000 000 001 000, also (1<<3). Wir können jetzt einfach wieder irgendwo ins Programm reinspringen um den AC weiter zu schieben:
sim> go 22 HALT instruction, PC: 00026 (AND 0) sim> ex l,ac L: 0 AC: 0100 sim> go 22 HALT instruction, PC: 00026 (AND 0) sim> ex l,ac L: 0 AC: 1000 sim> go 22 HALT instruction, PC: 00026 (AND 0) sim> ex l,ac L: 1 AC: 0000 sim> go 22 HALT instruction, PC: 00026 (AND 0) sim> ex l,ac L: 0 AC: 0004
Hier ist gut zu sehen, wie das gesetzte Bit vom AC ins L geschoben wird und von da wieder in den AC zurück. Passt!
Analyse des RIM Laders
Schauen wir uns kurz die ersten Progrmamzeilen des RIM Laders an:
- Das erste Kommando (KCC) löscht L und AC,
- dann wird die erste Lochreihe eingelesen (KRB). Channel 1..8 landen im AC 0..7.
- Mit den Schiebe-Operationen und erneutem Laden liegen schilesslich die beiden 2×6 Bit “Nutzdaten” im AC,
- die schlussendlich im Speicher abgelegt werden.
Ich habe die 8 Kanäle des Lesegeräts mit den ZIffern 8…1 im AC/L eingetragen und beobachte die Schiebeaktionen:
L 1 1 ACCU L 1 0 9 8 7 6 5 4 3 2 1 0 - ----------------------- KCC ? 0 0 0 0 0 0 0 0 0 0 0 0 KRB ? 0 0 0 0 8 7 6 5 4 3 2 1 CLL 0 RTL 0 0 0 8 7 6 5 4 3 2 1 0 0 RTL 0 8 7 6 5 4 3 2 1 0 0 0 0 ... RTL 7 6 5 4 3 2 1 0 0 0 0 0 8 ^ ^ ^ ^ ^ ^ KSF 7 0 0 0 0 8 7 6 5 4 3 2 1 ^ ^ ^ ^ ^ ^
Damit haben wir aus den zwei Lochsteifen-Reihen 4×3 Bits eingelesen, die abhängig von den beiden “header”-Bits entweder als Adresse oder Daten behandelt werden:
11 10 9 8 7 6 5 4 3 2 1 0 AC addr1 addr2 addr3 addr4