[1] Circa la ricorsione vedere il paragrafo dedicato.
[3] In particolare, per quanto riguarda l'InDOS flag, va osservato che quando esso non è nullo un servizio DOS è in corso di esecuzione, pertanto i TSR non devono utilizzare alcun servizio dell'int 21h, al fine di evitare la distruzione del contenuto dello stack del DOS. Controllando lo stato del flag, un TSR è in grado di determinare quando è possibile invocare funzioni DOS senza pericolo di compromettere lo stato del sistema. Tuttavia esiste una complicazione: l'interprete di comandi COMMAND.COM ed alcuni altri programmi trascorrono gran parte del tempo in attesa di input dalla tastiera mediante la funzione 0Ah (GetString) dell'int 21h: l'InDOS flag, in tale circostanza, è nonnullo. E' possibile aggirare il problema intercettando l'int 28h, chiamato in loop dai servizi 00h0Ch, oppure dotando il TSR di un gestore dell'int 21h in grado di intercettare le chiamate alla funzione 0Ah nel modo seguente:
1) | Non invocare il servizio 0Ah immediatamente; eseguire invece un loop costituito da un ritardo seguito da una chiamata al servizio 0Bh dell'int 21h (GetInputStatus). |
2) | Continuare ad eseguire il loop sino a quando non venga segnalato (dal servizio 0Bh) che un tasto è pronto nel buffer della tastiera. |
3) | Solo a questo punto eseguire la chiamata alla funzione 0Ah: per tutto il tempo in cui viene eseguito e rieseguito il loop, il TSR può utilizzare i servizi DOS liberamente. |
[4] Codice del file IBMDOS.COM (o
MSDOS.SYS). Chi desiderasse complicarsi la vita, potrebbe
ricercare una sequenza simile, invece di decrementare l'offset
dell'indirizzo dell'InDOS flag, anche nelle versioni
di DOS dalla 3.1 in poi:
test ss:[NearByte],0FFH
jne NearLabel
push ss:[NearWord]
int 28H
[5] Responsabile è la _restorezero(), routine non documentata di servizio della keep(). La _restorezero() provvede anche a ripristinare i vettori degli int 00h, 04h e 06h, per i quali valgono dunque le affermazioni riguardanti l'int 05h.
[6] Il cast è (void(interrupt *)()).
[7] Si ricordi che il compilatore Borland C++ genera le istruzioni necessarie alla gestione di BP ed SP anche nelle funzioni dichiarate void funzione(void), mentre ciò non avviene con il compilatore TURBO C 2.0. Utilizzando quest'ultimo è quindi indispensabile eliminare l'istruzione POP BP che precede la IRET. A complicare ulteriormente le cose giunge il fatto che il modello huge salva DS sullo stack in ingresso alla funzione e lo ripristina in uscita: occorre tenerne conto se si compila il TSR con detto modello di memoria.
[9] I valori da 00h a 7Fh sono riservati al DOS (PRINT usa AH = 01h, ASSIGN usa AH = 02h, SHARE usa AH = 10h); le applicazioni possono dunque utilizzare uno qualsiasi dei valori restanti (80hFFh).
[10] Inoltre, una word (anziché un byte) consente di esprimere un maggior numero di combinazioni: il gestore dell'int 2Fh potrebbe utilizzare altri registri per effettuare il controllo (ad esempio BX, o qualunque altro registro non utilizzato da altri servizi dello stesso interrupt), per diminuire la probabilità di conflitto con altre applicazioni. L'algoritmo qui descritto è, come si è detto, quello consigliato da Microsoft (e, pertanto, ufficiale), ma attualmente non esistono motivi di carattere tecnico che impediscano al programmatore di utilizzare metodi alternativi.
[11] L'ordine dei parametri formali, lo ripetiamo,
è rigido. Per il compilatore Borland esso è: BP,
DI, SI, DS, ES, DX,
CX, BX, AX, IP, CS,
FLAGS, seguiti da eventuali parametri definiti dal programmatore.
Non è necessario dichiarare tutti i parametri elencati;
è però della massima importanza che la dichiarazione
abbia inizio dal primo registro (BP)
e includa tutti i registri referenziati nel codice della funzione,
senza escludere quelli in posizione intermedia eventualmente non
utilizzati.