|
|
Guida al Linguaggio C
II
Parte
La prima voce indica il tipo di disco ed esattamente :
Valore HEX Significato
-----------------------------------------
FF Doppia faccia, 8 settori
FE Singola faccia, 8 settori
FD Doppia faccia, 9 settori
FC Singola faccia, 9 settori
F9 Doppia faccia, 15 settori
F8 Disco fisso
Il secondo, il terzo e il quarto bytes contiene FFFFH.
Ogni successiva voce della FAT contiene il successivo cluster del file con due particolari significati.
Un valore pari a 000H indica che il cluster e' libero e disponibile.
Nel caso che si esegua la cancellazione di un file si puo' notare che le voci della FAT relative a questo vengono messe a zero.
Nel caso di occupazione si puo' ricostruire la catena del file.
Es.
Voce FAT Valore Descrizione
-----------------------------------------
. ... ................
5 7 Next cluster = 7
6 FF7 Avariato
7 8 Next cluster = 8
8 FFF Fine file
ecc.
Nell'esempio precedente avrete notato la presenza di due valori particolari.
Nel caso che una voce della FAT contenga FF7H significa che il cluster e' stato marcato come avariato in fase di formattazione.
Questo chiaramente non sara' disponibile.
FFFH indica la fine della catena relativa a un file.
In altre parole significa che il file e' terminato.
Il Dos gestisce due copie della FAT sul dischetto nel caso che una venga rovinata.
La prima occupa il settore immediatamente successivo al settore di boot.
Il discorso fatto fino ad ora sulla FAT risulta estremamente semplice.
Purtroppo questa e' solo la teoria in quanto il metodo utilizzato fisicamente dal Dos per gestire la FAT e' un po' piu' complicato.
L'organizzazione fisica della FAT viene fatta con un metodo di memorizzazione a rovescio.
Nel caso di una FAT a 12 bit ogni valore relativo a una voce della stessa e' organizzato in modo che questo risulti essere un
valore di tre cifre (000H-FFFH) e cioe' rappresentabile appunto
con 12 bit.
L' organizzazione avviene a coppie di tre bytes ciascuna.
Se questa coppia di voci risulta essere
ABC DEF (in bytes AB CD EF)
ribaltando il tutto i valori relativi a ogni voce saranno
DAB EFC
Per calcolare ogni successivo cluster di un file partendo dal primo segnato nei campi della directory, che vedremo, sono necessari i seguenti calcoli (relativi a una FAT da 12 bit).
Si moltiplica il numero del cluster appena usato per 1.5.
La parte intera del risultato del prodotto e' un offset all'interno della FAT che contiene il numero del successivo cluster del file.
Se il numero del cluster era un numero pari allora si valutano i 12 bits di ordine piu' basso del valore a 16 bit ottenuto.
In caso contrario i bits da considerare sono i 12 di ordine piu' alto.
Come e' gia' stato detto se il contenuto di un cluster e' FF8H o FFFH allora si e' giunti alla fine del file.
Per convertire il cluster nel settore logico sono necessarie le seguenti operazioni.
Si sottrae 2 dal numero del cluster e si moltiplica questo per il numero di settori per cluster.
Successivamente si addiziona il numero del settore in cui incomincia l'area data del disco.
Una FAT a 16 bits mantiene gli stessi riferimenti solo che, ad esempio, la fine del file viene segnata da FFFFH anziche' FFFH mentre un cluster errato e' FFF7H invece di FF7H.
Nel caso di una FAT a 16 bit i calcoli da fare sono piu' semplici.
Si moltiplica il numero del cluster contenuto in uno dei campi della directory per due.
Se il contenuto e' FFFFH significa che il file e' terminato altrimenti il valore corrisponde al successivo cluster del file.
Sembrera' fuori luogo la descrizione dell'organizzazione della directory sul disco ma penso che sia utile trattarla a questo punto visto che parlando della FAT ho accennato a un campo che conteneva il primo cluster di un file.
Ogni ingresso della directory e' composto da 32 bytes cosi suddivisi :
Bytes 0-7
Il primo bytes potrebbe essere la prima lettera del nome del file oppure uno dei seguenti valori :
00H - File non usato. Viene inserito per limitare la ricerca sulla directory.
E5H - Indica che il file e' stato cancellato.
2EH - Indica che si tratta di una subdirectory.
Nel caso che il nome di un file non sia lungo 8 caratteri il campo viene completato mediante degli spazi (ASCII 32).
Bytes 8-10
Indica l'estensione del file.
Bytes 11
Contiene l'attributo del file (1 byte).
I codici relativi ai vari tipi possibili sono gia' stati riportati parzialmente nel programma d'esempio che leggeva la directory e la mostrava in una finestra video.
L'elenco completo e' il seguente :
01H - File marcato come read-only.
02H - Hidden file (file nascosto)
04H - System file
08H - Volume label
10H - Sub directory
20H - Bit archivio (Usato da BACKUP e RESTORE)
Per semplificare si puo' immaginare il byte di attributo nel seguente modo :
+---+---+---+---+---+---+---+---+
: 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0 :
+---+---+---+---+---+---+---+---+
: : : : : : : :
Non usati : : : : : 1 = read only
: : : : 1 = Hidden
: : : 1 = System
: : 1 = Volume label
: 1 = Subdirectory
1 = Archivio di bit
Bytes 12-21
Riservati al Dos.
Bytes 22-23
Questi bytes contengono l' ora di quando il file e' stato creato o quella relativa all'ultima modifica.
L'interpretazione dei due bytes e' la seguente :
:---------- Byte 23 ------------:---------- Byte 22 ------------:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ :15 :14 :13 :12 :11 :10 : 9 : 8 : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0 :
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
: : : : : : : : : : : : : : : :
h h h h h m m m m m m x x x x x
dove
h e' il numero delle ore (0-23)
m e' il numero dei minuti (0-59)
x e' il numero di incrementi di due secondi
Bytes 24-25
Mentre nei precedenti due bytes veniva conservata l'ora in questi ritroviamo la data della creazione del file o dell'ultima modifica.
:---------- Byte 25 ------------:---------- Byte 24 ------------:
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ :15 :14 :13 :12 :11 :10 : 9 : 8 : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0 :
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ : : : : : : : : : : : : : : :
y y y y y y y m m m m d d d d d
dove
y e' l'anno (0-119)
d e' il giorno (1-31)
m e' il mese (1-12)
Bytes 26-27
Ecco finalmente il valore che indica dove inizia il file.
Parlando precedentemente della FAT avevamo accennato a questo
campo della directory dicendo che da questo iniziava la catena di
assegnazione dello spazio della FAT.
Il technical reference riporta che il primo cluster per i dati,
sia nel caso del disco fisso che in quello dei dischetti, e'
sempre il cluster 002.
Bytes 28-31
In questi due bytes viene conservata la dimensione del file.
La prima word (2 bytes) contiene la parte bassa del valore mentre la seconda la parte alta.
Il discorso partito dal servizio 1BH e' un po' degenerato ma, come avevo detto prima, era necessario per chiarire alcuni concetti fondamentali che il servizio stesso tratta.
Sarebbe possibile leggere direttamente su disco il settore in cui sono conservati questi dati relativi alla FAT e alla directory mediante il gia' citato int 25H.
Mediante la call 1BH e' possibile avere comodamente i dati basilari della FAT senza dover eseguire operazione di lettura diretta.
I valori riportati sono i seguenti.
DS:BX puntano al byte di identificazione della FAT (ID) del drive di default.
DX contiene il numero totale di cluster su disco mentre AL indica quanti settori sono riservati per ogni unita' di allocazione.
In genere questo valore e' uno nel caso di dischetti singola faccia mentre e' due nel caso di doppia faccia.
In ultimo CX contiene il numero di bytes per ogni settore.
1CH - Allocation Table Information for Specific Device
Il servizio e' in pratica uguale al 1BH solo che in questo caso non e' piu' relativo al disco di default ma mediante il registro DL, in ingresso, e' possibile specificare il numero del drive interessato (0 = default, 1 = A:, ecc.).
21H - Random Read
Il servizio legge un blocco casuale da un file.
Il numero del blocco deve essere specificato nel FCB che e' puntato da DS:DX alla chiamata della funzione.
I valori restituiti sono contenuti in AL e precisamente si possono avere le seguenti condizioni.
00H - Lettura eseguita con successo
01H - Lettura fallita (EOF)
02H - DTA troppo piccolo
03H - Lettura parziale (EOF)
22H - Random Write
All'opposto del servizio 21H che legge questo scrive un record in un file casuale.
Anche in questo caso, come per la funzione precedente, il numero del blocco deve essere settato all'interno dell'apposito campo del FCB che viene puntato dai registri DS:DX.
I valori riportati in AL dal servizio sono :
00H - Scrittura eseguita con successo
01H - Disco pieno
02H - DTA troppo piccolo
23H - File Size
Il servizio 23H riporta le dimensioni di un determinato file.
Il registro AL puo' restituire due diversi valori
00H - il file e' stato trovato
FFH - il file non e' stato trovato
La dimensione del file non viene riportata direttamente all'interno di qualche registro ma bensi' piazzata nell'apposito campo del FCB (Bytes 16-19).
24H - Set Realtive Record Field
Setta il campo del record casuale in modo che corrisponda agli attuali campi dei record del FCB.
Si deve, in genere, chiamare questa funzione prima di eseguire una lettura o una scrittura
random.
25H - Set Interrupt Vector
Questa call non risultera' nuova in quanto l'ho gia' utilizzata in un esempio precedente accennando soltanto al suo scopo.
Mediante questa funzione e' possibile settare l'indirizzo di una routine di servizio di un interrupt.
Piu' avanti vedremo la funzione opposta ovvero quella che riporta il segmento e l'offset di un interrupt specificato (anche questa e' gia' stata utilizzata precedentemente in alcuni esempi).
In quali casi ritorna utile scriversi delle particolari funzioni di servizio degli interrupts o modificare quelle esistenti ?
Rispondere in modo preciso alla domanda non e' possibile in quanto esistono un infinita' di situazioni in cui potrebbe rivelarsi utile modificare o addirittura scrivere le routine di servizio.
Un esempio potrebbe essere portato da un programma residente in memoria.
Le vie da seguire, in questo caso, potrebbero essere svariate.
Uno dei metodi potrebbe essere la scrittura di una routine da collegare all'interrupt di timer (INT 1CH) che esegua un controllo periodico sul buffer di tastiera per individuare eventuali tasti premuti.
Un'altro metodo, gia' visto precedentemente, e' quello di modificare il servizio di interrupt che serve la tastiera allo scopo di fare eseguire un controllo sui codici dei caratteri.
Un altro esempio di scrittura integrale potrebbe essere quello relativo alla gestione delle porte di comunicazione.
In alcuni programmi di questo tipo si potrebbe sostituire una routine di polling con una funzione di interrupt.
In altre parole al posto di testare mediante cicli ripetitivi lo stato del modem e della linea si potrebbe fare in modo che sia una chiamata di interrupt, eseguita in modo automatico, ad assolvere al compito desiderato.
La scrittura in linguaggio C di una routine di interrupt presenta alcuni problemi eliminabili mediante alcune funzioni, da abbinare al modulo principale, scritte in assembler.
In ogni caso preferisco rimandare l'argomentazione all'apposito capitolo riguardante la scrittura di programmi residenti in memoria.
Proprio ultimamente sono riuscito a reperire la documentazione riguardante gli interrupts non documentati dalla Microsoft e cioe' quelli definiti "strategici".
Il discorso penso che sara' abbastanza lungo ed e' proprio per questo motivo che ho optato per una trattazione separata dell'argomento.
Per ora limitiamoci a ripetere la sintassi di utilizzo di questo servizio.
AH contiene quindi 25H che e' il numero della call.
DS:DX puntano al segmento e all'offset della routine dell'interrupt.
AL, infine, contiene il numero dell'interrupt di cui si vuole settare l'indirizzo della funzione di servizio.
La call 25H non restituisce alcun valore dopo la chiamata dell'interrupt 21H.
26H - Create New Program Segment
Lo scopo della call e' quello di creare un nuovo segmento di programma per l'esecuzione di un processo caricato separatamente.
Un esempio e' relativo al caricamento di un file di overlay.
Il registro DX viene utilizzato per passare alla funzione il valore del paragrafo di segmento per il nuovo processo.
Il servizio copia nel nuovo segmento creato il PSP relativo al programma chiamante ed esegue su questo alcune modifiche.
E' inutile dire che anche in questo caso il valore relativo alla call e' settato in AH.
Non viene restituito alcun valore.
Andando anche in questo caso fuori dall'argomento e' necessario aprire una parentesi riguardante il significato del PSP (Program
Segment Prefix).
Quando il Dos carica per l'esecuzione un programma crea quello definito PSP.
Si tratta di un area di memoria collocata in testa al programma dove vengono conservati molti dati utilizzati dallo stesso Dos per l'esecuzione di questo.
Il PSP viene sempre piazzato all'offset 0 nel segmento di codice.
Il programma , se .COM, viene collocato all'offset 100H.
In caso di un programma .EXE questo valore potrebbe essere diverso.
Infatti nel caso di un programma .EXE, dopo il caricamento, i regsitri DS e ES puntano al PSP mentre i registri CS, IP, SP e SS sono settati al valore passato dal linker.
A differenza, nei .COM, tutti i registri di segmento puntano inizialmente al PSP.
Il registro IP, in quest' ultimo caso, punta sempre a 100H nel segmento di codice.
Come vedremo nei seguenti capitoli esistono alcune funzioni che permettono di avere di ritorno il segmento in cui e' piazzato il
PSP o di settarlo.
Un discorso di questo tipo diventa importante nel momento in cui si vuole scrivere un programma residente in memoria.
Un idea piu' chiara a riguardo del PSP e' possibile farsela guardando la sua struttura.
0 +---------+--------+--------+-------------------+
: INT 20H :Dim.Mem.: Riserv.: Dispacciatore DOS:
8 +---------+--------+--------+-------+-----------+
: :Terminate address:(IP,CS): CTRLC IP :
10 +---------+-----------------+---+---------------+
:CTRLC CS :Critical Error IP,CS : :
+---------+---------------------+ :
: Used by Dos 2C :
: 5C +------------------------+
: : Formatted Parameter :
+----------------------+ Area 1 formatted as :
: standard unopened FCB :
: 6C +------------------------+
: : Formatted Parameter :
+----------------------+ Area 2 formatted as :
: unopened FCB (overlaid if FCB at 5C is opened):
80 +-----------------------------------------------+
: Unformatted parameter area (DTA) :
100 +-----------------------------------------------+
Vediamo ora singolarmente ogni campo del PSP.
Il primo campo inizia all'offset 00H ed e' lungo 2 bytes.
Contiene l'istruzione INT 20H che come vedremo e' uno dei metodi per terminare un programma.
Come e' facile capire se il programma deve terminare basta che punti a questo campo.
Il secondo campo inizia all'offset 02H ed e' lungo 2 bytes.
In questo viene conservata la dimensione della memoria in paragrafi.
Come avevamo gia' detto, parlando dei registri di segmento, un paragrafo e' lungo 10H bytes (16 in decimale).
Da questo risulta facile calcolare il numero di bytes disponibili. (NUMERO PARAGRAFI x 16 = MEMORIA)
In alcuni casi si potrebbe verificare che il numero di bytes riportati non corrispondano effettivamente all'ammontare della memoria rimasta libera.
Alcuni programmi eseguono delle particolari scritture nelle tabelle del Dos al fine di modificare l'indicatore della fine della memoria disponibile.
Saltando il terzo campo che e' riservato al Dos arriviamo al quarto ovvero a quello definito come dispacciatore delle funzioni del Dos.
Il campo si trova all'offset 05H ed e' lungo 5 bytes.
Il suo scopo e' quello di contenere l'indirizzo della routine di controllo delle funzioni Dos (INT 21H).
Il sesto campo, offset 0AH, e' lungo 4 byte e contiene una copia dell'indirizzo della routine di terminazione del programma.
Questo infatti punta alla routine che deve essere eseguita quando il programma termina.
Un altro campo inizia all'offset 0EH ed e' lungo 4 byte come il precedente.
Viene contenuta in questa locazione una copia dell'indirizzo di ctrl-break.
A partire dall'offset 12H per 4 byte ritroviamo il vettore d'errore (Critical error exit).
All'offset 16H troviamo un'area di lavoro del Dos lunga 22 bytes.
Il puntatore alle variabili d'ambiente sono all'offset 2CH.
Nei due bytes da questo offset sono scritti segmento e offset dell'area in cui sono conservate le variabili di sistema.
Per variabili di sistema intendo dire, ad esempio, il PATH, il PROMPT e variabili come quelle che avevamo settato per l'utilizzo del compilatore.
Il successivo campo all'offset 2EH, lungo 34 bytes, e' anche questo destinato come area di lavoro del Dos.
All'offset 50H ritroviamo 3 bytes contenenti le istruzioni assembler
int 21H
retf
Costituisce un metodo per chiamare un int 21H senza farlo in modo diretto.
Si setta nel registro AH il numero della call che si vuole eseguire e si esegue un salto di programma a questo offset.
All'offset 55H ritroviamo 43 bytes occupati dall'area destinata al FCB.
Avevo detto precedentemente parlando del passaggio di argomenti al main() di un programma in linguaggio C che potevano essere utilizzate argc e argv per indicare rispettivamente il numero di argomenti passati e la matrice contenente la stringa con i vari argomenti.
Questi valori sono conservati all'offset 80H per quanto riguarda il numero di argomenti e al 81H (lungo 127 byte) per la stringa con i vari parametri.
Questi ultimi 128 bytes vengono anche utilizzati come area di trasferimento del disco (DTA).
Il programma lanciato processa le informazioni che sono conservate nell'area degli argomenti passati e utilizza questa come DTA.
Se si desidera conservarli e' possibile salvarli in altre zone di memoria oppure settare, mediante una delle call dell'int 21H appena viste, una differente area di trasferimento del disco.
27H - Random Block Read
Questo servizio legge uno o piu' record da una posizione casuale all'interno del file.
DS:DX puntano al FCB aperto mentre CX contiene il numero dei record da leggere.
AL restituisce l'esito dell'operazione (vedi servizio 21H) e CX il numero di blocchi effettivamente letti.
28H - Random Block Write
Mentre il servizio precedente leggeva un certo numero di blocchi questo li scrive.
DS:DX puntano a un FCB aperto e CX contiene il numero di records che
devono essere scritti.
Per i valori di ritorno restituiti in AL vedi il servizio 22H che e' simile a questo con l'unica differenza che permette di scrivere un solo record.
CX anche in questo caso conterra' il numero di record effettivamente scritti.
29H - Parse Filename
Il servizio analizza una riga di comando alla ricerca di un file espresso nella forma
d:filename.ext
e se trovato crea un FCB non aperto nella memoria puntata da ES:DI.
DS:SI puntano alla stringa di comando da analizzare.
Mediante appositi settaggi dei bit del registro AL e' possibile specificare il modo in cui deve essere analizzata la linea di comando.
I bit da 4 a 7 sono ignorati mentre quelli da 0 a 3 hanno i seguenti significati :
Bit 0 = 1 La specifica del file viene ricercata al di la' dei separatori.
Bit 1 = 1 L' identificatore del drive viene cambiato nel FCB soltanto se questo viene specificato nella linea di comando che viene analizzata.
Bit 2 = 1 Il nome del file nel FCB viene cambiato solo se nella linea di comando viene specificato un nome di file valido.
In questo modo e' possibile nei programmi specificare un nome di file di default ed eventualmente modificarlo mediante un comando
diretto.
Bit 3 = 1 L'estensione del file viene cambiata nel FCB solo senella linea di comando viene specificata.
Le informazioni necessarie sono salvate, come abbiamo visto prima, all' offset 80H del PSP (128 Bytes).
Un esempio di utilizzo in assembler e' il seguente :
;Controlla la linea di comando e setta un FCB
;all'offset 5CH nel PSP
mov ah,29H
mov si,81H
mov di,5CH
mov al,1111b ; bit value controls parsing
int 21H
Il servizio 29H restituisce i seguenti valori.
AL = 00H Non ci sono caratteri jolly all'interno della linea di comando.
01H Ci sono caratteri jolly (* o ?) nella linea.
FFH Operazione fallita.
DS:SI Puntano al primo carattere dopo il nome di file analizzato
ES:DI Puntano al primo byte del FCB.
Questa call non e' utilizzata con linee di comando che contengono
il path completo del file.
2AH - Get Date
Il servizio acquisisce la data.
In ingresso solo il registro AH conterra' il numero dell call (2AH).
In uscita si avranno i seguenti valori :
AL = Giorno della settimana (0 = Domenica, ...., 6 = Sabato)
CX = Anno (1980-2099)
DH = Mese (1 - 12)
DL = Giorno (1 - 31)
Un esempio in linguaggio C.
#include <stdio.h>
#include <dos.h>
union REGS inregs, outregs;
static char *date[] = {
"Domenica",
"Lunedi",
"Martedi",
"Mercoledi",
"Giovedi",
"Venerdi",
"Sabato"
} ;
main()
{
int var3, var4, var5, var6;
inregs.h.ah = 0x2A;
intdos ( &inregs, &outregs );
var3 = outregs.h.al;
var4 = outregs.x.cx;
var5 = outregs.h.dh;
var6 = outregs.h.dl;
printf("di %s %ld:%ld:%ld\n", date[var3], var6, var5, var4);
}
2BH = Set Date
In questo caso la funzione serve a settare la data del Dos.I registri in ingresso devono contenere :
AH = Numero call (2BH)
CX = Anno (1980 - 2099)
DH = Mese (1 - 12)
DL = Giorno (1 - 31)
AL viene utilizzato per restituire l'esito dell'operazione di settaggio e precisamente :
00H = Data settata
FFH = Data non settata.
Un altro esempio :
#include <stdio.h>
#include <dos.h>
union REGS inregs, outregs;
main()
{
int var3, var4, var5;
inregs.h.ah = 0x2B;
printf("Giorno : ");
scanf("%d", &var3);
inregs.h.dl = var3;
printf("Mese : ");
scanf("%d", &var4);
inregs.h.dh = var4;
printf("Anno 1980-2000 : ");
scanf("%d", &var5);
inregs.x.cx = var5;
intdos( &inregs, &outregs);
if( outregs.h.al == 0xFF) {
puts("\nData non valida");
exit();
}
}
2CH - Get Time
Riporta l'ora, minuti, secondi e centesimi di secondo.
I registri interessati in uscita sono :
CH = Ora (0 - 23)
CL = Minuti (0 - 59)
DH = Secondi (0 - 59)
DL = Centesimi (0 - 99)
2DH - Set Time
Setta ora, minuti, secondi e centesimi.
In questo caso i registri interessati sono uguali a quelli del servizio precedente solo che devono essere settati prima di chiamare la funzione.
2EH - Set/Reset Verify Switch
Il servizio se messo a stato attivo (ON) fa' in modo che ad ogni operazione di scrittura su disco corrisponda un controllo del CRC.
AL conterra' i valori relativi all'attivazione e alla disattivazione del servizio di verifica ovvero :
00H = Verify OFF
01H = Verify ON
2FH - Get Disk Transfer Address (DTA)
Il servizio 1AH serviva a settare l'area di trasferimento del disco.
Mediante il servizio 2FH questa viene restituita mediante ES:BX che puntano alla zona di memoria utilizzata per questo scopo.
30H - Get DOS Version Number
Il servizio 30H riporta il numero della versione Dos su cui si lavora.
Possono verificarsi dei casi in cui un nostro particolare programma faccia riferimento a delle chiamate presenti solo nelle versioni superiori a un certo numero di relase del Dos.
In questo caso e' necessario eseguire una verifica relativa al numero di questa.
Il numero di versione viene restituito suddiviso in due parti.
Il registro AL contiene la parte maggiore mentre AH quella minore.
Esempio :
Vers. 3.20
- --
+-----------+ +-----------+
: :
Parte maggiore Parte minore
Nel seguente esempio viene controllata la versione del Dos.
Se questa e' minore alla 3.00 il programma abortisce.
#include <stdio.h>
#include <dos.h>
#define FROMVERS 3
union REGS inregs,outregs;
main()
{
inregs.h.ah = 0x30;
intdos(&inregs,&outregs);
printf("Dos Version %d.%d", outregs.h.al, outregs.h.ah);
if(outregs.h.al < FROMVERS) {
puts("Versione Dos non corretta");
puts("Deve essere dalla 3.00 in poi");
abort();
}
}
31H - Terminate Process and Remain Resident
Il servizio permette ad un programma di terminare ma di rimanere allo stesso tempo residente in memoria.
Esistono altri servizi che eseguono lo stesso compito come ad esempio l' int 27H.
Vedremo questi parlando dei programmi residenti in memoria.
Il servizio 31H permette di restituire in uscita un codice testabile mediante il sottocomando dos ERRORLEVEL.
Questo numero di codice viene passato come argomento in ingresso nel servizio mediante il registro AL.
Sempre in ingresso deve essere specificato il numero di paragrafi che devono essere conservati residenti.
Il registro che conservera' questo valore e' DX.
32H - Get Disk Information
Questo servizio non e' stato documentato dalla Microsoft.
Guardando il Technical Reference si nota che il servzio viene definito come "Used Internally by DOS".
In ogni caso il servizio restituisce informazioni riguardanti il lettore specificato nel registro DL. (0 = Default, 1 = A:, ecc.)
In uscita vengono riportate le seguenti informazioni.
AL contiene 00H se il drive specificato esiste.
In caso contrario AL contiene FFH.
DS:BX puntano al blocco di informazioni del disco che contiene le notizie viste parlando dell'interrupt relativo ai floppy.
Fate attenzione ad utilizzare questa funzione in quanto il registro DS viene cambiato.
Questo significa che prima di eseguire la call e' necessario salvare il contenuto di questo registro allo scopo di ripristinarlo dopo la chiamata stessa.
33H - Ctrl-Break Check
Il servizio testa o setta lo stato del Ctrl-Break.
AL contiene il codice dell'operazione da eseguire e precisamente
00H - Restituisce lo stato
01H - Setta lo stato
Lo stato viene specificato nel registro DL
00H - OFF
01H - ON
Nel caso che venga richiesta la funzione per avere di ritorno lo stato del Ctrl-Break DL contiene in uscita
00H - Se in stato OFF
01H - Se in stato ON
34H - Find Active Byte
Ed ecco un altra funzione non documentata.
Questa assume una notevole importanza per la scrittura di programmi residenti in memoria in quanto uno dei peggiori ostacoli per la scrittura di questi ultimi e' costituita dalle funzioni non rientranti.
Tutte le call del Dos non sono rientranti.
Il "byte attivo" conta il numero delle chiamate al Dos che sono processate al momento della call.
Il registro ES restituisce il segmento del byte attivo mentre l'offset e' contenuto in BX.
Anche in questo caso bisogna prestare attenzione al fatto che la call cambia il registro ES.
35H - Get Vector
Di questa call e' gia' stato fatto uso in alcuni esempi precedenti.
Il servizio restituisce in ES:BX segmento e offset della routine di servizio di un determinato interrupt specificato in ingresso mediante il registro AL.
Nel momento in cui si modifica un vettore di interrupt mediante il servizio 25H e' conveniente salvare il vecchio indirizzo mediante questa call allo scopo di poterlo ripristinare prima della fine del nostro programma.
36H - Get Disk Free Space
Il servizio restituisce un certo numero di informazioni riguardanti il disco specificato in ingresso nel registro DL (0 = default, 1 = A:, ecc.).
I registri in uscita specificano :
BX = Cluster disponibili
DX = Numero totale di cluster
CX = Bytes per settore
AX = Restituisce FFFFH se si e' verificato un errore.
E' possibile mediante alcuni calcoli risalire alle seguenti informazioni :
CX*AX*DX = Spazio totale disco
CX*AX*BX = Spazio libero
CX*AX = Bytes per cluster
(BX*100)/DX = Percentuale libera su disco
Un esempio in linguaggio C.
#include <stdio.h>
#include <dos.h>
union REGS inregs, outregs;
long val_bx, val_dx, val_cx, val_ax;
main()
{
inregs.h.ah = 0x36;
inregs.h.dl = 0x00;
intdos(&inregs, &outregs);
val_bx = outregs.x.bx;
val_dx = outregs.x.dx;
val_cx = outregs.x.cx;
val_ax = outregs.x.ax;
printf("\n%8ld bytes per cluster",val_cx*val_ax);
printf("\n%8ld bytes totali disco",val_cx*val_ax*val_dx);
printf("\n%8ld bytes liberi", val_cx*val_ax*val_bx);
printf("\n%8d %% libero", (val_bx*100) / val_dx);
}
Indietro - Continua...
Nuova pagina 1
|
|