User Tools

Site Tools


content:retrocomputing:vice

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
content:retrocomputing:vice [2024/07/12 21:26] – [Mappa della memoria] admincontent:retrocomputing:vice [2024/08/03 18:08] (current) – [Apple] admin
Line 31: Line 31:
  
 ===== Tastiera ===== ===== Tastiera =====
 +
 +==== Italiana ====
 +
 +Se stampa caratteri //strani//, assicurarsi che sia presente la **tastiera italiana**; andare su //Preferences... - Settings// e poi:
 +
 +{{:content:retrocomputing:vice-tastiera-ita.png?600|}}
  
 ==== Apple ==== ==== Apple ====
Line 62: Line 68:
  
  
-===== 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'**): 
- 
-<file> 
-(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)  
-</file> 
- 
-==== Leggere e scrivere nella memoria ==== 
- 
-**Visualizzare** il contenuto della **memoria** (con **'M'**): 
- 
-<file> 
-(C:$1011) M 033c 0348 
->C:033c  00 00 00 00  00 00 00 00  00 00 00 00  00            ............. 
-(C:$0349)  
-</file> 
- 
-Le locazioni $033C-$0348 sono tutte vuote; **scriviamo nella memoria** (con **'>C'**, per '//change memory//') in linguaggio macchina: 
- 
-<file> 
-(C:$0349) >C:033c ad 80 03 ae 81 03 8d 81 03 8e 80 03 00 
-(C:$0349) 
-</file> 
- 
-<note tip>L'area di memoria **$033c-$03fb** è il //datassette buffer//, valida per brevi programmi di massimo 192 bytes</note> 
- 
-Di seguito alcuni **//opcodes//** utilizzati: 
- 
-{{:content:retrocomputing:opcodes01.png|}} 
- 
-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: 
- 
-<file> 
-(C:$0349) M 033c 0348 
->C:033c  ad 80 03 ae  81 03 8d 81  03 8e 80 03  00            ............. 
-(C:$0349)  
-</file> 
- 
-Verifichiamo e quindi copiamo dei valori nelle locazioni $0380 e $381: 
- 
-<file> 
-(C:$0410) M $0380 $0381 
->C:0380  00 00 
-  
-(C:$0382) >C:0380 11 99 
- 
-(C:$0382) M $0380 $0381 
->C:0380  11 99   
-</file>  
-       
-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: 
- 
-<file> 
-(C:$0382) G 033c 
-</file> 
- 
-Le due locazioni adesso hanno effettivamente il contenuto invertito: 
- 
-<file> 
-(C:$e5d1) M 0380 0381 
->C:0380  99 11   
-</file> 
- 
-==== Disassemblare ==== 
- 
-Per **disassemblare** (tradurre da linguaggio macchina in assembly) le locazioni dove si è salvato il codice si fa così (con **'D'**): 
- 
-<file> 
-(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 
-</file> 
- 
-Di seguito uno schema delle operazioni svolte da/verso registri CPU/memoria: 
- 
-{{:content:retrocomputing:assembly01.png?400|}} 
- 
-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): 
- 
-<file> 
-? PEEK(896) 
- 153 (cioè $99) 
-  
-? PEEK(897) 
- 17 (cioè $11) 
-</file> 
- 
-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'**): 
- 
-<file> 
-(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)  
-</file> 
- 
-Alla locazione 0346 è stato digitato //Return//, per indicare la fine dell'input. 
- 
-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: 
- 
-<file> 
-SYS 828  
-</file> 
- 
-Dove '828' è il decimale di $033C.  
- 
-Il programma, che carica i valori $99 e $98 nelle locazioni $0380 e $0381, è stato eseguito: 
- 
-<file> 
-(C:$e5d1) M 0380 0381 
->C:0380  99 98                                                .. 
-</file> 
- 
-==== CHROUT ==== 
- 
-Per **scrivere a video** possiamo usare il seguente codice: 
- 
-<file> 
-(C:$e5cd) >C:0400 3 9 1 f 20 12 f 2 5 12 14 f 
-(C:$e5cd) X 
-</file> 
- 
-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: 
- 
-{{:content:retrocomputing:vice01.png?500|}} 
- 
-Invece che scrivere direttamente in memoria, si possono usare le **//KERNAL subroutines//**, salvate nella **ROM** omonima. Uno dei vantaggi di queste è che usano i codici ASCII; ad es. la **CHROUT ($FFD2)** mostra a video il contenuto del **registro A**.  
- 
-<file> 
-(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 
-</file> 
- 
-A video comparirà velocemente la scritta 'ABC' ($41 $42 $43). 
- 
-Aggiungendo 'RTS' (//Return from subroutine//): 
- 
-<file> 
-.034b RTS   
-</file> 
- 
-è possibile eseguire il comando dal Basic: 
- 
-<file> 
-SYS 828 
-</file> 
- 
-{{:content:retrocomputing:vice02.png?500|}} 
- 
-L'indirizzamento di memoria della **//KERNAL ROM//** va **da $E000 a $FFFF**, come indicato nella **[[https://sta.c64.org/cbm64mem.html|memory map]]**. 
- 
-==== 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//. 
- 
-<file> 
-(C:$e5cd) A 033c 
-.033c  LDX #$00 
-.033e  LDA $034A,X 
-.0341  JSR $FFD2 
-.0344  INX 
-.0345  CPX #$06 
-.0347  BNE $033E 
-.0349  RTS 
-</file> 
- 
-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 Indexed mode// (vedi riga $033e) 
- 
-<note tip>Un indirizzamento di tipo //absolute indexed mode// è limitato a soli 256 byte; per incrementare questo limite si può usare un tipo di indirizzamento //[[#indirizzamento_indirect_indexed|Indirect, Indexed]]//</note> 
- 
-Le righe $0345 e $0347 possono essere spiegate così: **CPX** (//'compare X'//) in realtà effettua una sottrazione del valore immediato $06 dal registro X. In questo modo, si ottiene un valore, che se non è zero (**BNE**, che verifica il //flag Zero//) comporta un //branch//, creando così il //loop//. 
- 
-Il **//flag Carry//**, oltre che dalle operazioni aritmetiche, viene **influenzato anche dalle operazioni di comparazione CPX, CPY e CMP**, come indicato qui di seguito. 
- 
-<note tip>Un'**alternativa a BNE** può essere anche **BCC**, che sfrutta il //flag Carry//; nella fattispecie: 
- 
-  * **BCS** effettua il //branch// se il valore nel registro (X,Y o A) è >= del valore comparato (flag Carry=1) 
-  * **BCC** effettua il //branch// se il valore nel registro (X,Y o A) è < del valore comparato (flag Carry=0) 
- 
-Ma in questo caso è quindi necessario cambiare anche la comparazione in **CPX #$07**, con un valore maggiore di uno rispetto a quello cercato. 
-</note> 
- 
-Riassumendo, dopo aver effettuato una **comparazione**, si possono usare i seguenti //mnemonics// per ottenere dei //branch//, a seconda delle varie **condizioni**: 
- 
-^Condizione^Flag^Branch da usare^Note^ 
-|"registro uguale a"  |**Z** - Zero|BEQ (branch equal 0)|| 
-|"registro diverso a" |**Z** - Zero|BNE (branch not equal 0)|| 
-|"registro minore di"|**C** - Carry|BCC (branch carry clear)|| 
-|"registro maggiore o uguale a"|**C** - Carry|BCS (branch carry set)|| 
-|"registro negativo" (MSB=1)|**N** - Negative|BMI (branch minus)|| 
-|"registro positivo" (MSB=0)|**N** - Negative|BPL (branch plus)|| 
-|"overflow numero con segno" (bit 6=1)|**V** - Overflow|BVS (branch overflow set)|| 
-|"no overflow numero con segno" (bit 6=0)|**V** - Overflow|BVC (branch overflow clear)|| 
- 
-Per stampare la stringa voluta, sarà sufficiente memorizzare i valori ASCII esadecimali di HELLO e RETURN a partire dalla locazione $034a. Sono valori che dobbiamo memorizzare come tali, non possiamo //assemblarli//: 
- 
-<file> 
-(C:$0368) >C:034a 48 45 4c 4c 4f 0d 
-</file> 
- 
-Richiamando la subroutine dal Basic otteniamo: 
- 
-{{:content:retrocomputing:vice03.png?500|}} 
- 
-==== 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: 
- 
-{{:content:retrocomputing:vice04.png?500|}} 
- 
-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//: 
- 
-{{:content:retrocomputing:vice05.png?500|}} 
- 
-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: 
- 
-{{:content:retrocomputing:vice06.png?500|}} 
- 
-<note tip>Cancellando il programma Basic (ad esempio con 'NEW') il codice in memoria rimane comunque</note> 
- 
-==== GETIN e STOP ==== 
- 
-Un'altra **//KERNAL subroutine//**, oltre alla già vista [[#CHROUT]], è **GETIN** ($FFE4), che testa la pressione di un tasto (simile al comando Basic GET) e lo salva nel registro A in formato ASCII. 
- 
-C'è anche **STOP** ($FFE1), che testa la pressione di RUN/STOP. 
- 
-Il seguente programma testa proprio inizialmente la pressione di RUN/STOP ed in tal caso effettua un opportuno RTS: 
- 
-<file> 
-(C:$e5d4) A 033C JSR $FFe1 
-.033f  BEQ $0351 
- 
-... 
- 
-.0351  RTS 
-</file> 
- 
-{{:content:retrocomputing:vice-run-stop.png?500|}} 
- 
-Successivamente chiama la KERNAL routine **GETIN** e ottiene quindi la pressione di un tasto, che viene salvato in A sotto forma di codice ASCII: 
- 
-<file> 
-... 
- 
-.0341  JSR $FFe4 
-.0344  CMP #$30 
-.0346  BCC $033C 
-.0348  CMP #$3A 
-.034a  BCS $033C 
-.034c  JSR $FFD2 
-.034f  NOP 
-.0351  RTS 
-</file> 
- 
-Siccome in questo programma ci interessano solo i **numeri da 0 a 9** (codici ASCII da $30 a $39), le righe $0344-$0346 testano se il codice ASCII digitato è //minore// di 30 (vedi uso **BCC** sopra) mentre le righe $0348-$034a testano se il codice ASCII digitato è //maggiore o uguale// di 3A; non essendo questi valori accettabili, in entrambe le condizioni il programma torna all'inizio per un ulteriore verifica del pulsante premuto. 
- 
-{{:content:retrocomputing:vice-ascii-0-9.png|}} 
- 
-Una **tabella completa dei codici ASCII (PETSCII)** per il C64 è presente **[[https://sta.c64.org/cbm64pet.html|qui]]**. 
- 
-Quindi solo la pressione di numeri 0-9 produrrà un output: 
- 
-{{:content:retrocomputing:vice-0-9.png?500|}} 
- 
-=== Esempio 1 === 
- 
-Questo **altro programma** testa la pressione dei tasti '4' oppure RUN/STOP: 
- 
-<file> 
-.C:033c  20 E1 FF    JSR $FFE1 
-.C:033f  F0 0D       BEQ $034E 
-.C:0341  20 E4 FF    JSR $FFE4 
-.C:0344  C9 34       CMP #$34 
-.C:0346  D0 F4       BNE $033C 
-.C:0348  20 D2 FF    JSR $FFD2 
-.C:034b  20 3C 03    JSR $033C 
-.C:034e  60          RTS 
-</file> 
- 
-=== Esempio 2 === 
- 
-Altro esempio, in cui si vuole consentire la visualizzazione dei soli **caratteri alfanumerici** (0-9 e A-Z): 
- 
-<file> 
-(C:$0354) d 033c 0357 
-.C:033c  20 E1 FF    JSR $FFE1 ; verifica RUN/STOP 
-.C:033f  F0 1C       BEQ $035D ; se premuto, vai RTS 
-.C:0341  20 E4 FF    JSR $FFE4 ; testa pulsante 
-.C:0344  C9 30       CMP #$30   ; 
-.C:0346  90 F4       BCC $033C ; se < $30 ('0') vai ad inizio 
-.C:0348  C9 75       CMP #$5B ; 
-.C:034a  B0 F0       BCS $033C ; se >= $5B (carattere dopo 'Z') vai ad inizio 
-.C:034c  C9 3A       CMP #$3A   ; 
-.C:034e  90 07       BCC $0357 ; se < $3A ('9') vai a stampa carattere 
-.C:0350  C9 41       CMP #$41   ; 
-.C:0352  B0 03       BCC $033c ; se < $41 ('A') vai ad inizio 
-.C:0357  20 D2 FF    JSR $FFD2 ; stampa carattere 
-.C:035a  20 3C 03    JSR $033C ; vai ad inizio 
-.C:035d  60          RTS ; return from subroutine 
-</file> 
- 
-Il codice sopra si prende cura di non visualizzare i caratteri prima dello '0', dopo la 'Z' e in mezzo tra le cifre e le lettere. 
-==== AND, ORA e EOR ==== 
- 
-Con gli **operandi AND, ORA e EOR** si possono effettuare operazioni sui **singoli bit dell'accumulatore A, senza toccare gli altri bit** (**non** ci sono equivalenti per i registri X o Y).  
- 
-  * per **azzerare un bit** dell'accumulatore **A** si può usare **AND**, funzionando quindi come una //mask//; ad es. per azzerare il suo LSB (il bit meno significativo) si può usare 
-<file>AND #$FE</file> 
-  * per **settare a 1 un bit** dell'accumulatore **A** si può usare **OR**; ad es. per rettare a 1 il suo MSB (il bit più significativo,) si può usare 
-<file>ORA #$80</file> 
-  * per **invertire alcuni bit** dell'accumulatore **A** si può usare **EOR**: 
- 
-{{:content:retrocomputing:img_20240609_041508.png?400|}} 
- 
-==== Addizione ==== 
- 
-Per **sommare dei numeri** si usa: 
- 
-  * l'**accumulatore A** (**non** i registri X e Y) e un byte di memoria 
-  * l'operando **ADC //"ADd with Carry"//** 
-  * non esiste un operando di addizione //senza// Carry, ma è possibile cancellare il flag Carry, prima dell'ADC, con **CLC** 
-  * il **risultato** dell'operazione **resta nell'accumulatore A** 
- 
-L'esempio seguente mostra la **somma di due numeri da 2 byte ciascuno** ($03A1:$03A0 + $03B1:$03B0 = $03C1:$03C0).  
- 
-<note tip>In realtà, si tratta di due distinte operazioni, che danno come risultato $03C0 e $03C1, che non sono legate tra di loro, se non dal fatto che il //carry// della prima viene riportato con ADC nella seconda</note> 
- 
-{{:content:retrocomputing:adc-carry01.png?400|}} 
- 
-<file> 
-(C:$034f) d 033c 034c 
-.C:033c  18          CLC        ; Carry azzerato 
-.C:033d  AD A0 03    LDA $03A0  ; copia valore da locazione $03A0 in A 
-.C:0340  6D B0 03    ADC $03B0  ; somma valore in A con valore in locazione $03B0; qui il carry può essere a 1 
-.C:0343  8D C0 03    STA $03C0  ; salva somma in A in $03C0 
-.C:0346  AD A1 03    LDA $03A1  ; copia valore da locazione $03A1 in A 
-.C:0349  6D B1 03    ADC $03B1  ; tiene conto del valore del carry precedente e fa la somma dell'high byte 
-.C:034c  8D C1 03    STA $03C1  ; salva somma in A in $03C1 
-</file> 
- 
-Qui vengono caricati dei valori nelle locazioni di memoria oggetto di somma: 
- 
-<file> 
-(C:$03a2) >C:03a0 8d 45 
-(C:$03a2) >C:03b0 7a 52 
-</file> 
- 
-==== Sottrazione ==== 
- 
-Prima di effettuare una **sottrazione** conviene settare il **//carry (borrow)// flag con SEC**. 
- 
-Il seguente esempio sottrae due valori (8D-45) e salva il risultato in $0382: 
- 
-<file> 
-(C:$e5d4) >C:0380 8d 45        ; carica i valori degli operandi in $0380 e $0381 
-   
-.C:033c  38          SEC 
-.C:033d  AD 80 03    LDA $0380 ; A=8D 
-.C:0340  ED 81 03    SBC $0381 ; A=8D-45 
-.C:0343  8D 82 03    STA $0382 ; $0382=A 
-.C:0346  60          RTS 
- 
-(C:$04c2) m 0382 0383 
->C:0382  48 00  
-</file> 
- 
-==== Shift register ==== 
- 
-=== ASL === 
- 
-Per effettuare uno **//shift register// a sinistra**, dell'**accumulatore** o di una **locazione di memoria**, si possono usare **ASL** o **ROL**: 
- 
-  * **ASL**: **non** usa il //carry// nel primo bit LSB, che imposta a 0 
-  * **ROL**: usa il //carry// nel primo bit LSB 
- 
-Il seguente programma effettua uno **//shift left di A//** e salva il risultato nella locazione $0349; dopo 7 iterazioni un bit si sposta dal bit 0 al bit 7: 
- 
-{{:content:retrocomputing:vice-asl.png?400|}} 
- 
-<file> 
-(C:$034b) d 033c 0347 
-.C:033c  A9 01       LDA #$01 
-.C:033e  A2 07       LDX #$07 
-.C:0340  0A          ASL A 
-.C:0341  CA          DEX 
-.C:0342  D0 FC       BNE $0340 
-.C:0344  8D 49 03    STA $0349 
-.C:0347  00          BRK 
- 
-(C:$0489) m 0349 034a 
->C:0349  80 00   
-</file> 
- 
-Ad ogni iterazione, il registro A viene **moltiplicato di 2**. Infatti, la locazione $0349 contiene, dopo 7 iterazioni, il valore $80. 
- 
-=== ROL === 
- 
-Invece, il seguente programma simula l'utilizzo di un numero composto da un //low byte// ($0351) e da un //high byte// ($0352); viene caricato il valore $8F nel //low byte// e, tramite un ASL e subito dopo un ROL, passando per il //Carry//, dopo 8 iterazioni, il valore finisce spostato nell'//high byte//: 
- 
-{{:content:retrocomputing:vice-rol01.png|}} 
- 
-<file> 
-(C:$0348) d 033c 0352 
-.C:033c  A9 00       LDA #$00 
-.C:033e  8D 52 03    STA $0352 
-.C:0341  A9 8F       LDA #$8F 
-.C:0343  8D 51 03    STA $0351 
-.C:0346  A2 08       LDX #$08 
-.C:0348  0E 51 03    ASL $0351 
-.C:034b  2E 52 03    ROL $0352 
-.C:034e  CA          DEX 
-.C:034f  D0 F7       BNE $0348 
-</file> 
- 
-<note>Per effettuare uno **//shift register// a destra** si usano invece **LSR** o **ROR**</note> 
- 
-==== Subroutine ==== 
- 
-Con i comandi **TAX, TXA, TAY, TYA** si copia il contenuto di A in X o Y e viceversa. Qui di seguito un programma che li usa; il **programma effettua la somma di due numeri ad una cifra**. 
- 
-La **prima parte** riprende quanto evidenziato **[[#esempio_2|sopra]]**, cioè: 
- 
-  * verifica la pressione di RUN/STOP  
-  * accetta l'input di numeri nel range 0-9 
-  * stampa il numero 
-  * con l'istruzione //AND #$0F// prende in considerazione la parte destra del codice ASCII, in modo che se il tasto premuto è 0, il codice ASCII è $30 e viene memorizzato $0, cioè il valore binario effettivo: 
- 
-<code> 
-.C:033c  20 E1 FF    JSR $FFE1 
-.C:033f  F0 10       BEQ $0351 
-.C:0341  20 E4 FF    JSR $FFE4 
-.C:0344  C9 30       CMP #$30 
-.C:0346  90 F4       BCC $033C 
-.C:0348  C9 3A       CMP #$3A 
-.C:034a  B0 F0       BCS $033C 
-.C:034c  20 D2 FF    JSR $FFD2 
-.C:034f  29 0F       AND #$0F 
-.C:0351  60          RTS 
-</code> 
- 
-Questa prima parte è una **//subroutine//**, che viene richiamata più volte dal codice vero e proprio sottostante. 
- 
-La **seconda parte** richiama due volte la subroutine di input ed effettua e stampa la somma di due numeri nel range 0-9: 
- 
-<code> 
-.C:0352  20 3C 03    JSR $033C     ; richiama subroutine di input 
-.C:0355  8D C0 03    STA $03C0     ; salva il valore binario del primo addendo in una locazione 
-.C:0358  A9 2B       LDA #$2B      ; codice ASCII per '+' 
-.C:035a  20 D2 FF    JSR $FFD2 
-.C:035d  20 3C 03    JSR $033C 
-.C:0360  AA          TAX           ; salva il valore binario del secondo addendo nel registro X, visto che non viene usato 
-.C:0361  A9 3D       LDA #$3D      ; codice ASCII per '=' 
-.C:0363  20 D2 FF    JSR $FFD2 
-.C:0366  8A          TXA           ; riporta il valore binario del secondo addendo in A 
-.C:0367  18          CLC           ; non considerare Carry 
-.C:0368  6D C0 03    ADC $03C0     ; somma di A, che contiene il secondo addendo, con la locazione in cui è stato memorizzato il primo addendo 
-.C:036b  AA          TAX           ; salva il valore binario della somma (questa volta) nel registro X, visto che non viene usato 
-.C:036c  C9 0A       CMP #$0A       
-.C:036e  90 07       BCC $0379     ; se somma <$0A (10) vai a stampa_risultato 
-.C:0370  A9 31       LDA #$31      ; somma è >=$0a: stampa "1" 
-.C:0372  20 D2 FF    JSR $FFD2 
-.C:0375  8A          TXA           ; copia valore binario somma presente in X in A 
-.C:0376  38          SEC 
-.C:0377  E9 0A       SBC #$0A      ; A (somma) = A - $0A 
-.C:0379  09 30       ORA #$30      ; stampa risultato; aggiungi '$3' nel nibble di sinistra, così da ottenere il valore ASCII della somma dei due addendi 
-.C:037b  20 D2 FF    JSR $FFD2 
-.C:037e  A9 0D       LDA #$0D      ; stampa Return 
-.C:0380  20 D2 FF    JSR $FFD2 
-.C:0383  60          RTS 
-</code> 
- 
-{{:content:retrocomputing:vice-somma01.png?500|}} 
- 
-<note important>Bisogna fare attenzione con TAX e TXA, in quanto può capitare che il valore riportato in A non sia quello in precedenza salvato in X. L'esempio di seguito ne è privo e preferisce salvare due valori nelle locazioni, invece che nel registro X</note> 
- 
-Qui di seguito un **esempio** in cui si effettua una **sottrazione di due valori**, sempre usando la //subroutine// presente in $033C: 
- 
-<code> 
-.C:0352  20 3C 03    JSR $033C 
-.C:0355  8D C0 03    STA $03C0     ; salva minuendo in $03C0 
-.C:0358  A9 2D       LDA #$2D 
-.C:035a  20 D2 FF    JSR $FFD2 
-.C:035d  20 3C 03    JSR $033C     ; salva sottraendo in $03C1 
-.C:0360  8D C1 03    STA $03C1 
-.C:0363  A9 3D       LDA #$3D 
-.C:0365  20 D2 FF    JSR $FFD2 
-.C:0368  AD C0 03    LDA $03C0 
-.C:036b  38          SEC 
-.C:036c  ED C1 03    SBC $03C1     ; effettua $03C0-$03C1 e lascia in A 
-.C:036f  09 30       ORA #$30 
-.C:0371  20 D2 FF    JSR $FFD2 
-.C:0374  A9 0D       LDA #$0D 
-.C:0376  20 D2 FF    JSR $FFD2 
-.C:0379  60          RTS 
-</code> 
- 
-{{:content:retrocomputing:vice-sottr01.png?500|}} 
- 
-Qui di seguito un altro **esempio** che testa se un numero è **pari o dispari** facendo un **//LSR//** (logical shift right) e controllando il //carry// (usa la stessa //subroutine// sopra). Se C=1 è dispari, altrimenti pari: 
- 
-<code> 
-.C:0352  20 3C 03    JSR $033C 
-.C:0355  4A          LSR A 
-.C:0356  90 24       BCC $037C   ; C=0, vai a stampa ' IS EVEN' 
-.C:0358  A9 20       LDA #$20    ; C=1, stampa 'IS ODD' (spazio) 
-.C:035a  20 D2 FF    JSR $FFD2 
-.C:035d  A9 49       LDA #$49    ; 'I' 
-.C:035f  20 D2 FF    JSR $FFD2 
-.C:0362  A9 53       LDA #$53    ; 'S' 
-.C:0364  20 D2 FF    JSR $FFD2 
-.C:0367  A9 20       LDA #$20    ; (spazio) 
-.C:0369  20 D2 FF    JSR $FFD2 
-.C:036c  A9 4F       LDA #$4F    ; 'O' 
-.C:036e  20 D2 FF    JSR $FFD2 
-.C:0371  A9 44       LDA #$44    ; 'D' 
-.C:0373  20 D2 FF    JSR $FFD2 
-.C:0376  A9 44       LDA #$44    ; 'D' 
-.C:0378  20 D2 FF    JSR $FFD2 
-.C:037b  60          RTS 
-.C:037c  A9 20       LDA #$20    ; (spazio) 
-.C:037e  20 D2 FF    JSR $FFD2 
-.C:0381  A9 49       LDA #$49    ; 'I' 
-.C:0383  20 D2 FF    JSR $FFD2 
-.C:0386  A9 53       LDA #$53    ; 'S' 
-.C:0388  20 D2 FF    JSR $FFD2 
-.C:038b  A9 20       LDA #$20    ; (spazio) 
-.C:038d  20 D2 FF    JSR $FFD2 
-.C:0390  A9 45       LDA #$45    ; 'E' 
-.C:0392  20 D2 FF    JSR $FFD2 
-.C:0395  A9 56       LDA #$56    ; 'V' 
-.C:0397  20 D2 FF    JSR $FFD2 
-.C:039a  A9 45       LDA #$45    ; 'E' 
-.C:039c  20 D2 FF    JSR $FFD2 
-.C:039f  A9 4E       LDA #$4E    ; 'N' 
-.C:03a1  20 D2 FF    JSR $FFD2 
-.C:03a4  60          RTS 
-</code> 
- 
-{{:content:retrocomputing:vice-even-odd.png?500|}} 
- 
-==== Indirizzamento Indirect, Indexed ==== 
- 
-L'indirizzamento di tipo **//Indirect, Indexed//** consente di raggiungere più di 256 byte di memoria.  
-==== Start & End of Basic ==== 
- 
-Il Start-of-Basic e l'End-of-Basic è definito in questi registri: 
- 
-{{:content:retrocomputing:c64-memory01.png?600|}} 
- 
-Da questi valori di default, si capisce che i byte disponibili per Basic, all'accensione del C64, sono 
- 
-<file>40960-2049 = 38911</file> 
- 
-===== Kick Assembler ===== 
- 
-Un //assembler// avanzato è **Kick Assembler**; **[[https://www.youtube.com/watch?v=rFOh_lYcF8A&list=PLU1o_YShTPgoA7_nZ0PutqaPDsitA5RvV&pp=iAQB|qui]]** un corso che spiega come creare un gioco usando questo ambiente di sviluppo. 
- 
-Nel classico comando per eseguire un programma da disco: 
- 
-<file>LOAD "*",8,1</file> 
- 
-il parametro **'1'** indica al computer di caricare in memoria il programma da disco iniziando alla locazione di memoria specificata dai primi due byte del file (programma) da caricare, che solitamente è $0801. 
- 
-Se si effettua un //LIST// del programma appena caricato compare solitamente una singola linea: 
- 
-{{:content:retrocomputing:vice-sys01.png|}} 
- 
-Che quindi punta alla locazione 2049 ($080b); quella è la locazione da dove parte il programma vero e proprio, quindi abbastanza all'inizio dello //Start-of-Basic//. 
- 
-All'inizio di ogni codice di //Kick Assembler// bisogna inserire la seguente istruzione: 
- 
-<code> 
-// $801 
-BasicUpstart2(main) 
- 
-// $810 
-main: 
-</code> 
- 
-Quello che fa //BasicUpstart2(main)// è il seguente piccolo programma in Basic: 
- 
-<file> 
-10 SYS2064 
-</file> 
- 
-Quindi, nella posizione $801 viene inserito il programma 10 SYS2064, che quindi rimanderà alla locazione 2064 ($810), dove sarà presente il codice //main://. 
- 
- 
-===== VIC 20 ===== 
- 
-==== VICMON ==== 
- 
-**VICMON** è un **[[#machine_language_monitor|MLM]]** per VIC20. Per eseguirlo su **VICE** è necessario 
- 
-  * avere il file in **formato .crt** 
-  * impostare la cartuccia come indicato **[[https://sourceforge.net/p/vice-emu/bugs/1447/|qui]]** e cioè: 
- 
-{{:content:retrocomputing:vicmon01.png|}} 
- 
-==== Hello World ==== 
- 
-Di seguito il codice per stampare a video "HELLO WORLD". 
- 
-<code> 
-., 1100 ldx #$00 
-., 1102 lda $110e,x 
-., 1105 beq $110d 
-., 1107 jsr $ffd2 
-., 110a inx 
-., 110b bne $1102 
-., 110d brk 
-</code> 
- 
-Questi i valori ASCII da memorizzare: 
- 
-<code> 
-.m 110e 
- 
-.:110e 48 45 4c 4c 4f 
-.:1113 20 57 4f 52 4c 
-.:1118 44 00  
-</code> 
- 
-{{:content:retrocomputing:helloworld01.png|}} 
- 
-Conviene prima della 'H', inserire il valore ASCII $93 per **cancellare lo schermo**, quindi le locazioni di memoria dove viene salvato il testo cambiano così: 
- 
-<code> 
-.m 110e 
- 
-.:110e 93 48 45 4c 4c 
-.:1113 4f 20 57 4f 52 
-.:1118 4c 44 00  
-</code> 
- 
-{{:content:retrocomputing:helloworld02.png|}} 
- 
-=== Variante senza CHROUT === 
- 
-Una variante prevede l'output a video **senza l'uso della subroutine kernal CHROUT**, ma effettuando l'**output direttamente sulla memoria video del VIC 20 $1E00-$1FFF (7680-8191)**. 
- 
-Come prima cosa conviene sfruttare gli **screen codes** della scritta già presente a video: 
- 
-{{:content:retrocomputing:helloworld03.png|}} 
- 
-Poi basta cambiare l'indirizzo della prima locazione di memoria in $1113 (dando Return ad ogni riga), per sovrascrivere le locazioni con i codici ASCII in Screen codes: 
- 
-{{:content:retrocomputing:helloworld05.png|}} 
- 
-Il codice è stato cambiato, ed è stato necessario modificare **sia la mappa schermo che la mappa colore (in rosso)**, altrimenti le scritte non sarebbero comparse; inoltre, a causa dello **//scrolling//**, è stato necessario modificare le locazioni schermo e colore a partire dalla **sesta riga** (a partire quindi dalle locazioni $1E6E - 7790 per lo schermo e $966E - 38510 per la mappa colore), così che la scritta non scomparisse in alto. 
- 
- ==== Mappa della memoria ==== 
- 
-Programmando il VIC 20 in assembly, si va direttamente ad utilizzare/scrivere sulla sua memoria; può essere quindi utili conoscere alcune **aree della memoria**, così da comprenderne meglio il comportamento del computer. 
- 
-=== Reset vector === 
- 
-L'**indirizzo del reset vector** è nella memoria **in KERNAL rom** ($E000-$FFFF 57344-65535); è contenuto in due indirizzi di memoria, $FFFD - 65533 (high byte) e $FFFC - 65532 (low byte); facendo un po' di calcoli si ottiene: 
- 
-{{:content:retrocomputing:vice-reset-vector01.png|}} 
- 
-che è l'**indirizzo del reset vector ($FD22 - 64802)**, che può quindi essere richiamato, ad es. da BASIC, per effettuare un reset del computer: 
- 
-{{:content:retrocomputing:vic-reset-vector02.png|}} 
- 
-La routine Kernal vera e propria presente in $FD22 è abbastanza complessa; incollo qui di seguito le prime istruzioni: 
- 
-{{:content:retrocomputing:vic-reset-vector03.png|}} 
- 
-=== Start-of-Basic RAM === 
- 
-L'inizio della **RAM Basic** è definito, a seconda che il VIC 20 sia o meno espanso, così: 
- 
-{{:content:retrocomputing:vic-basic-ram01.png|}} 
- 
-tratto da **[[https://techtinkering.com/articles/basic-line-storage-on-the-vic-20/|qui]]**. Il **vettore di inizio Basic è dato dal contenuto di due locazioni, 43 (low byte) e 44 (high byte)**; il valore $1001 è confermato: 
- 
-{{:content:retrocomputing:vic-basic-ram02.png|}} 
- 
-<note tip> 
-Quasi tutta la memoria RAM del VIC 20 è assegnata al BASIC; questo consente di scrivere programmi quanto più grandi possibile. **Per ottenere più spazio per i programmi in linguaggio macchina bisogna quindi riassegnare la memoria assegnata al BASIC** 
-</note> 
- 
-Questo valore e i successivi, potrebbero interferire con il codice assembly che scriviamo; fino ad adesso per questo abbiamo utilizzato $1100 - 4352: un programma Basic potrebbe andare a sovrascriverlo. E' consigliabile quindi **spostare in avanti il vettore di Start-of-Basic**; come indicato **[[https://www.atarimagazines.com/compute/issue38/105_1_PART_III_VISITING_THE_VIC-20_VIDEO.php|qui]]** conviene procedere così: 
- 
-  - settare a '0' il valore della prima locazione della nuova area Basic 
-  - impostare i valori della nuova area Basic al valore delle prima locazione + 1 
-  - dare 'NEW' in Basic, così lo stesso si posiziona correttamente nella nuova area 
- 
-Per la nuova locazione dello Start-of-Basic prendiamo l'attuale + 1024, cioè 4096+1024=5120; per ottenere quanto sopra si procede quindi così: 
- 
-<code> 
-POKE 5120,0 
-POKE 43,1:POKE 44,20:NEW 
-</code>  
- 
-Infatti 5121=1+20*256. 
- 
-<note tip> 
-Questo consente di avere uno **spazio sufficiente per l'assembly, da $1000 a $13FF**, prima dell'area Basic che va da $1400 a $1DFF, prima a sua volta della memoria video, che inizia a $1E00. 
-</note> 
- 
-Per conferma, si può provare a digitare il seguente programma in BASIC e verificare dove viene memorizzato: 
- 
-<code> 
-1234PRINT"CIAO" 
-</code> 
- 
-e controllare quello che viene memorizzato nel nuovo //Start-of-Basic// a $1400: 
- 
-{{:content:retrocomputing:vic-basic-ram03.png|}} 
- 
-dove: 
- 
-  * '00' è il primo byte a $1400 
-  * '140D' è il //Next line link// 
-  * '04D2' è '1234' 
-  * '99' è il //token// di PRINT 
-  * poi seguono i PETSCII di "CIAO" 
-  * '00' è il termine della riga 
-  * la prossima riga inizia, come da indicazioni sopra (//Next link link//), a '140D' 
- 
-=== Espansione RAM === 
- 
-Con il VIC 20 è possibile usare una scheda che consente di espandere il computer, così come le originali cartucce da 3K, 8K o 16K. Ad es., una scheda compatibile è la seguente: 
- 
-{{:content:retrocomputing:vic20-expansion.png?500|}} 
- 
-I settaggi DIP switch corrispondono alle linee del connettore di espansione del computer: 
- 
-{{:content:retrocomputing:vic20-expansion02.png?500|}} 
- 
-Dove: 
- 
-^Linea^RAM aggiuntiva^Note^ 
-|RAM1|1 KB|Nel BLK0| 
-|RAM2|1 KB|Nel BLK0| 
-|RAM3|1 KB|Nel BLK0| 
-|BLK1|8 KB|| 
-|BLK2|8 KB|| 
-|BLK3|8 KB|| 
-|BLK4|8 KB|| 
- 
-Qui uno schema della memoria di un VIC 20: 
- 
-{{:content:retrocomputing:memory_map.png?500|}} 
- 
-{{:content:retrocomputing:memory_map02.png?400|}} 
- 
-Di seguito è spiegato come settare i DIP switch per ottenere le espansioni RAM: 
  
-^RAM1^RAM2^RAM3^BLK1^BLK2^BLK3^BLK5^Diag^Espansione^Bytes free^ 
-|1|1|1|0|0|0|0|0|  3K|  6655| 
-|1|1|1|1|0|0|0|0|  8K|  11775| 
-|1|1|1|1|1|0|0|0|  16K|  19967| 
-|1|1|1|1|1|1|0|0|  24K|  28159| 
content/retrocomputing/vice.1720812372.txt.gz · Last modified: 2024/07/12 21:26 by admin