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
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