Leggere i programmi BASIC nella memoria del C64
Articolo di Alberto, pubblicato il 18-06-2004.
Categoria: Programmazione.

Se da ragazzino hai digitato qualche listato Basic sul tuo C64, del tipo di quelli contenuti su qualche rivista specializzata (io lo facevo spesso), probabilmente ti sarai chiesto almeno una volta 'Dove vanno a finire le linee Basic che digito?'. In altre parole 'Dove e con che criterio il C64 memorizza i programmi Basic digitati?'.

Cerchiamo di capirlo insieme.

Il C64 memorizza i listati Basic (come pure i programmi utente scritti in linguaggio macchina) nella sua RAM, cioè nella parte di memoria in cui è possibile scrivere dati.
All'accensione il C64 dispone di 38911 bytes atti a contenere programmi Basic (questa informazione, tra l'altro, è contenuta nella testata dell'interprete Basic stesso). Ora, all'accensione la RAM del C64 è organizzata circa in questo modo:

area testo basic -> area delle variabili (non array) -> area delle variabili (array) -> area RAM libera -> area stringhe dirette

Dopo aver acceso il nostro 64, digitiamo la seguente istruzione

PRINT PEEK(43):PRINT PEEK(44):PRINT PEEK(45):PRINT PEEK(46)
*

Che stampa a schermo il contenuto delle locazioni di memoria da 43 a 46 ($2B-$2E in esadecimale). Il risultato a schermo sarà:

1
8
3
8

Cosa significano queste cifre?

Le prime due cifre costituiscono l'indirizzo iniziale dell'area di memoria contenente il testo basic, mentre le altre due costituiscono l'indirizzo iniziale dell'area di tutte le variabili non array.

Da cui si ricavano i seguenti indirizzi:

43-44 ( puntatore ind. iniziale testo basic ) -> 1*1 + 8*256 = 1 + 2048 = 2049 ($0801 esadecimale)

45-46 ( puntatore ind. iniziale area variabili ) -> 3*1 + 8*256 = 3 + 2048 = 2051 ($0803 esadecimale)

