Chaostreff Tech Talk - Eine Einführung in die Programmierung des C64

Hallo,

der alte Heimcomputer Commodore 64 (kurz C64) aus den 1980er Jahren war zu seiner Zeit beliebt – und ist es für Retro-Fans anscheinend noch heute. Doch wie kann man ihn programmieren?

Um dies näherzubringen, möchte ich gerne einen Vortrag halten mit dem Titel „Eine Einführung in die Programmierung des C64 – Kleine Demoprogramme in BASIC und Assembler“.

Zielgruppe sind alle, die Interesse am C64, seiner Programmierung und/oder an Retro-Computing haben.

Vorausgesetzt an den Zuhörer wird, dass man keine Angst vor Hexadezimalzahlen hat. Aber keine Sorge, es muss nicht groß gerechnet werden, das übernehme ich. Vorteilhaft ist es auch, wenn man schon mal programmiert hat.

Während des Vortrags sollen die gezeigten Programme live auf dem C64-Emulator VICE ausgeführt werden. Die Programme in der Programmiersprache Assembler werden mittels des ACME-Assemblers in Maschinensprache übersetzt. Programmiert werden die Assemblerprogramme mithilfe eines gewöhnlichen Texteditors.

Geplante Vortragsinhalte bezüglich der Programmierung des C64 sind:

  • Hardwareausstattung des C64 (kurz)
  • kleine Demoprogramme in BASIC
  • Speichern auf und Laden von Diskette
  • kleine Demoprogramme in Assembler
  • Start eines Assemblerprogramms aus einem BASIC-Programm heraus
  • Debugging mittels eines Maschinensprachemonitors
  • ein Rechenbeispielprogramm in Assembler

Der Vortrag inklusive der Vorführung der Programme wird etwa eine Stunde dauern. Für eine anschließende Diskussion und Fragen plane ich ebenfalls eine Stunde ein.

Beginn ist am 27.08.2025 um 18 Uhr. Ort ist das FabLab Cottbus.

Ich freue mich auf zahlreiches Erscheinen.

Viele Grüße
toki

2 „Gefällt mir“

Dies ist eine freundliche Erinnerung an meinen Vortrag nächste Woche.

Ich freue mich auf euch!

1 „Gefällt mir“

Wäre eine Verschiebung um ca 30 min auf 1830 möglich? :slight_smile:

Kann ich machen (und hoffe, es stört niemanden).

1 „Gefällt mir“

Kann man selber mitmachen in dem Emulator?

Wenn du flink bist, ja. Die geplanten Beispiele sind wirklich mini. Habe jetzt aber keine Zeit für Workshop-Charakter eingeplant. Das meiste wird aber in Assembler sein, was außerhalb des Emulators mit herkömmlichem Texteditor geschrieben wird.

Wenn du zum Ausprobieren Code-Beispiele angepasst haben willst, kannst du auch gerne fragen, dann übernehme ich das und du kannst zugucken.

Ich versuche mich zu beeilen damit der Verzug nicht so hoch ist :slight_smile:

1 „Gefällt mir“

War interessant! Vielen Dank nochmals.

Gern geschehen! Vielen Dank allen fürs Kommen!

Hier die Inhalte meiner Vortragsfolien:

Eine Einführung in die Programmierung des C64 – Kleine Demoprogramme in BASIC und Assembler

Hardware des C64 (Auswahl)

Der Computer selbst (Tastatur)

Bild: Datei:Commodore64.jpg – C64-Wiki

Hauptprozessor und Speicher

CPU MOS 6510

Bild: Datei:CPU 6510.jpg – C64-Wiki

  • Taktfrequenz: ca. 1 MHz
  • Breite des Datenbusses: 8 Bit
  • Breite des Adressbusses: 16 Bit

RAM

Bild: Datei:C64 RAM.jpg – C64-Wiki

  • 64 KiB

Diskette und Laufwerk

Bild: Datei:Diskette.jpg – C64-Wiki

Bild: Datei:1541.jpg – C64-Wiki

Benutzung des C64 (BASIC)

VICE starten

Kommandozeile: bash x64sc

Bild: Datei:Einschaltmeldung C64.jpg – C64-Wiki

Direktmodus

Bildschirmrahmenfarbe auf Schwarz setzen:

POKE 53280, 0

Zur nächsten Bildschirmrahmenfarbe wechseln:

