- Programmazione » Programmazione » Guida C - Manuale programmazione con articoli e risorse interessanti
I puntatori: gli indirizzi di memoria
PUNTATORI
Proviamo ad immaginare la memoria come una sequenza di
piccoli contenitori, ciascuno dei quali rappresenta un byte:
ad ogni "contenitore" , talvolta detto
"locazione" , potremo attribuire un numero
d'ordine, che lo identifica univocamente. Se il primo
byte ha numero d'ordine 0, allora il numero assegnato ad
un generico byte ne individua la posizione in termini di
spostamento (offset) rispetto al primo byte,
cioè rispetto all'inizio della memoria.
Così, il byte numero 12445 dista proprio 12445 byte
dal primo, il quale, potremmo dire, dista 0 byte da se
stesso. L'indirizzamento (cioè l'accesso alla
memoria mediante indirizzi) avviene proprio come appena
descritto: ogni byte è accessibile attraverso il suo
offset rispetto ad un certo punto di partenza, il quale,
però, non necessariamente è costituito dal
primo byte di memoria in assoluto. Vediamo
perché.
Nella CPU del PC sono disponibili alcuni byte, organizzati
come vere e proprie variabili, dette registri
(register). La CPU è in grado di effettuare
elaborazioni unicamente sui valori contenuti nei propri
registri (che si trovano fisicamente al suo interno e non
nella RAM); pertanto qualunque valore oggetto di elaborazione
deve essere "caricato" , cioè scritto, negli
opportuni registri. Il risultato delle operazioni compiute
dalla CPU deve essere conservato, se necessario, altrove
(tipicamente nella RAM), al fine di lasciare i registri
disponibili per altre elaborazioni.
Anche gli indirizzi di memoria sono soggetti a questa
regola.
I registri del processore Intel 8086 si compongono di 16 bit
ciascuno, pertanto il valore massimo che essi possono
esprimere è quello dell'integer, cioè
65535 (esadecimale FFFF): il massimo offset
gestibile dalla CPU permette dunque di indirizzare una
sequenza di 65536 byte (compreso il primo, che ha offset pari
a 0), corrispondenti a 64Kb.
Configurazioni di RAM superiori (praticamente tutte) devono
perciò essere indirizzate con uno stratagemma: in
pratica si utilizzano due registri, rispettivamente detti
registro di segmento (segment register) e registro di
offset (offset register). Segmento e offset vengono
solitamente indicati in notazione esadecimale, utilizzando i
due punti (":") come separatore, ad
esempio 045A:10BF. Ma non è tutto.
Se segmento e offset venissero semplicemente affiancati, si
potrebbero indirizzare al massimo 128Kb di RAM: infatti si
potrebbe avere un offset massimo di 65535 byte a partire dal
byte numero 65535. Quello che occorre è invece un
valore in grado di numerare, o meglio di indirizzare, almeno
1Mb: i fatidici 640Kb, ormai presenti su tutte le macchine in
circolazione, più gli indirizzi riservati al BIOS e
alle schede adattatrici[5]. Occorre, in altre parole,
un indirizzamento a20 bit[6].
Questo si ottiene sommando al segmento i 12 bit più
significativi dell'offset, ed accodando i 4 bit rimanenti
dell'offset stesso: tale tecnica consente di trasformare
un indirizzo segmento:offset in un indirizzo
lineare[7]. L'indirizzo seg:off di poco fa
(045A:10BF) corrisponde all'indirizzo lineare
0565F, infatti 045A+10B = 565 (le prime 3
cifre di un valore esadecimale di 4 cifre, cioè a 16
bit, corrispondono ai 12 bit più
significativi).
Complicato? Effettivamente... Ma dal momento che le cose
stanno proprio così, tanto vale adeguarsi e cercare di
padroneggiare al meglio la situazione. In fondo è
anche questione di abitudine.