Ciò significa che, all'accensione, il C64 memorizza il testo dei programmi Basic (cioè i listati che noi digitiamo a schermo) a partire dalla locazione n. 2049, mentre l'area che contiene la definizione delle variabili inizia subito dopo la fine del testo Basic (all'accensione della macchina, alla locazione n. 2051). Com'e' facile immaginare, i valori di queste locazioni cambieranno non appena digiteremo una qualunque riga basic in memoria.

Digitiamo ora:

PRINT PEEK(47):PRINT PEEK(48):PRINT PEEK(49):PRINT PEEK(50)

**

Avremo a schermo:

3
8
3
8

Queste locazioni contengono, rispettivamente, l'indirizzo d'inizio dell'area riservata a contenere le informazioni sulle variabili array, e l'indirizzo d'inizio della RAM libera, cioè non occupata da bytes riguardanti programmi Basic.

Da qui ricaviamo che, all'accensione, i puntatori al testo dei programmi Basic, alle variabili (normali e array), e alla RAM libera coincidono alla locazione 2051.

Queste locazioni punteranno ad indirizzi diversi tra loro, non appena definiremo delle variabili all'interno del nostro programma Basic.

Infine, digitiamo:

PRINT PEEK(51):PRINT PEEK(52)

Avremo stavolta:

0
160

Queste ultime due locazioni puntano all'indirizzo iniziale dell'area che gestisce le stringhe temporanee immesse in modo diretto (cioè non in modo programma). Ad esempio, l'istruzione

PRINT "COMMODORE 64"

memorizza una stringa temporanea (cioè non associata ad una variabile stringa) in modo diretto (cioè non dall'interno di una riga di programma).
Al contrario delle altre variabili, le stringhe temporanee dirette vengono allocate "dall'alto verso il basso", cioè a partire dalla locazione puntata dalle locazioni 49-50, in giù.
Deduciamo perciò che, all'accensione, le stringhe temporanee dirette vengono allocate a partire dalla locazione 40960 in giù( 0*1 + 160*256 ).

Questa è, di default, l'ultima locazione usata dai programmi Basic.

Digitiamo ora il seguente programma

10 A$="ALBERTO"
20 N%=1
30 PRINT "ESEMPIO"
40 DEF FN F(X)=X*2
50 FOR I=1 TO 2: A%(I)=I+1 : NEXT

Scrivendo queste righe, abbiamo inserito in memoria, a partire dalla locazione 2049, del testo Basic. Non solo;abbiamo anche definito una variabile stringa una variabile intera, una stringa temporanea indiretta, una variabile funzione, un array di interi non dimensionato ( formato quindi da 11 elementi ). Digitiamo di nuovo le istruzioni *, **, ***.

Scopriremo i seguenti valori:

43 ($2B) -> 1
44 ($2C) -> 8
45 ($2D) -> 91
46 ($2E) -> 8
47 ($2F) -> 91
48 ($30) -> 8
49 ($31) -> 91
50 ($32) -> 8
51 ($33) -> 0
52 ($34) -> 160

Il puntatore all'area delle variabili non array è stato spostato alla locazione 2139;ciò significa che il testo Basic, in memoria, si trova compreso tra la locazione 2049 ($0801) e la locazione 2138 ($085A).

Notiamo però che, nonostante abbiamo definito variabili normali e di tipo array, i puntatori all'area variabili e alla RAM libera coincidono ancora. . . com'e' possibile tutto ciò?
Il motivo è semplice;l'interprete Basic del C64 alloca variabili in memoria 'a Run-Time', cioè solo quando il programma Basic viene mandato in esecuzione.

Perciò, diamo ora RUN, e digitiamo ancora una volta *, **, ***.

I valori delle locazioni d'interesse sono ora:

43 ($2B) -> 1
44 ($2C) -> 8
45 ($2D) -> 91
46 ($2E) -> 8
47 ($2F) -> 126
48 ($30) -> 8
49 ($31) -> 155
50 ($32) -> 8
51 ($33) -> 0
52 ($34) -> 160

Da cui ricaviamo che le variabili non array sono state allocate nelle locazioni 2139-2173, mentre l'array è stato allocato nelle locazioni 2174-2202.

La RAM libera comincia dunque a partire dall'indirizzo 2203.

Il puntatore all'area delle stringhe temporanee dirette, invece, è rimasto invariato, in quanto l'unica stringa temporanea presente in memoria è contenuta nel nostro programma.

Adesso, disassembliamo il contenuto delle locazioni $0801-$085A con un qualsiasi programma monitor.

ATTENZIONE!!!IL MONITOR DEVE ESSERE CARICATO A PARTIRE DA UNA LOCAZIONE SUPERIORE ALLA 2202, ALTRIMENTI IL CONTENUTO DEL PROGRAMMA BASIC DIGITATO VERRA' SOVRASCRITTO

Ecco il dump esadecimale del testo del nostro programma

12 08 0A 00 41 24 B2 22 41 4C 42 45 52 54 4F 22 00 1B 08 14 00 4E 25 B2 31 00 2B 08 1E 00 99 20 22 45 53 45 4D 50 49 4F 22 00 3C 08 28 00 96 20 A5 20 46 28 58 29 B2 58 AC 32 00 59 08 32 00 81 20 49 B2 31 20 A4 20 32 3A 20 41 25 28 49 29 B2 49 AA 31 20 3A 20 82 00 00 00

I primi 2 byte di ogni istruzione indicano l'indirizzo d'inizio ( formato byte basso/alto ) della prossima istruzione in memoria.

I 2 byte successivi identificano la riga basic dell'istruzione ( formato byte basso/alto ).
Ogni istruzione termina col byte teminatore 0.

Tenendo conto di queste considerazioni, possiamo facilmente estrarre le righe che identificano ogni istruzione

 

CODICE NUMERICO ISTRUZIONE CODICE BASIC ISTRUZIONE NOTE
12 08 0A 00 41 24 B2 22 41 4C 42 45 52 54 4F 22 10 A$="ALBERTO" $22 è il codice Ascii di ", $24 di $
1B 08 14 00 4E 25 B2 31 20 N%=1 $25 è il cod. Ascii di %, $B2 è il cod. Ascii di =
2B 08 1E 00 99 20 22 45 53 45 4D 50 49 4F 22 30 PRINT "ESEMPIO" $99 è il codice operativo dell'istruzione PRINT
3C 08 28 00 96 20 A5 20 46 28 58 29 B2 58 AC 32 40 DEF FN F(X)=X*2 $96 è il cod. operativo di DEF, $A5 è il cod. operativo di FN
59 08 32 00 81 20 49 B2 31 20 A4 20 32 3A 20 41 25 28 49 29 B2 49 AA 31 20 3A 20 82 50 FOR I=1 TO 2: A%(I)=I+1 : NEXT $81 è il cod. op. di FOR, A4 è il cod. operativo di TO, $3A è il cod. Ascii di :, $28 è il cod. Ascii di (, $29 è il cod. Ascii di ), $82 è il cod. operativo di NEXT

 

I due 0 finali indicano al C64 un link a una linea basic inesistente;questo significa che il testo del programma Basic termina qui (ed è un informazione preziosa per le operazioni di LIST, di GOTO e di GOSUB).
Analizziamo ora l'area delle variabili non array (locazioni $085B-$087D). Il dump risulta essere

41 80 07 09 08 00 00 CE 80 00 01 00 00 00 C6 00 38 08

72 08 58 58 00 00 00 00 00 00 49 00 82 40 00 00 00

Sapendo che ogni variabile non array occupa 7 bytes, e che i primi 2 byte del descrittore contengono i primi 2 caratteri del nome della variabile stessa, si ha

 

DESCRITTORE VARIABILE VARIABILE BASIC NOTE
41 80 07 09 08 00 00 A il secondo byte ha il bit 7 settato, perciò A è una stringa;07 indica la lunghezza della stringa;gli altri 2 byte indicano l'indirizzo di partenza della stringa nell'area del testo basic ( formato byte basso/alto )
CE 80 00 01 00 00 00 N i primi 2 byte hanno il bit 7 settato, quindi N è un numero intero;i due byte successivi indicano il valore della variabile intera ( formato byte basso/alto )
C6 00 38 08 72 08 58 F il primo byte ha il bit 7 settato, perciò F è una funzione;il terzo e quarto byte indicano l'indirizzo in cui è definita la funzione;i due bytes successivi indicano l'indirizzo di partenza del descrittore della variabile indipendente;l'ultimo byte indica il nome della variabile indipendente
58 00 00 00 00 00 00 X i primi due byte indicano il nome della variabile
49 00 82 40 00 00 00 I i primi due byte indicano il nome della variabile;i 2 byte successivi indicano che si tratta di una variabile di conteggio intera con valore finale 2

E ora, passiamo ad esaminare il contenuto dell'area delle variabili array (locazioni $087E-$089A)

C1 80 1D 00 01 00 0B 00 00 00 02 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Anche i descrittori degli array occupano 7 bytes in memoria, per cui

DESCRITTORE ARRAY ARRAY BASIC NOTE
C1 80 1D 00 01 00 0B A I primi 2 byte hanno il bit 7 settato, quindi si tratta di un array di numeri interi;i 2 byte successivi indicano lo spiazzamento del prossimo array in quest'area ( formato byte basso/alto );il byte successivo indica il numero di dimensioni dell'array;il sesto byte indica il numero di righe dell'array (matrice), l'ultimo byte indica il numero di colonne dell'array (array monodimensionale o matrice)

Gli altri byte contengono i valori degli elementi dell'array ( formato byte alto/basso )

DESCRITTORE

ELEMENTO ARRAY

VARIABILE BASIC NOTE
00 00 A(0) valore = 0
00 02 A(1) valore = 2
00 03 A(2) valore = 3
00 00 A(3) valore = 0
00 00 A(4) valore = 0
00 00 A(5) valore = 0
00 00 A(6) valore = 0
00 00 A(7) valore = 0
00 00 A(8) valore = 0
00 00 A(9) valore = 0
00 00 A(10) valore = 0

ALCUNI ACCORGIMENTI NELLO SCRIVERE PROGRAMMI BASIC

Da questa analisi dei programmi Basic e dei puntatori alle sezioni di memoria che lo costituiscono, è possibile imparare alcune "dritte":
  • per far coesistere 2 o più programmi Basic in memoria si possono modificare i puntatori di inizio del testo basic
  • è possibile creare una sezione di RAM non influenzata da eventuali programmi Basic (ad esempio, per definire sprites, o set di caratteri personalizzati, o ancora routines in linguaggio macchina da far interagire coi programmi Basic stessi ) alterando i puntatori alle stringhe temporanee e le locazioni n. 55-56 (che puntano all'indirizzo più alto usato dal Basic stesso)
  • è anche possibile alterare 'a Run-time' i valori di alcune variabili in memoria, conoscendone l'esatta locazione
  • è possibile 'criptare' i bytes dei propri programmi Basic in modo da proteggerli da sguardi indiscreti, che poi, una volta caricati, possono essere decodificati, o proteggerli semplicemente nascondendone il listato (per far questo, è sufficiente modificare i primi due bytes del testo basic, ponendoli a 0; questo stratagemma "inganna" il C64, indicandogli che nessun listato Basic è presente in memoia, anche se, in effetti, non è così)

Insomma... hai capito che l'unico limite sta solo nella tua inventiva e nella tua curiosità!

| | Share
Commenti
Commenta gioco Ci sono 3 commenti per questo articolo. Registrati se vuoi lasciarne uno.
Complimenti!!!!!!! Sei veramente un genio!!!!! W il C64
# - postato da OISSELA1972 - 31 August 2005 [07:12]
Adesso mi ci rimetto anche io a programmare, e ti faccio vedere che ti combino. :) ahhahahah WWW AmigaOS WWW - WWW C64 WWW - WWW Commodore WWW
@ - postato da SpawnPPC - 19 February 2010 [15:09]
sono in linea con il commento
@ - postato da anna cristina - 25 March 2010 [20:04]
Commodore 64
Utenti Online
Ciao, ospite!
(Login | Registrati)

Cerca un gioco
Random Game
Ultimo Commento
Clicca per leggere tutti i commenti
Teenage Mutant Hero Turtles - The Coin-Op!
"Davvero un giocone !! Grafica, musica, gameplay da urlo. L'unica pecca (e purtroppo non è una pecca da poco) è il bilanciamento della difficoltà, praticamente nullo. Finito al secondo o terzo tentativo, l'ho rigiocato di recente, dopo molti anni e dopo essermi totalmente disabituato (ma si può dire "disabituato"?) allo stile di gioco anni '90 ma niente da fare, sfida pressochè nulla. Fosse stato un pochetto più difficile, si sarebbe beccato un 10 senza ombra di dubbio, ma resta comunque una delle conversioni migliori di tutti i tempi."
- Scritto da Nicco
Ult. Commento Art.
Intervista ad Antony Hager e Paul Docherty
"Intervista da pelle d'oca e molto interessante!Non immaginavo minimamente che dietro la fase di guida di VENDETTA ci fosse la mano "DriftEsperta"di Butler, dopo eoni si scoprono cose e si comprende meglio il perchè di tale qualità.GRAZIE ..."
- Scritto da Amy-Mor
Ospitato su