Table of Contents
VICE
Intro
Si tratta di un emulatore, disponibile per vari sistemi operativi, di home computer Commodore.
Installazione
Si può installare dai repo Ubuntu, ma poi bisogna copiare le ROM dal pacchetto sorgente, pena errore di “fail to load kernal”.
Le tre ROM da copiare corrispondono ai chip fisici:
$ wget http://www.zimmers.net/anonftp/pub/cbm/crossplatform/emulators/VICE/vice-2.4.tar.gz $ tar vzxf vice-2.4.tar.gz $ cd Scaricati/vice-2.4/data/C64 # cp kernal basic chargen /usr/lib/vice/C64
Copiare anche le ROM dei varie drive e datassette:
$ cd Scaricati/vice-2.4/data/DRIVES # cp d* /usr/lib/vice/DRIVES
Esecuzione
Digitare “Commodore…” e seleziore il 64. Oppure da bash digitare x64.
Tastiera
Apple
Home: fn + cursore sx
Ad esempio per cancellare lo schermo, sul C64 si fa shift + Home, qui si fa shift + fn + cursore sx.
RUN/STOP: esc
RESTORE: fn + cursorse su
Altri tasti sono disponibili qui.
Salvataggi
Per salvare un programma Basic (ed eventualmente poi importarlo in un vero C64…) si fa:
Create and attach an empty disk image….
Dare poi il nome del programma, che avrà come estensione .d64. Una volta creata l'immagine disco, si potrà collegarla semplicemente con Attach a disk image; i vari programmi verranno salvati come file separati con estensione .PRG.
Machine Language Monitor
Un MLM (machine language monitor) in assembly è un tool che consente di:
- visualizzare locazioni di memoria
- scrivere/modificare locazioni di memoria
- eseguire codice da memoria
Per entrare nel VICE Monitor digitare Alt+H (Command+H per i Mac ). Quando è attivo il monitor non è attivo il Basic.
Visualizzare i registri
Visualizzare i registri (con 'R'):
(C:$e5d1) R ADDR A X Y SP 00 01 NV-BDIZC LIN CYC STOPWATCH .;e5d1 00 00 0a f3 2f 37 00100010 000 000 5425056 (C:$e5d1)
Leggere e scrivere nella memoria
Visualizzare il contenuto della memoria (con 'M'):
(C:$1011) M 033c 0348 >C:033c 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. (C:$0349)
Le locazioni $033C-$0348 sono tutte vuote; scriviamo nella memoria (con '>C') in linguaggio macchina:
(C:$0349) >C:033c ad 80 03 ae 81 03 8d 81 03 8e 80 03 00 (C:$0349)
Il programma consiste nello scambiare il contenuto delle locazioni $0380 e $381 (questo è ancora da verificare/modificare).
Per verificare il contenuto della memoria appena scritta:
(C:$0349) M 033c 0348 >C:033c ad 80 03 ae 81 03 8d 81 03 8e 80 03 00 ............. (C:$0349)
Verifichiamo e quindi copiamo dei valori nelle locazioni $0380 e $381:
(C:$0410) M $0380 $0381 >C:0380 00 00 (C:$0382) >C:0380 11 99
Adesso la locazione $0380 contiene il valore $11 e la $0381 contiene $99.
Eseguire codice da memoria
Eseguiamo il programma (con 'G') che inverte le locazioni:
(C:$0382) G 033c
Le due locazioni adesso hanno effettivamente il contenuto invertito:
(C:$e5d1) M 0380 0381 >C:0380 99 11
Disassemblare
Per disassemblare (tradurre da linguaggio macchina in assembly) le locazioni dove si è salvato il codice si fa così (con 'D'):
(C:$0382) D 033c 0348 .C:033c AD 80 03 LDA $0380 .C:033f AE 81 03 LDX $0381 .C:0342 8D 81 03 STA $0381 .C:0345 8E 80 03 STX $0380 .C:0348 00 BRK
L'ultimo comando (BRK) presente in $0348 interrompe il Monitor e passa il controllo al Basic nel VICE. Anche qui possiamo verificare il valore, modificato, delle locazioni $0380 (896 in decimale) e $0381 (897):
? PEEK(896) 153 (cioè $99) ? PEEK(897) 17 (cioè $11)
Un altro modo per passare dal monitor al Basic è premendo 'X'.
Assemblare
Per assemblare (scrivere in assembly per poi essere tradotto in linguaggio macchina) si fa così (con 'A'):
(C:$034b) A 033c .033c LDA #$99 .033e STA $0380 .0341 LDX #$98 .0343 STX $0381 .0346 (C:$0346) M 033c 034a >C:033c a9 99 8d 80 03 a2 98 8e 81 03 00 00 00 00 00 ............... (C:$034b)
Il carattere '#' indica che il valore da caricare nel registro non è quello di una locazione di memoria, ma un valore immediato (o letterale).
Basic
L'esecuzione può avvenire anche nel Basic del C64:
SYS 828
Dove '828' è il decimale di $033C.
Il programma, che carica i valori $99 e $98 nelle locazioni $0380 e $0381, è stato eseguito:
(C:$e5d1) M 0380 0381 >C:0380 99 98 ..
KERNAL subroutines
Per scrivere a video possiamo usare il seguente codice:
(C:$e5cd) >C:0400 3 9 1 f 20 12 f 2 5 12 14 f (C:$e5cd) X
dove $0400 è l'inizio della memoria video del C64; i caratteri che seguono non sono ASCII, ma screen codes (vedi Appendice B della C64 Programmer's Reference Guide).
Il codice produrrà il seguente output:
Invece che scrivere direttamente in memoria, si possono usare le KERNAL subroutines. Uno dei vantaggi di queste è che usano i codici ASCII; ad es. la CHROUT ($FFD2) mostra a video il contenuto del registro A.
(C:$e5cf) A 033c LDA #$41 .033e JSR $FFD2 .0341 LDA #$42 .0343 JSR $FFD2 .0346 LDA #$43 .0348 JSR $FFD2 .034b (C:$034b) G 033c
A video comparirà velocemente la scritta 'ABC' ($41 $42 $43).
Aggiungendo 'RTS' (Return from subroutine):
.034b RTS
è possibile eseguire il comando dal Basic:
SYS 828
Loop
Ipotizziamo di voler ottimizzare il precedente codice memorizzando, invece di 'ABC' la sequenza 'HELLO' in locazioni di memoria consecutive e leggerle tramite un loop.
(C:$e5cd) A 033c .033c LDX #$00 .033e LDA $034A,X .0341 JSR $FFD2 .0344 INX .0345 CPX #$06 .0347 BNE $033E .0349 RTS
Per questo loop andremo ad utilizzare il registro X perché:
- il registro X può essere incrementato (riga $0344), a differenza dell'Accumulatore
- può essere implementato, assieme all'accumulatore, per ottenere un indirizzamento di tipo absolute (vedi riga $033e)
Per stampare la stringa voluta, sarà sufficiente memorizzare i valori ASCII esadecimali di HELLO e RETURN. Sono valori che dobbiamo memorizzare come tali, non possiamo assemblarli:
(C:$0368) >C:034a 48 45 4c 4c 4f 0d
Richiamando la subroutine dal Basic otteniamo:
Salvare
Per potere salvare il codice bisogna essere in Basic; bisogna:
- reperire, tramite dei PEEK, i valori sia del codice che i valori di testo di HELLO
- ricrearli poi con dei POKE
Recuperiamo intanto il codice e valori stringa; il codice in assembly è compreso tra $033c e $034f, che corrispondono ai decimali 828 e 847. Quindi:
Si tratta dei valori decimali del codice esadecimale inserito nelle locazioni. Tali valori possono poi essere ricopiati tramite comandi Basic DATA e memorizzati con dei POKE:
Tale codice, che ricrea il codice assembly di prima, si può ovviamente salvare come un qualsiasi programma Basic:
Per salvare su nastro usa il comando File-Create and attach datassette image…. Dopodiché si potrà salvare il listato ed eseguirlo: