C64 Programm aus Basic heraus starten

Wäre es nicht schön, wenn man sein fertiges Maschinen-Programm (.prg) direkt von Basic aus starten könnte, ohne sich die Einsprungadresse merken zu müssen? Sprich, wir müssen uns nicht mehr den „SYS {Adresse}“-Befehl merken sondern starten das Programm einfach mit RUN. Nachfolgend eine kurze Erklärung, wie das umgesetzt werden kann.

Wenn unser Programm den notwendigen SYS-Befehl zu Beginn des Quellcodes in den Basic-Speicher schreibt, reicht ein RUN aus um an die richtige Stelle im Speicher zu springen und das eigentliche Programm auszuführen. Schauen wir uns dazu an, wie der Basic-Speicher ab Adresse 2048 ($0800) aufgebaut ist und funktioniert. Wir stellen uns dazu vor, dass wir folgende Basic-Zeile eingegeben haben:

10 POKE 53280,1

Führt man dieses kleine Basic-Programm mit dem Befehl RUN aus, so interpretiert der Basic-Interpreter die Zeile Zeichen für Zeichen und startet danach den passenden Maschinencode, in diesem Fall zum Ändern der Rahmenfarbe (boardercolor) in Adresse 53280 ($D020) auf den Wert 1. Mit einer einfachen FOR-Schleife lesen wir nun den Inhalt des Basic-Speichers aus, ohne dass wir dafür einen Maschinensprache-Monitor einsetzen müssen:

FOR A=1 TO 16: PRINT PEEK(2048+A): NEXT A

Wie die Zahl 16 unserer FOR-Schleife zu bestimmen ist, erkläre ich weiter unten. Das Ergebnis wird so aussehen:

Wir müssen nun verstehen, welche Bedeutung die Zeichen 15 bis 0 im Basic-Speicher haben.

AdresseZeichenBedeutungKommentar
2049 ($0801)15 ($0f)$080fZeiger auf nächste Zeile, low-order byte
2050 ($0802)8 ($08)$080fZeiger auf nächste Zeile, high-order byte
2051 ($0803)10 ($0a)0010Zeilennummer, low-order byte
2052 ($0804)0 ($00)0010Zeilennummer, high-order byte
2053 ($0805)151 ($97)POKEToken-Code für den Befehl „POKE“
2054 ($0806)32 ($20)SPACELeerzeichen
2055 ($0807)53 ($35)„5“PETSCII für das Zeichen „5“
2056 ($0808)51 ($33)„3“
2057 ($0809)50 ($32)„2“
2058 ($080a)56 ($38)„8“
2059 ($080b)48 ($30)„0“
2060 ($080c)44 ($2c)„,“
2061 ($080d)49 ($31)„1“PETSCII für das Zeichen „1“
2062 ($080e)0 ($00)TermTerminierung der Basic-Zeile
2063 ($080f)0 ($00)EndEnde des Basic-Programms, Byte 1
2064 ($0810)0 ($00)EndEnde des Basic-Programms, Byte 2

Der Basic-Speicher startet also mit einem Zeiger auf die nächste Basic-Zeile ($080f), die in unserem Beispiel aus zwei terminierenden Nullen ($00) besteht. Die Zeilennummer ist wie die Endadresse eine 16-bit-Zahl und ist deshalb auf dem C64 in Low-Byte, High-Byte getrennt in zwei 8-bit-Adressen abgespeichert.
An Adresse $0805 folgt der eigentliche Basic-Befehl „POKE“, der vom C64 als ein 1-byte-Token abgespeichert wird, in diesem Fall $97. danach folgen die ASCII-Codes (PETSCII) unserer übrigen Zeichen. Token-Codes und PETSCII-Codes lassen sich einfach in Tabellen nachlesen.

Nun zu unserem echten Anwendungsfall. Unser Programm startet ab Adresse 4096 ($1000). Wir müssen also das Basic-Programm „10 SYS 4096“ in den Basic-Speicher schreiben und können anschließend mit RUN unser Programm ausführen lassen. Unser Assembler-Code dafür sieht so aus:

     *= $0801
     .byte $0f,$08,$0a,$00,$9e,$20
     .byte $34,$30,$39,$36,$00,$00
     .byte $00
     *= $1000
     ; hier steht unser Programm
     rts

Ab Adresse 2049 ($0801) schreiben wir 13 Bytes in den Basic-Speicher, die unserer Zeile „10 SYS 4096“ entsprechen, terminiert mit einem Zeilenende $00 sowie zwei Null-Bytes. In diesem Fall ist der Token-Code für den Befehl „SYS“ 158 ($9e). $080f ist der Zeiger auf die Endadresse im Speicher, hier die erste Adresse der ersten Doppelnull.
Wenn wir dieses Assembler-Programm kompiliert als .prg Datei gespeichert haben, können wir anschließend das Programm laden und einfach mit RUN ausführen.

Schreibe einen Kommentar

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