| Pur non essendo possibile derogare a questa regola, la
dimensione di un EXE può talvolta essere anche più
grande di 256k: questo è possibile per la possibilità di
applicare la tecnica degli Overlay
che consente di occupare la memoria in dotazione con pezzi di programma (overlay)
di volta in volta diversi, in funzione delle esigenze
contingenti, rigorosamente al posto di altri; gli overlay (copertura)
sono dunque parti di codice alternative, contenute comunque nell'EXE, così
da portare la dimensione di questi ultimi a valori maggiori di 256k. |
| Vediamo in dettaglio le fasi di allocazione
di
un EXE da parte del loader del
Dos:
| legge in memoria i primi 27
bytes dell'header (Informazioni di controllo).
NB: le citazioni agli offset,
indicate nei punti seguenti sono riferire a questa parte dell'header. |
| riserva (alloca)
una porzione di memoria in funzione della dimensione del modulo
caricabile e dei numeri di allocazione (offset 000A
e offset 000C).
In ogni caso il Dos tenta di allocare 65536 paragrafi (FFFFH), pari ad
un gigaBytes di memoria e, non essendo (ovviamente) in grado di farlo, riceve (da se
stesso, cioè dalle sue funzioni) tutta la memoria attualmente
libera. Se è più grande della minima necessaria (cioè
quella del programma caricato più quella indicata dall'offset
000A,
MinimunAllocation) il Dos alloca la
quantità specificata all'offset 000C,
MaximunAllocation; in alternativa
allocherà la maggior quantità possibile. |
| crea un Prefisso di Segmento di
programma (PSP). |
| determina la lunghezza del modulo
caricabile (cioè quella del programma, al netto dell'header
stesso) sottraendo la dimensione dell'header (offset 0008,
HeaderParagraphs) da quella del file (offset 0004,
PageCount) ed aggiustandola verso il basso in funzione del valore dell'offset 0002,
LastPageSize. |
| carica il modulo
caricabile subito dopo il PSP. |
| localizza l'inizio della Tabella di
Rilocazione (offset 0018,
StartOfRelocationTable):
analizza le sue voci, cioè tutti i riferimenti ai registri di segmento presenti nel
modulo caricabile, e provvede a ricalcolarne il valore in funzione del valore della voce e di quello del segmento in cui viene caricato il modulo; il risultato viene sostituito a quello irrisolto, nel modulo stesso. |
| carica i registri di segmento DS
e ES in modo da puntare il PSP
(e quindi all'inizio del primo segmento trovato libero); poiché i dati
del nostro programma sono inseriti in segmenti solitamente diversi
da questo, il programmatore deve provvedere a scrivere le istruzioni necessarie ad obbligare il processore (in
run-time) a puntare le zone dati ed extra-dati effettive. |
| carica la coppia CS:IP
in modo da puntare all'interno del segmento di
codice sulla base delle indicazioni lasciate dal Linker per
CS all'offset 0016,
InitialCS, e per IP
all'offset 0014,
InitialIP (a sua volta impostate dall'assemblatore a partire
dal valore dell'etichetta d'indirizzo (per esempio INIZIO)
scritta subito dopo la direttiva END). |
| carica la coppia SS:SP
in modo da puntare all'interno del segmento di
stack
sulla base delle indicazioni lasciate dal Linker per
SS all'offset 000E,
InitialSS, e per SP
all'offset 0010,
InitialSP
(a sua volta impostate
dall'assemblatore a partire dal valore dell'etichetta STACK
scritta subito dopo la direttiva SEGMENT). |
| naturalmente segnala errore se la memoria
disponibile non è sufficiente a contenere il nostro modulo
caricabile, sempre con l'aiuto delle tabelle dell'header (minimum load size,
dimensione
minima di caricamento).
|
| quando tutto questo è stato portato a
termine cede il controllo al modulo eseguibile
EXE e il programma
comincia a girare in memoria... |
|