Il Program Segment Prefix


Il Program Segment Prefix (abbreviato in PSP), occupa i primi 256 byte (16 paragrafi) del program segment assegnato ad un programma EXE o COM da eseguire; siccome il program segment è allineato al paragrafo, anche il PSP sarà, a sua volta, allineato al paragrafo. Lo scopo del PSP, è quello di contenere una serie di importanti informazioni, che vengono utilizzate, sia dal DOS, sia dal programma in esecuzione.
Analizziamo le caratteristiche, in versione Assembly (sintassi MASM), della struttura del PSP; per comodità, sulla sinistra della struttura sono stati riportati anche gli offset interni dei vari membri. Il contenuto di diversi membri del PSP rimane inutilizzato, in quanto si riferisce alle primissime versioni del DOS, che risentivano ancora dell'influenza del SO predecessore, cioè il CP/M (Control Program for Microcomputer); come molti ricorderanno, il CP/M, sviluppato dalla Digital, veniva utilizzato anche da alcuni modelli di microcomputer Commodore.

Analizziamo il significato dei campi che formano il PSP; si tenga presente che i campi privi di nome sono riservati al DOS.

TerminateLocation (indirizzo di fine esecuzione)

Questo campo da 16 bit, contiene il codice macchina di una istruzione (INT 20h) che termina il programma in esecuzione e restituisce il controllo al DOS; in sostanza, se un programma vuole terminare la propria esecuzione, deve effettuare un salto all'offset 0000h del PSP. Si ottiene lo stesso risultato, attraverso una chiamata diretta alla INT 20h; questi metodi di terminazione di un programma, sono ormai obsoleti e continuano ad esistere solo per motivi di compatibilità con le vecchissime versioni del DOS.

EndOfAllocatedMemory (fine della memoria allocata)

Questo campo da 16 bit, contiene la componente Seg dell'indirizzo da cui inizia il primo segmento di memoria, successivo al program segment del programma in esecuzione; possiamo dire quindi che, il primo segmento di memoria successivo al program segment del programma in esecuzione, parte dall'indirizzo logico EndOfAllocatedMemory:0000h.

OldDosCallLocation (vecchio indirizzo per le chiamate al DOS)

Questo campo da 5 byte, è un retaggio del vecchio CP/M; i programmi che giravano su CP/M, richiedevano i servizi del SO attraverso una chiamata al codice macchina presente appunto all'offset 0005h del PSP. Naturalmente, questo campo non viene utilizzato dal DOS; nelle versioni più recenti del DOS, le richieste dei servizi del SO vengono effettuate attraverso una chiamata della INT 21h (interrupt dei servizi DOS).

SavedInt22Pointer, SavedInt23Pointer, SavedInt24Pointer

(copie degli indirizzi delle ISR per le INT 22h, 23h e 24h).
Prima di eseguire un programma, il DOS salva in questi tre campi da 32 bit ciascuno, gli indirizzi logici Seg:Offset delle ISR corrispondenti alle tre INT, 22h (terminate address), 23h (control break address) e 24h (critical error address); in questo modo, il programma in esecuzione può installare proprie ISR per gestire queste tre INT, senza preoccuparsi di salvare gli indirizzi delle ISR predefinite. Quando il programma termina, il DOS provvede ad effettuare tutte le operazioni di ripristino dei vecchi indirizzi.

ParentPspSegment (segmento PSP del padre)

Questo campo da 16 bit, contiene la componente Seg dell'indirizzo da cui inizia il PSP del padre del programma in esecuzione; siccome il PSP è sempre allineato al paragrafo, possiamo dire che il PSP del padre del programma in esecuzione, inizia dall'indirizzo logico ParentPspSegment:0000h.

HandleIndexTable (tabella degli indici delle handle)