POKE 53280, (PEEK(53280) + 1) AND 255

Programmmodus

Programm: Zur nächsten Bildschirmrahmenfarbe wechseln:

10 POKE 53280, (PEEK(53280) + 1) AND 255

Programm-Listing ausgeben:

LIST

Programm starten:

RUN

Endlos alle 16 Farben für den Bildschirmrahmen durchgehen:

10 POKE 53280, (PEEK(53280) + 1) AND 255
20 GOTO 10

Diskettenabbild erstellen und einlegen: basic-beispiel.d64

SAVE "BASIC-BEISPIEL",8

Neustart und Diskette einlegen. Dann Diskettenverzeichnis laden:

LOAD "$",8
LIST

Unser Programm laden und starten:

LOAD "BASIC-BEISPIEL",8
RUN

Neustart und Diskette einlegen. Dann erstes Programm von Diskette laden und starten

LOAD "*",8,1
RUN

Assemblerprogrammierung mittels ACME-Assembler

Programm ab $c000

per Texteditor:

; beispiel-c000.asm

!cpu 6510

* = $c000  ; setze Programmanfang auf $c000 (49152)

lda #$00   ; lade Akku mit 0 (entspricht der Farbe Schwarz)
sta $d020  ; setze Rahmenfarbe auf Akku-Inhalt
rts        ; springe zurück zu BASIC

Assemblieren

per Kommandozeile (Bash):

# PRG-Datei erstellen
acme --format cbm --outfile "beispiel-c000.prg" "beispiel-c000.asm"

# D64-Diskettenabbild erstellen, formatieren und PRG-Datei schreiben
c1541 \
  -format "beispiel,1" d64 "beispiel-c000.d64" \
  -write "beispiel-c000.prg" "beispiel-c000"

# VICE starten und erstes Programm auf Diskette laden und starten
x64sc beispiel-c000.d64

per BASIC starten:

0 SYS 49152

BASIC-Header

Das BASIC-Programm 0 SYS2061 per Assembler geschrieben:

; beispiel-0801.asm
!cpu 6510

* = $0801  ; setze BASIC-Programmanfang auf $0801

; BASIC-Programm zum Start des eigentlichen Assembler-Programms
!byte $0b,$08          ; Pointer zur nächsten Zeile ($080b)
!byte $00,$00          ; BASIC-Zeile 0
!byte $9e              ; SYS
!byte $32,$30,$36,$31  ; 2061
!byte $00              ; Zeilenende
!byte $00,$00          ; Endmarkierung des BASIC-Programms

Assembler-Programm mit BASIC-Header

; beispiel-0801.asm
!cpu 6510

* = $0801  ; setze BASIC-Programmanfang auf $0801

; BASIC-Programm zum Start des eigentlichen Assembler-Programms
!byte $0b,$08          ; Pointer zur nächsten Zeile ($080b)
!byte $00,$00          ; BASIC-Zeile 0
!byte $9e              ; SYS
!byte $32,$30,$36,$31  ; 2061
!byte $00              ; Zeilenende
!byte $00,$00          ; Endmarkierung des BASIC-Programms

@hier      ; Sprunglabel
inc $d020  ; wechsle zur nächsten Rahmenfarbe
jmp @hier  ; springe zu @hier

PRG-Datei erstellen

per Kommandozeile (Bash):

# PRG-Datei erstellen
acme --format cbm --outfile "beispiel-0801.prg" "beispiel-0801.asm"

# D64-Diskettenabbild erstellen, formatieren und PRG-Datei schreiben
c1541 \
  -format "beispiel,1" d64 "beispiel-0801.d64" \
  -write "beispiel-0801.prg" "beispiel-0801"

# Programm mit VICE laden und automatisch starten
x64sc "beispiel-0801.d64"

Maschinensprachemonitor

Register anzeigen

(C:$e5cd) r
  ADDR A  X  Y  SP 00 01 NV-BDIZC LIN CYC  STOPWATCH
.;e5cd 00 00 0a f3 2f 37 00100010 082 000    2580102
(C:$e5cd)

Direktassembler

(C:$e5cd) a c000
.c000  lda #$02
.c002  sta $d020
.c005  rts
.c006
(C:$c006)

Disassembler

(C:$c011) d c000 c005
.C:c000  A9 02       LDA #$02
.C:c002  8D 20 D0    STA $D020
.C:c005  60          RTS
(C:$c006)