Un programma DOS in esecuzione, può aprire, se necessario, un certo numero di file su disco; quando si apre un file su disco, il DOS restituisce un valore a 16 bit, chiamato handle (maniglia), che viene utilizzato per identificare il file stesso. Le handle di tutti i file correntemente aperti da tutti i programmi in esecuzione, vengono memorizzate in una tabella globale che prende il nome di SFT o System File Table; ogni elemento di questa tabella, contiene la descrizione completa di uno dei file aperti.
Ogni programma in esecuzione, è dotato a sua volta di una tabella locale chiamata handle index table; ogni elemento di questa tabella, è un indice che individua nella SFT uno dei file aperti dal programma stesso.
Il campo HandleIndexTable è un vettore di 20 byte, dove ciascun byte rappresenta un indice; questo sistema permette quindi ad un programma, di aprire sino a 20 file contemporaneamente.

EnvironmentSegment (segmento d'ambiente)

Questo campo da 16 bit, contiene la componente Seg dell'indirizzo da cui inizia in memoria l'environment segment di un programma in esecuzione; siccome l'environment segment è sempre allineato al paragrafo, il suo indirizzo logico iniziale completo è EnvironmentSegment:0000h. Un programma in esecuzione, pur potendo accedere al suo environment segment, non deve assolutamente modificarne il contenuto.

HandleIndexTableLength (lunghezza della tabella degli indici delle handle)

Questo campo da 16 bit, contiene il numero massimo degli elementi che possono trovare posto nella handle index table; se la tabella è contenuta nel PSP, questo numero è 20.

HandleIndexTablePtr (indirizzo della tabella degli indici delle handle)

Se un programma vuole aprire più di 20 file contemporaneamente, deve disporre di una tabella più grande di quella contenuta nel PSP; il campo HandleIndexTablePtr da 32 bit, contiene l'indirizzo logico completo Seg:Offset da cui inizia in memoria la handle index table. Eventualmente, questo indirizzo può anche puntare alla stessa handle index table presente nel PSP.

NewDosCallLocation (nuovo indirizzo per le chiamate ai servizi DOS)

Questo campo da 3 byte, rappresenta una procedura che contiene il codice macchina delle due istruzioni:
INT 21h
e
RET
La prima istruzione chiama la INT 21h (interrupt dei servizi DOS); la seconda istruzione, restituisce il controllo al chiamante.
In sostanza, un programma che vuole eseguire questo codice, deve chiamare la procedura che si trova all'offset 0050h del PSP; si tratta di un procedimento contorto, che può essere tranquillamente evitato chiamando la INT 21h direttamente dal programma.

FirstFCB, SecondFCB (prima e seconda FCB)

Gli FCB o File Control Blocks, rappresentavano il sistema utilizzato nella versione 1.0 del DOS, per la gestione dei file su disco; questo sistema è ormai obsoleto, ed è stato sostituito dalla SFT o System File Table.

CommandLineParmLength (lunghezza effettiva della stringa dei parametri passati dalla linea di comando)

Questo campo da 1 byte, contiene la lunghezza effettiva della stringa, che l'utente ha passato dalla linea di comando, ad un programma da eseguire.

CommandLineParameters (stringa dei parametri passati dalla linea di comando)

Questo campo da 127 byte, contiene la stringa che racchiude l'insieme dei parametri che l'utente ha passato dalla linea di comando, ad un programma eseguibile; questa stringa termina con un byte di valore 0Dh, che è il codice ASCII del carriage return (ritorno carrello), corrispondente al tasto [Invio].
Consideriamo, ad esempio, un programma NOMEPROG.EXE che viene eseguito con il comando:
nomeprog mela pera limone ciliegia
In questo caso, il campo CommandLineParameters assume, in versione Assembly, il seguente aspetto:
CommandLineParameters db ' mela pera limone ciliegia', 0Dh
Si noti che anche lo spazio (codice ASCII 20h) presente tra nomeprog e mela, viene inserito nella stringa dei parametri; in questo esempio, il campo CommandLineParmLength contiene il valore 26, che non comprende il byte finale 0Dh.
Se si ha la necessità di elaborare queste informazioni, si consiglia di farlo non appena inizia l'esecuzione di un programma; la cosa migliore da fare, consiste nel salvare da qualche parte, il contenuto di CommandLineParmLength e CommandLineParameters.