Breakpoint setzen

(C:$c006) bk c000
BREAK: 1  C:$c000  (Stop on exec)
(C:$c006)

Ausführung fortsetzen

(C:$c006) x

Dann in BASIC ausführen:

SYS 49152

und es öffnet sich der Monitor wegen des Breakpoints:

#1 (Stop on  exec c000)  191/$0bf,  46/$2e
.C:c000  A9 02       LDA #$02       - A:00 X:00 Y:00 SP:f7 ..-.....   34744231
(C:$c000)

Nächsten Befehl ausführen

(C:$c000) z
.C:c002  8D 20 D0    STA $D020      - A:02 X:00 Y:00 SP:f7 ..-.....   34744233
(C:$c002) z
.C:c005  60          RTS            - A:02 X:00 Y:00 SP:f7 ..-.....   34744237
(C:$c005)

Die letzten 5 Befehle anzeigen

(C:$e147) cpuhistory 5
.C:e143  28          PLP            A:02 X:00 Y:00 SP:f6 ..-...Z.     42790990
.C:e144  6C 14 00    JMP ($0014)    A:02 X:00 Y:00 SP:f7 ..-B....     42790994
.C:c000  A9 02       LDA #$02       A:02 X:00 Y:00 SP:f7 ..-B....     42790999
.C:c002  8D 20 D0    STA $D020      A:02 X:00 Y:00 SP:f7 ..-B....     42791001
.C:c005  60          RTS            A:02 X:00 Y:00 SP:f7 ..-B....     42791005
(C:$e147)

Ein einfaches Rechenbeispiel in Assembler

Aufgabenstellung

  • Vor Programmausführung gibt der Benutzer zwei Dezimalzahlen von je einer Ziffer links oben auf dem Bildschirm ein.
  • Der Benutzer startet das Programm.
  • Das Programm addiert beide oben genannten Zahlen und gibt das Ergebnis rechts daneben aus.

Beispiel 1: 3 4 07

Beispiel 2: 7 5 12

Bildschirmspeicher

Bild: Datei:Bildschirmspeicher.png – C64-Wiki

Zeichensatz (nur erste Hälfte)

Bild: Datei:bscode zs1 0-127.png – C64-Wiki

Programm

main:
; ersten Operanden holen
lda $0400  ; lade Akku mit dem Bildschirm-Zeichen in der linken oberen Ecke
and #$0f   ; hole dir nur die unteren vier Bits (diese enthalten den Zifferwert) und speichere sie im Akku
sta @op1   ; speichere den Akku-Inhalt in @op1

; zweiten Operanden holen
lda $0402  ; lade Akku mit dem übernächsten Bildschirm-Zeichen
and #$0f   ; hole dir nur die unteren vier Bits (diese enthalten den Zifferwert) und speichere sie im Akku
sta @op2   ; speichere den Akku-Inhalt in @op2

; beide Operanden addieren
lda @op1   ; lade Akku mit @op1
clc        ; setze Carry-Flag (Übertrag) auf 0
adc @op2   ; addiere zum Akku @op2 hinzu, Übertrag danach im Carry-Flag

; Korrektur für Basis 10
cmp #10    ; vergleiche Akku-Inhalt mit 10
bcc @nein  ; falls Vergleich ergab, dass Akku kleiner als 10 ist, springe zu @nein
sbc #10    ; ansonsten subtrahiere 10 vom Akku und setze dabei Carry-Flag auf 1
@nein

; Ergebnis ausgeben
ora #'0'   ; füge Zeichen '0' zum Akku hinzu
sta $0405  ; schreibe Akku in den Bildschirm, wo die Ergebnisziffer hin soll
lda #'0'   ; lade Akku mit dem Zeichen '0'
adc #0     ; addiere den Inhalt des Carry-Flags (also des Übertrags) zum Akku
sta $0404  ; schreibe Akku in den Bildschirm links neben die Ergebnisziffer

rts        ; springe zurück zu BASIC

!addr @op1 !byte 0  ; Speicher für den ersten Operanden
!addr @op2 !byte 0  ; Speicher für den zweiten Operanden

Verschiedenes

Weiterführende Links

Wissen:

Programmierung:

Quellen

3 „Gefällt mir“

Als Ergänzung für Leute, die wie ich bei fast Null anfangen, fand ich folgende Seite ganz nett : https://www.retro-programming.de/

1 „Gefällt mir“