Fallers große Liebe: Roman

MASSIMO UBERTINI
MS-DOS
WWW.UBERTINI.IT
MODULO 1
MS-DOS
MS-DOS
Processi
TSR
Memoria
File system
I/O
Comandi
MS-DOS
um 1 di 138
MS-DOS (MICROSOFT DISK OPERATING SYSTEM)
Introduzione
MS-DOS gira solo su processori INTEL iAPx86, poiché di questi ne esistono cinquanta
milioni, senza dubbio MS-DOS è il SO più usato di tutti i tempi.
Il primo PC fu Altair 8800, prodotto nel 1975, di MITS (Micro Instrumentation and
Telemetry Systems) di Albuquerque nel New Mexico di Ed Roberts, ex ingegnere
dell’aviazione militare USA, con CPU INTEL 8080, aveva 256 KB di RAM.
Il primo micro computer della storia compare sulla copertina di Practical Electronics.
Un giovane di nome Bill Gates scrisse una versione di Basic per Altair ed ebbe un
modesto seguito tra i primi utenti di queste macchine.
Molte ditte iniziarono a costruire PC basati sul chip 8080; su di questi girava un SO
chiamato CP/M (Control Program for Microcomputer) prodotto dalla DR (Digital Research),
una piccola casa produttrice della California fondata da Gary Kildall.
CP/M-86 per CPU INTEL 8086/8088.
CP/M-8000 per CPU Z8000.
CP/M-68K per CPU Motorola 68000.
Tutti questi PC furono chiamati micro computer.
PC IBM
Intorno al 1980, l’IBM, decise che quella dei PC era un’area in cui avrebbe voluto operare;
per cui fece qualcosa d’insolito per le normali burocrazie e precauzioni interne: incaricò
uno dei suoi manager Philipe Estridge, di andare a Boca Raton, in Florida, duemila Km
lontano da sguardi indiscreti, dalla Corporate Headquarter nel Westchester Country, nello
stato di New York e gli disse di non tornare senza un PC.
Estridge decise che il solo modo per produrre velocemente un PC era usare componenti
standard, piuttosto che progettarne propri all’IBM, come aveva sempre fatto in passato.
Nel frattempo l’INTEL aveva prodotto due successori dell’8080, l’8086 e una versione con
un bus a 8 bit dell’8086, l’8088.
Estridge scelse quest’ultimo perché era composto da chip che erano più economici.
L’IBM, per il S/W, fece riferimento a Bill Gates, che nel frattempo aveva messo su una
casa di S/W chiamata Microsoft e gli chiese la licenza dell’interprete Basic da usare sul PC
IBM e chiese anche se avesse un SO per la macchina.
Gates suggerì all’IBM di usare il CP/M-86 della DR, ma, dopo aver parlato con questi
ultimi, scoprì che il CP/M-86 era ancora in fase di sviluppo e l’IBM non poteva attendere,
allora IBM tornò alla Microsoft e chiese di sviluppare un SO simile al CP/M.
Gates sapeva che non c’era il tempo necessario per prendere questo impegno, ma
sapeva anche di una casa produttrice, la Seattle Computer Products, che aveva scritto un
SO dello stesso tipo del CP/M, chiamato 86-DOS, per verificare i limiti di una memoria che
aveva in produzione e in vendita.
La Microsoft comprò 86-DOS; nell’aprile del 1981 assunse il suo autore, Tim Paterson, per
migliorarlo; cambiò il nome del SO in MS-DOS e lo vendette all’IBM.
Quando fu presentato, nell’agosto del 1981, il PC IBM era dotato del suo SO, l’MS-DOS,
la virtù principale è che vi poteva girare la maggior parte del S/W che andava sull’8080
sotto CP/M.
Se qualcuno avesse intuito che nel giro di dieci anni questo piccolo sistema, adottato
quasi casualmente, avrebbe controllato cinquanta milioni di PC, avrebbe anche pensato di
studiarlo più approfonditamente.
Comunque, né l’IBM né nessun altro ebbe la percezione di quanto grande sarebbe stato il
successo del PC IBM e, all’inizio, pensò che sarebbe stato usato per girare con i
videogiochi a casa.
MS-DOS
um 2 di 138
Per esempio, il clock a 4.77 MHz fu scelto per essere compatibile con la frequenza dei
televisori degli Stati Uniti, in modo tale che la gente potesse usare il monitor della TV
invece che uno proprio del PC.
La cosa più giusta che l’IBM fece fu di lasciare il PC come sistema aperto; infatti il
progetto completo, compresi i listati della ROM (Read Only Memory) e gli schemi dei
circuiti elettrici, erano descritti nei minimi particolari in un libro disponibile presso i
rivenditori di PC.
Questo significava che venditori S/W e H/W OEM potevano fare nuovi prodotti H/W e S/W
da aggiungere al PC e fu ciò che fecero a migliaia.
Infatti, con la disponibilità dei disegni dei circuiti e con la macchina interamente composta
da componenti disponibili in commercio, alcune ditte cominciarono a costruire e a vendere
delle copie del PC, chiamate cloni, in competizione diretta con la stessa IBM.
Questa enorme profusione di energie e creatività portò al successo del PC e con esso al
successo dell’MS-DOS.
M S-DOS non era neppure incluso nell’acquisto del PC, si pagava a parte.
Nel lancio iniziale, IBM non aveva fatto alcuno sforzo di marketing per spingere MS-DOS;
l’accento era tutto sul PC.
IBM si diede da fare a spiegare che vi erano ben tre SO disponibili per PC.
1. MS-DOS.
2. UCSD (University California San Diego) p-System, un sistema di sviluppo per
programmatori, era un S/W del tipo “scritto una volta, gira dappertutto”.
3. CP/M-86, era arrivato in ritardo sul mercato ma la stampa riteneva che fosse superiore
a MS-DOS.
MicroPro aveva trasportato su CP/M-86 Word-Star, Ashton-Tate progettò una versione per
il CP/M-86 di dBASE II.
Però DR fece uno sbaglio colossale nel fissare il prezzo del CP/M-86 a 240 dollari, il
prezzo di MS-DOS era di 40 dollari, l’enorme differenza di prezzo rese virtualmente
impossibile vendere il CP/M-86 ai clienti finali e il SO sparì quasi subito.
Versione 1.0
La prima versione dell’MS-DOS uscita nell’agosto del 1981 con il PC IBM era la versione
1.0, occupava 12 KB di RAM ed era compatibile con il CP/M.
Il codice sorgente era formato da 4000 righe di codice assembly e il solo disco che
supportava era un floppy disk da 5”1/4 da 160 KB.
Il SO era formato da tre applicazioni.
1. IBMIO.COM, il sistema d’I/O del disco e dei caratteri.
2. IBMDOS.COM, il driver del disco e dei file.
3. COMMAND.COM, l’interprete dei comandi, una shell primitiva.
A differenza di Unix, che era stato sempre completamente indipendente, MS-DOS ha
sempre fatto uso di una ROM installata sul PC IBM, chiamata BIOS (Basic Input Output
System) che contiene i driver per i dispositivi standard, per cui con una chiamata MS-DOS
può gestire l’I/O.
Laddove Unix contiene i driver per l’I/O da terminale, dai dischi, MS-DOS usava per gli
stessi scopi il BIOS.
La versione 1.0 utilizzava una sola directory, come il CP/M; al contrario persino la prima
versione di Unix era fornita di un file system gerarchico.
Aveva la capacità di gestire shell script molto semplici, chiamati batch file.
Nell’ottobre del 1982, la Microsoft distribuì la versione 1.1 di MS-DOS, che supportava
floppy disk da 320 KB.
MS-DOS
um 3 di 138
Il codice sorgente è disponibile, dal mese di marzo 2014, sul sito del Computer History
Museum, fondato nel 1996 a Mountain View in California.
Il file ZIP contiene quattro cartelle.
1. v11object: 27 file binari che costituiscono il sistema operativo.
2. v11source: 7 file in linguaggio assembly e l’email di Tim Paterson inviata a Len
Shustek, il direttore del museo.
3. v20object: 38 file binari e documentazione.
4. v20source: 118 file in linguaggio assembly e documentazione.
Versione 2.0
Nel marzo del 1983, l’IBM presentò il PC XT (eXtended Technology), il suo primo PC
fornito di un disco fisso e con la nuova versione di MS-DOS, la 2.0 che rappresentava un
taglio netto con il passato, occupava 24 KB di RAM.
La Microsoft lo riscrisse interamente integrandolo con molte idee prese da Unix.
Per esempio, il file system di MS-DOS fu basato molto su quello di Unix, con un piccolo
numero di modifiche, per esempio, l’uso di (\) al posto di (/) come componente separatore.
Erano presenti le chiamate di sistema OPEN, READ, WRITE e CLOSE nella stessa forma
di Unix, utilizzando, in pratica, il descrittore di file non presente nella versione 1.0.
Era migliorata la shell che poteva gestire la ridirezione dello standard I/O e supportava la
pipeline e i filtri, floppy da 360 KB, i driver di dispositivi installabili dall’utente, lo SPOOL
(Simultaneous Peripheral Operations On Line) di stampa, la possibilità di descrivere la
configurazione del sistema, la gestione della memoria e la shell personalizzata.
MS-DOS raggiunse la dimensione di 20000 righe di codice assembly ed eliminò
decisamente il CP/M, autodefinendosi il SO dominante per il PC.
Poiché il disco fisso offrì la possibilità di utilizzare molte applicazioni di grosse dimensioni,
il PC XT trasferì l’interesse per i PC dall’ambiente casalingo al mondo degli affari.
Piccole, medie e grandi imprese cominciarono ad acquistare i PC.
Microsoft per le applicazioni commerciali dovette produrre la versione 2.05, che teneva
conto anche dell’ora, della data, della valuta e dei simboli decimali di molte nazioni, per
esempio il codice giapponese Kanji a sedici bit.
Seguì a novembre dello stesso anno la 2.1 introdotta per il PC jr e infine mise insieme
queste due ultime versioni sotto il nome di 2.11.
Versione 3.0
Nell’agosto del 1984 l’IBM portò sul mercato il PC AT (Advanced Technology), basato
sulla CPU 80286 con 16 MB di memoria, aveva il Kernel Mode e lo User Mode, una
modalità di protezione e la capacità di eseguire più applicazioni contemporaneamente.
La versione di MS-DOS, era la 3.0, non supportava nessuna di queste caratteristiche, al
contrario girava in una modalità che simulava l’8088 ed era solo più veloce.
Poiché il PC AT poteva utilizzare il floppy da 1.2 MB, un clock a batteria tampone e
l’informazione di configurazione in CMOS (Complementary Metal Oxide Semiconductor),
fu aggiunto un supporto per questi dispositivi.
Inoltre, ora, erano supportati dischi fissi fino a 32 MB.
In più, l’interprete dei comandi, la shell, fu rimossa dal SO e realizzata in un’applicazione
separata, in modo che gli utenti la potessero sostituire con una versione personalizzata;
tutto ciò fece aumentare le dimensioni del codice fino a 40000 righe.
MS-DOS
um 4 di 138
La versione 3.0 fu sostituita dalla 3.1 nel novembre del 1984 con la novità di fornire un
supporto per le reti.
La successiva fu la 3.2 presentata a gennaio del 1986; essa supportava floppy da 3”½ e la
rete IBM Token Ring.
Nel mese di aprile 1986 l’IBM portò sul mercato il successore della linea PC, la famiglia
dei PS/2 (Personal System/2), presentata con floppy da 3”½ da 720 KB per le versioni più
piccole e da 1.44 MB per quelle più grandi.
Il PS/2 che era dotato della versione 3.3 supportava questi nuovi formati, altri formati
internazionali e anche le linee seriali che operavano a 19200 bps (bit per secondo).
Insieme con il PS/2 e la versione 3.3 di MS-DOS, l’IBM e la Microsoft distribuirono un SO
completamente nuovo, chiamato OS/2 (Operating System).
OS/2 avrebbe sostituito MS-DOS, ma ciò non accadde mai; infatti nonostante avesse molti
vantaggi, come l’utilizzo completo della memoria, l’esecuzione in modalità protetta e la
possibilità di adottare la multi programmazione, gli utenti non furono interessati al suo uso.
Nel 1991, la Microsoft comunicò che stava disinteressandosi del tutto di OS/2, il che irritò
talmente l’IBM da indurla a firmare un contratto con la Apple Computer quale fornitore del
futuro S/W, interrompendo i contatti commerciali con la Microsoft.
Versione 4.0
Constatando che il grosso successo atteso dell’OS/2 non avvenne mai, l’IBM sorprese tutti
realizzando una nuova versione di MS-DOS, la 4.0, che successivamente la Microsoft
riadattò per distribuirla ai costruttori di cloni PC.
Questo evento fece intendere all’IBM che MS-DOS non stava scomparendo, così, invece
di abbandonarlo, decise di renderlo decisamente migliore.
Uno dei grossi miglioramenti introdotti in questa versione fu la capacità di gestire dischi
fissi fino a 2 GB.
Molti utenti, specialmente i principianti, nel migliore dei casi pensano che le linee di
comando siano ermetiche e nel peggiore dei casi pensano che siano ostili, probabilmente
anche peggio di Unix, la cui shell è stata raramente ritenuta piacevole per i principianti.
Per rendere la vita più facile a queste persone, MS-DOS, a partire da questa versione,
presentò un’alternativa: l’interfaccia orientata al video chiamata DOSSHELL.
Essa elenca tutti i file e le directory in finestre e permette agli utenti di fare una notevole
quantità di lavoro puntando e selezionando semplicemente con il mouse.
Sebbene non sia un’interfaccia utente grafica ben chiara come Windows, questo è stato il
primo passo in quella direzione.
Versione 5.0
La versione 5.0 di MS-DOS fu presentata nell’aprile del 1991.
Per la prima volta era fatto un uso serio della memoria estesa di cui molti proprietari di
80286 e 80386 avevano parecchi MB.
Sebbene essa avesse la restrizione che le applicazioni non potevano eccedere i 640 KB,
almeno aveva la capacità di allocare la maggior parte dell’MS-DOS stesso sulla memoria
estesa, così circa 600 KB dei 640 KB erano disponibili per le applicazioni utente.
Inoltre, i driver dei dispositivi scritti dagli utenti potevano essere messi anche nella
memoria estesa.
Questa versione aveva anche la capacità di usare la memoria tra 640 KB e 1 MB sulle
macchine 80386 per i driver dei dispositivi e alcune applicazioni di utilità mettendo a
disposizione molto di più di 640 KB, supportava floppy da 2.88 MB.
Aveva l’applicazione DOSKEY, la history list di Unix, che poteva essere installata per
recepire e bufferizzare tutte le battute dei tasti; intercettando le interruzioni da tastiera
esaminava tutti i caratteri digitati prima che essi fossero passati al SO.
In questo modo si potevano usare scorciatoie e altri accorgimenti passando righe
precedenti di comando, con o senza editing, a COMMAND.COM come se essi
giungessero direttamente dalla tastiera; inoltre riciclando i comandi precedenti, DOSKEY,
MS-DOS
um 5 di 138
permetteva agli utenti anche di definire della macro.
In origine, MS-DOS era strettamente un sistema monotasking.
Comunque, dalla versione 5.0, era possibile far partire un comando con un doppio clic sul
nome di file e poi sospenderlo premendo CTRL+ESC.
A questo punto ricompare la finestra DOSSHELL con il nome dell’applicazione sospesa
nella finestra Lista dei processi Attivi; ora l’utente è libero di eseguire qualsiasi
comando, compreso far partire un’altra applicazione, che a sua volta può essere sospesa
allo stesso modo.
Tutte le applicazioni sospese sono elencate in questa finestra e con un doppio clic su una
di esse, l’applicazione prescelta riparte.
Sebbene non sia la stessa cosa della multi programmazione è una buona seconda scelta.
Questa versione offriva un’utility HELP di aiuto per gli utenti e molte nuove applicazioni di
utilità e nuovi comandi.
Per la prima volta, la versione 5.0 di MS-DOS fu venduta nei negozi, fino a quel momento
tutte le versioni erano state vendute dai rivenditori di PC che le consegnavano insieme alle
macchine e questo fu interpretato come un’assunzione di responsabilità da parte della
Microsoft.
Versione 6.0
La versione 6.0 di MS-DOS fu presentata nel 1993, include le seguenti caratteristiche.
Comando SETUP per l’installazione.
DOUBLESPACE, un’applicazione integrata di compressione dischi.
MEMMAKER, un’applicazione di ottimizzazione della memoria che consente di spostare in
modo semplice i driver di periferica e le applicazioni residenti in memoria dalla
convenzionale all’area di memoria superiore.
DEFRAG, un’applicazione che riorganizza i file sull’hard disk per ridurre il tempo di
accesso del PC ai file.
SCANDISK, per rilevare e correggere errori dei dischi.
SMARTDRV, comando avanzato con cache per CD-ROM.
MOVE, che sposta uno o più file da una directory o unità ad un’altra.
DELTREE, che elimina una cartella, i suoi file e tutte le cartelle e i file ad essa subordinati.
MSD (MicroSoft Diagnostics), che raccoglie e visualizza informazioni tecniche sul PC.
INTERLNK, un’applicazione che semplifica il trasferimento di file tra PC.
La Guida in linea sui comandi di tipo ipertestuale.
BACKUP per Windows, MSAV antivirus per MS-DOS e per Windows, UNDELETE per
Windows, CHOICE, DISKCOPY in una sola passata.
Occupazione 6.3 MB.
La possibilità di definire più configurazioni del sistema, particolarmente utile se si
condivide il PC con più utenti, la possibilità di avviare il sistema senza eseguire
CONFIG.SYS e AUTOEXEC.BAT: F5, di chiedere conferma per ciascun comando
caricato: F8.
Versione 7.0
Nel 1995 tecnicamente MS-DOS è del tutto obsoleto, però quando fu chiaro che l’OS/2
non avrebbe avuto seguito, la Microsoft fece una scelta diversa, sviluppando Windows
come interfaccia grafica orientata al mouse con MS-DOS.
D’altra parte, l’MS-DOS ha collezionato una grossa quantità di S/W ad alto livello.
Implementazione
MS-DOS è strutturato in tre livelli.
1. Il BIOS.
2. Il kernel.
3. La shell, COMMAND.COM.
MS-DOS
um 6 di 138
Il BIOS è un insieme di driver di dispositivo a basso livello che serve ad isolare MS-DOS
dai particolari che riguardano l’H/W.
Per esempio, il BIOS contiene le chiamate per leggere e scrivere dagli indirizzi assoluti del
disco, per leggere un carattere dalla tastiera e per scrivere un carattere sul video.
Il BIOS di solito è fornito dalle case produttrici di PC, piuttosto che dalla Microsoft e
generalmente, in parte, è posto in una ROM nel segmento appena al di sotto del limite
dello spazio degli indirizzi di 1 MB.
Le routine BIOS sono chiamate mediante TRAP per mezzo del vettore d’interruzioni
piuttosto che per mezzo di chiamate dirette di routine; ciò rende possibile al venditore di
modificare la dimensione e la posizione delle routine BIOS nei nuovi modelli, senza dover
rigenerare il SO.
Il file IO.SYS, chiamato IBMIO.COM nella versione che consegna l’IBM, è un file nascosto
presente su tutti i sistemi MS-DOS.
Esso è caricato immediatamente dopo che è stato fatto il boot del PC e fornisce
un’interfaccia di chiamate di routine a BIOS, per cui il kernel può accedere ai servizi di
BIOS eseguendo le chiamate di routine ad IO.SYS invece che generare un TRAP nella
ROM; inoltre questo file contiene le routine BIOS che non sono nella ROM e un modulo
chiamato SYSINIT che è usato per fare il boot del sistema.
È importante tenere presente che l’esistenza di IO.SYS isola ulteriormente il kernel dai
particolari dell’H/W; per esempio, il kernel non deve sapere quale vettore si sta occupando
di un certo servizio BIOS, poiché questi dettagli sono nascosti in IO.SYS.
Il kernel è contenuto in un altro file nascosto, MSDOS.SYS, che l’IBM ha denominato
IBMDOS.COM e contiene la parte indipendente dalla macchina del SO.
Esso si occupa della gestione dei processi, della memoria e del file system e anche
d’interpretare tutte le chiamate di sistema.
La terza parte è formata dalla shell, il COMMAND.COM; naturalmente questa applicazione
non appartiene al SO è può essere cambiata dall’utente.
Il COMMAND.COM standard è formato da due parti.
1. La parte residente, che è sempre in memoria.
2. La parte transiente, che è in memoria solo quando la shell è attiva.
La parte residente è posta in memoria subito dopo MSDOS.SYS e contiene gli interrupt
22H (Terminate Address), 23H (Ctrl-Break Handler) e 24H (Critical Error Handler).
Quando l’applicazione è terminata, il codice di ritorno dell’applicazione stessa è usato per
determinare se l’applicazione è sovrapposta alla parte transiente del COMMAND.COM.
Se è così la parte residente ricaricherà la parte transiente dall’area indicata da
COMSPEC=; se invece non è trovato il sistema si blocca.
I messaggi di errore si trovano nella parte residente del COMMAND.COM.
La routine d’inizializzazione è inclusa nella parte residente, assume il controllo durante lo
startup e determina l’indirizzo dove l’applicazione dell’utente sarà caricata; essa sarà poi
sovrapposta dalla prima applicazione caricata.
La parte transiente è posta nella posizione finale superiore della memoria convenzionale e
le applicazioni utente che hanno bisogno di spazio ci possono riscrivere sopra; quando il
controllo ritorna a COMMAND.COM, questi controlla se la parte transiente è intatta, in
caso contrario la ricarica.
Contiene tutti i comandi interni; produce il prompt di MS-DOS, legge i comandi dallo
standard input, keyboard o file batch e li esegue.
Per i comandi esterni costruisce una linea di comando e una funzione EXEC che carica e
trasferisce il controllo all’applicazione.
I PC con MS-DOS sono inizializzati nel modo seguente: quando sono accesi oppure dopo
un reset S/W CTRL+ALT+DEL o un reset H/W tasto di reset sul case, in questo caso
riparte l’autodiagnostica, il controllo è trasferito all’indirizzo FFFF0H nella ROM che
contiene un salto alla routine d’inizializzazione alla ROM BIOS.
Questa routine effettua alcuni test e, se la macchina li passa, prova a leggere dal floppy A:
MS-DOS
um 7 di 138
nel settore di boot.
Nel caso che non ci sia alcun floppy presente nel dispositivo A, è letto il settore principale
di boot dell’hard disk se nessuno dei due dischi è trovato, il BIOS chiama l’interrupt 19H
ROM Basic o visualizza un messaggio d’errore.
La tabella di partizione in questo settore informa sulla posizione delle partizioni e su quale
di essa è attiva, la partizione attiva è quindi selezionata e il suo primo settore, il settore
secondario di boot, è letto ed eseguito.
Questa procedura di boot a due passi è usata solo per i dischi rigidi; la sua funzione è
quella di permettere un boot automatico sia di MS-DOS sia di altri SO.
Il settore di boot legge la sua directory radice per vedere se IO.SYS e MSDOS.SYS sono
presenti, nel qual caso li legge entrambi nella memoria e trasferisce il controllo ad IO.SYS.
Una volta caricato, IO.SYS chiama la routine di BIOS per inizializzare l’H/W, dopodiché
subentra SYSINIT e legge CONFIG.SYS per configurare il sistema.
Questo lavoro comprende l’allocazione del buffer cache, il caricamento dei driver di
dispositivo e la selezione delle pagine di codice per il linguaggio nazionale da utilizzare.
Infine SYSINIT usa MS-DOS stesso per caricare ed eseguire COMMAND.COM, se la
shell si trova in una sotto directory oppure è usato un processore di comando diverso
questo deve essere specificato tramite il comando SHELL=STATEMENT in CONFIG.SYS.
Esaminando tutto ciò si nota che SYSINIT fa lo stesso lavoro di init in Unix; dopo
l’inizializzazione, il COMMAND.COM legge ed esegue AUTOEXEC.BAT, che è uno shell
script ordinario per permettere all’utente di fare ciò che ritiene più opportuno.
utilizzo
Pochi comandi di base: semplicità.
Standard: si adatta a diverse configurazioni H/W.
Somiglianza con Unix.
Vastissima disponibilità di strumenti.
Monouser, Monotasking.
Cartelle gerarchicizzate.
MS-DOS può essere paragonato all’utilizzo di una delle prime versioni di Unix.
C’è una shell, chiamata COMMAND.COM, un file system, le chiamate di sistema, le utility
e altri aspetti che sono spesso simili a Unix, ma più primitivi.
Per usare MS-DOS basta accendere il PC e poco dopo compare il prompt della shell.
Non c’è alcun login o password, si sottintende che la macchina sia usata da un solo
utente, quindi scarsa protezione.
Per la stessa ragione, i file e le cartelle non hanno proprietari né bit di protezione e inoltre
non esiste il superuser e un utente qualsiasi può fare qualsiasi cosa.
In MS-DOS sono presenti alcune caratteristiche della shell di Unix e altre no.
Per far girare un’applicazione basta digitare il nome e gli argomenti nella shell che fa una
fork di un figlio, passa gli argomenti al figlio e rimane in attesa finché il figlio non ha finito
l’esecuzione ed esce.
Non è possibile mettere un carattere (&) alla fine della linea di comando per eseguire il
comando in background, d’altra parte è permesso solo un comando per riga.
In MS-DOS i comandi sono divisi in due categorie.
1. Interni circa quaranta sono eseguiti dalla shell stessa.
2. Esterni sono veri e propri utility che di solito si trovano nella cartella DOS.
La realizzazione di molti comandi nella shell rappresenta un compromesso; da un certo
punto di vista, non dovendo estrarli da un disco lento, li rende molto più veloci e, poiché il
primo PC IBM non aveva hard disk, si può considerare senza dubbio questa ragione per
cui i comandi furono inclusi nella shell.
Da un altro punto di vista, tutto quel codice rende la shell più grande e per evitare che
questo problema potesse sfuggire dalle mani, tutti i comandi interni sono stati mantenuti
alle dimensioni minime possibili.
MS-DOS
um 8 di 138
Per esempio, non c’è alcuna possibilità di cancellare più file non correlati in una sola volta.
I metacaratteri (*) e (?) sono presenti e sottintendono tutte le stringhe e un carattere
rispettivamente, come in Unix.
Il problema è che i metacaratteri funzionano solo per i comandi interni e non per quelli
esterni ad eccezione di quelli che li gestiscono esplicitamente.
In MS-DOS, la linea di comando è trasmessa all’applicazione così come è digitata, mentre
in Unix è il risultato dell’espansione della linea di comando che è passata all’applicazione.
Il risultato di tutto ciò è che gli utenti devono ricordare quali comandi gestiscono i
metacaratteri e quali non li gestiscono; la cosa importante non è sapere chi fa l’espansione
ma che questa sia fatta in modo non consistente.
Il COMMAND.COM non fa distinzione tra maiuscole e minuscole.
MS-DOS ha le cartelle di lavoro, ma esse differiscono da quelle di Unix in un aspetto
importante: in Unix ogni processo ha la sua propria directory di lavoro.
Se un utente digita cd /usr/ast/src e poi inizia un processo, questo eredita come cartella di
lavoro /usr/ast/src, se il processo poi modifica la sua cartella di lavoro in /usr/ast/mail ed
esce, la shell avrà come cartella di lavoro ancora /usr/ast/src e il processo successivo sarà
allocato in quest’ultima.
Al contrario, in MS-DOS, la stessa sequenza di eventi lascerà il secondo processo nella
cartella MAIL poiché MS-DOS ha una sola cartella di lavoro; è tenuta traccia in una
variabile globale kernel e quando questa variabile è modificata sono influenzati tutti i
processi successivi e non solo quello corrente.
La ridirezione dello standard input e output funziona come in Unix e usa anche la
stessa notazione; per l’output il default è il video e si utilizza il simbolo (>).
Esempio.
C> dir>pippo <INVIO>
C> dir>prn <INVIO>
l’output va sul file di nome pippo
l’output va su un dispositivo periferico, la stampante
Se, invece, si utilizza il simbolo (>>) l’output è scritto dove termina il file precedente,
operazione di append.
Esempio.
C> dir>\dev\nul <INVIO>
Per l’input il default è la tastiera e si utilizza il simbolo (<), che preleva le informazioni da
un file o da un altro dispositivo periferico.
I filtri sono usati per leggere un input e trasformarlo secondo una certa funzione, il
risultato è mandato in output.
I comandi sono i seguenti.
MORE: visualizza una pagina di video alla volta.
SORT: ordinamento secondo il codice ASCII.
FIND: ricerca in un file una particolare stringa.
A>dir>record
A>sort<record
A>sort/r<record
A>sort/+9<record
A>sort/+9<record>prn
A>find “17/02/71”record
A>find/v “ESE1”record
A>find/c “1”record
A>find/n “BAT”record
MS-DOS
ordinamento crescente
ordinamento decrescente
ordinamento in colonna 9
ordinamento in colonna 9
ricerca una stringa
um 9 di 138
A>find “ditta” <clienti.txt >salva.sav
A>more<record
A>more<record>prn
Sono permesse le pipeline (canalizzazione di comandi) ma sono implementate in modo
diverso con l’utilizzo di file temporanei.
L’output di un comando è l’input del comando successivo.
C> dir ¦ sort <INVIO>
(pipe = alt 124).
Sono ammessi più comandi pipe sulla stessa linea.
C> dir ¦ sort ¦ more <INVIO>
Il prompt dall’utente è un particolare simbolo, tipico di un dato ambiente, che
contrariamente al cursore, quadratino o lineetta lampeggiante che si posiziona nel punto in
cui andrà a collocarsi il carattere successivo, si posiziona sempre all’inizio della riga per
indicare la disponibilità alla ricezione di comandi.
Per esempio, nel linguaggio Basic il prompt è rappresentato dal simbolo OK, in MS-DOS
esso è costituito dal simbolo [drive]:\>.
Nomi di file riservati
AUX
CLOCK$
COM1,2,3,4
CON
PRN
LPT1,2,3
NUL
uguale a COM1
device driver dell’orologio
1, 2, 3, 4 porta seriale
console keyboard: input, display: output
uguale a LPT1
1, 2, 3 porta parallela, la stampante
nessun dispositivo, l’output è scartato
configurazione
MS-DOS può essere configurato in vari modi, per esempio, gli utenti sono liberi d’installare
i driver d’interrupt, cosa non pensabile in Unix.
La ragione di questa disparità è chiara, Unix è un sistema timesharing, con più utenti, per
cui permettere loro d’inserire codice nel kernel, in qualsiasi momento, sarebbe un modo
pericoloso di violare la sicurezza, in altre parole un invito a distruggere il sistema.
In un sistema a utente singolo che non ha alcun tipo di sicurezza, il danno è inferiore.
Un’altra forma di configurazione da parte dell’utente è la capacità d’installare i driver di
dispositivo, questi possono gestire dispositivi non standard d’I/O, come i sintetizzatori di
musica MIDI (Musical Instrument Digital Interface) e anche dispositivi standard, come
memoria estesa, in modo non standard.
Questa caratteristica fornisce un alto grado di flessibilità.
Un tipo completamente differente di adattamento della configurazione riguarda l’area del
linguaggio della nazione in cui è usato il PC, anche le configurazioni tradizionali delle
tastiere differiscono da nazione a nazione.
Per gestire le differenti tastiere, MS-DOS ha la capacità di mappare i codici dei tasti
prodotti dalla tastiera in caratteri differenti, dipendenti, per esempio, dal fatto che il tasto a
destra del TAB sia una “Q” negli Stati Uniti o una “A” in Francia; esso ha anche diversi file
di codice di pagina CPI (Code Page File) installabili che contengono le mappe di bit per i
255 caratteri visualizzabili.
Esiste anche una chiamata di sistema per permettere ad un’applicazione di chiedere una
struttura che contiene l’informazione sui formati della data e dell’ora, sul simbolo corrente,
MS-DOS
um 10 di 138
il separatore numerico e altri oggetti che variano da nazione a nazione.
Questa informazione permette alle applicazioni di accettare l’input e di produrre un output
nella forma desiderata dall’utente, senza preoccuparsi del luogo in cui l’utente stesso vive.
La maggior parte della configurazione di MS-DOS è gestita da un file chiamato
CONFIG.SYS che è letto quando parte il sistema.
Esso può contenere i comandi per installare i driver personali di dispositivo, definire il
linguaggio nazionale, determinare dove mettere il SO in memoria, allocare memoria per il
buffer cache, specificare il numero massimo di file aperti e scegliere la shell.
I principali comandi sono: BREAK, BUFFERS, COUNTRY, DEVICEHIGH, DOS, FCBS,
FILE, INSTALL, INTERLNK, LASTDRIVE, SET, SHELL, STACKS.
I principali driver di periferica sono: ANSI.SYS. DISPLAY.SYS, DBLSPACE.SYS,
EMM386.SYS, HIMEM.SYS, RAMDRIVE.SYS, SETVER.EXE.
Inoltre, dopo che questo file è stato elaborato, è eseguito un batch file speciale chiamato
AUTOEXEC.BAT per ulteriori inizializzazioni e configurazioni.
I principali comandi sono: PROMPT, MODE, PATH, SET.
Inoltre, è utilizzato per avviare i TSR (Terminate and Stay Resident), applicazioni che sono
caricate nella memoria e vi risiedono, generalmente, fino a quando non si spegne il PC.
I TSR forniti con MS-DOS sono: DOSKEY, VSAFE, SMARTDRV.
La controparte in Unix si chiama .profile per la Bourne-Shell e .login per la C-Shell.
Un blocco di configurazione inizia con un’intestazione di blocco [...], come nei file INI di
Windows.
File CONFIG.SYS
[menu]
definisce le scelte all’avvio
menuitem = MS-DOS
definisce una voce di menu
menuitem = WORKGROUP
menuitem = NOVELL
menuitem = PATHWORKS
menucolor = 14,1
imposta il colore del testo e di sfondo
menudefault = NOVELL,10
parte dopo 10 secondi se non si fanno scelte
[common]
comandi comuni per tutte le configurazioni
DEVICEHIGH=C:\DOS\SETVER.EXE
DEVICE=C:\DOS\HIMEM.SYS
DEVICE=C:\DOS\EMM386.EXE NOEMS
BUFFERS=10,0
FILES=40
DOS=UMB
FCBS=4,0
DOS=HIGH
COUNTRY=039,850,C:\DOS\COUNTRY.SYS
STACKS=9,256
SHELL=C:\DOS\COMMAND.COM C:\DOS\ /E:2048 /p
INSTALLHIGH=C:\DOS\SHARE.EXE
[ms-dos]
[workgroup]
[novell]
comandi per la configurazione novell
INSTALLHIGH=C:\NETWARE\LSL.COM
INSTALLHIGH=C:\NETWARE\EWRK3.COM
INSTALLHIGH=C:\NETWARE\IPXODI.COM
[pathworks]
DEVICE=\TCPIP\PROTMAN.SYS /I:C:\TCPIP
DEVICE=\TCPIP\NEMM.DOS
DEVICE=\TCPIP\EWRK3.DOS
DEVICE=\TCPIP\TCPDRV.DOS /I:C:\TCPIP
MS-DOS
um 11 di 138
LASTDRIVE=Z
File AUTOEXEC.BAT
@echo off
LOADHIGH C:\DOS\SMARTDRV.EXE
LOADHIGH C:\DOS\DOSKEY.COM
LOADHIGH C:\WINDOWS\MOUSE.COM /Y
LOADHIGH C:\DOS\KEYB IT,,C:\DOS\KEYBOARD.SYS
PROMPT $p$g
PATH C:\WINDOWS;C:\;C:\DOS;C:\NETWARE;
SET TEMP=C:\DOS
GOTO %CONFIG%
variabile associata alla scelta di menu
:MS-DOS
CLS
DATE
TIME
GOTO END
:WORKGROUP
CLS
GOTO END
:NOVELLLOADHIGH C:\NETWARE\NETX.COM
F:
LOGIN STUDENTI
CLS
C:
GOTO END
:PATHWORKS
SET PATH=%PATH%;C:\TCPIP;D:PCAPP;
CALL \TCPIP\STARTNET
:END
MS-DOS
attrib
chdir (cd)
cls
comp
copy
date
del (erase)
dir
edit
fc
find
help
mkdir (md)
more
print
rename
rmdir (rd)
set
type
MS-DOS
Unix
chmod
cd, pwd
clear
cmp
copy, cp
date
rm
ls, lc, ll
vi
diff
grep
man
mkdir
more, pg
lp, lpr
mv
rmdir
$set, %env
cat
DESCRIZIONE
Visualizza o modifica gli attributi dei file.
Visualizza il nome o cambia la cartella corrente.
Pulisce lo schermo.
Confronta il contenuto di due file.
Copia uno o più file.
Visualizza o modifica la data corrente.
Elimina i file specificati.
Elenca i file e le cartelle.
Editor.
Confronta due file e ne visualizza le eventuali differenze.
Ricerca una determinata stringa di testo in un file.
Manuale on-line.
Crea una nuova cartella.
Visualizza l’output una schermata alla volta.
Stampa un file di testo.
Cambia il nome di un file.
Elimina una cartella.
Visualizza, imposta o rimuove le variabili di ambiente.
Visualizza il contenuto di un file di testo.
um 12 di 138
chiamate di sistema
Alcune delle chiamate di sistema di MS-DOS sono simili a quelle di Unix, ma altre sono
completamente diverse.
Le chiamate di sistema sono fatte mediante un TRAP al kernel, con l’utilizzo di un vettore
21H e mettendo il numero della chiamata di sistema nel registro AX, poche altre utilizzano
altri vettori.
Una libreria d’interfaccia delle chiamate di sistema è fornita dal C e da altri compilatori per
permettere ai programmatori di linguaggio ad alto livello di fare le chiamate in modo
opportuno come in Unix.
Un buon numero di applicazioni MS-DOS scrivono sul vettore 21H un puntatore nel loro
codice, che permette loro di accettare e d’ispezionare tutte le chiamate di sistema.
Alcune di queste chiamate sono gestite in maniera diversa, di solito per estendere in un
qualche modo MS-DOS; la parte rimanente consiste in un salto all’indirizzo che il vettore
21H conteneva nella prima posizione.
Sebbene sia fornita una chiamata di sistema per leggere e scrivere i vettori d’interrupt, la
tecnica non è portabile su altri sistemi o architetture e causerà problemi se MS-DOS o i
suoi successori dovessero supportare anche la multiutenza.
Di fatto è una misura di emergenza per raggiungere funzionalità o tranelli che dovrebbero
essere messi nel SO sin dall’inizio.
Per rendere possibili le reti, per esempio, spesso s’implementa ulteriore codice di rete con
con TSR che accetta tutte le chiamate di sistema e ne ispeziona ognuna per vedere se
essa richiede un accesso remoto.
Quelle che lo richiedono sono gestite dal TSR e quelle che non lo richiedono sono
restituite a MS-DOS.
Le chiamate al sistema permettono di scrivere applicazioni indipendenti dall’H/W,
machine independent e con compatibilità con versioni successive di MS-DOS.
Sollevando il programmatore da incombenze quali la costruzione di apposite routine per la
lettura da disco, la gestione del file system, le chiamate di sistema rendono
contemporaneamente la gestione del sistema più sicura, ed efficiente.
Categorie di system calls
 Standard character device I/O.
 Memory management.
 Process management.
 File and directory management.
 Microsoft Network calls.
 Miscellaneous system functions.
SEQUENZE DI ESCAPE
C> PROMPT $E[65;112P
$E[ prompt indica che i successivi caratteri costituiscono una sequenza di escape.
65 è il codice ASCII del tasto da ridefinire, in questo caso A.
(;) è l’elemento separatore tra due codici ASCII.
112 è il codice ASCII del carattere che apparirà al posto del primo, in questo caso P.
P è l’elemento che indica il termine della sequenze di escape, tra i caratteri non ci devono
essere blank e/o <INVIO>.
clrscr();
gotoxy ();
printf (“%c[2J”,27);
printf (“%c[%d;%dH”,27,x,y);
In questo modo possono essere assegnati valori e stringhe di caratteri anche a quei tasti
MS-DOS
um 13 di 138
che non hanno un proprio valore specifico, tipo i tasti funzione: INS, DEL, ALT, SHIFT,
CTRL e i tasti del tastierino numerico.
Per esempio affinché il comando DIR sia lanciato premendo il tasto F10 bisogna usare la
sequenza seguente.
C>PROMPT $E[0;68;”dir”;13P
In cui 0;68 è il codice ASCII del tasto F10, 13 il codice ASCII del tasto INVIO.
Funzioni MS-DOS: spostamento cursore, clrscr, grafica.
Per utilizzarle è necessario introdurre nel CONFIG.SYS ed eseguire il seguente comando.
device = ansi.sys.
A>prompt $E [97;109;101;108;97; P
prompt
A>a
A>prompt $E [97;97;P
prompt
Per ripristinare il prompt invece di digitarlo basta mettere a fine sequenza.
$p$g: PROMPT $E[H$p$g
Cursore in 0,0.
C>PROMPT $E[31;1;5m CIAO MONDO
PROMPT $E[37;0m$p$g
File PROVA.BAT
REM assegnazione di F1
PROMPT $E [0;59;”2”;13P
REM assegnazione di F2
PROMPT $E [0;60;”8”;13P
PROMPT $E [H$E[K$E[7M TURBOPASCAL F1$E [8C LOTUS F2$E[24;1H COMANDO :
$E[0M$E[K.
A>prompt $ E [7M$T$E[M
#include <stdio.h>
#include <conio.h>
#define GOTO(x,y)
cprintf(“%c[%d;%dH”,27, y, x)
#define HAUT
cprintf(“%c[1A”,27)
#define BAS
printf(“%c[1B”,27)
#define DROITE
printf(“%c[1C”,27)
#define GAUCHE
printf(“%c[1d”,27)
#define SAUVE
printf(“%c[s”,27)
#define RAPPELLE
printf(“%c[u”,27)
#define CLS
printf(“%c[2J”,27)
#define DLN
printf(“%c[K”,27)
#define NORM
printf(“%c[0m”,27)
#define SURB
printf(“%c[1m”,27)
#define CLIG
printf(“%c[5m”,27)
#define INVS
printf(“%c[7m”,27)
#define SOULI
printf(“%c[4m”,27)
int main(void)
{ CLS; NORM; printf(“Stampa normale,\n\n “);
SURB;printf(“un po’ di blink.\n\n”);
NORM;SOULI; cprintf(“Testo sottolineato e colorato,\n\n “);
NORM;CLIG; printf(“e intermittente.\n\n”);
MS-DOS
um 14 di 138
NORM;INVS;printf(“Video inverso ...\n”);
NORM; getch();return (0);
}
BATCH
Altre caratteristiche prese da Unix sono le variabili di shell e gli script, chiamati file batch,
in MS-DOS ma sono molto più deboli di quelli usati in Unix.
Evitano d’immettere sequenze ripetitive di comandi e offrono la possibilità di creare delle
procedure standard, in altre parole personalizzano il SO.
Hanno una struttura procedurale: CALL, ECHO, FOR, GOTO, IF, PAUSE, REM, SHIFT.
Non sono in grado di leggere i messaggi di errore su video: sono ciechi, assumono che il
comando abbia funzionato alla perfezione e usano alla cieca il successivo.
La macchina virtuale, formata da MS-DOS più l’H/W, è programmabile, ovvero è in grado
di eseguire una sequenza di operazioni.
Uno script batch è formato da un insieme di comandi del SO scritti in un file di testo.
MS-DOS riconosce un file batch mediante l’estensione BAT.
L’operatore per scrivere uno script batch deve digitare l’insieme delle istruzioni che vuole
eseguire in un file di testo scritto, ad esempio, con l’editor interno del SO.
Per eseguire un file batch è sufficiente digitare il suo nome, senza l’estensione BAT, al
prompt dei comandi; dopodiché MS-DOS inizia ad interpretare e ad eseguire un’istruzione
dopo l’altra a partire dalla prima, uno script batch è quindi un’applicazione sorgente
eseguita da MS-DOS, mediante il suo interprete dei comandi.
Questa modalità è diversa da quella relativa alle applicazioni eseguibili EXE e COM, che
sono caricate in memoria centrale dal SO e in seguito eseguite dalla CPU.
Un file eseguibile, in linguaggio macchina, è quindi un codice compilato, mentre un file
batch di testo è uno script interpretato da DOS.
La macchina DOS può quindi essere utilizzata dall’operatore in due modalità.
1. Interattiva.
2. Batch o a lotti.
Nel modo interattivo, l’operatore interagisce direttamente con la macchina, fornendo
comandi mediante l’interfaccia interprete e verificando immediatamente il risultato
ottenuto.
Questo tipo di attività è “interattiva”, perché l’uomo dialoga direttamente con il sistema.
Nella modalità batch, lo script è eseguito in modo automatico da MS-DOS senza
l’intervento dell’operatore, il quale non può in alcun modo intervenire se l’applicazione non
è terminata.
L’uso della modalità batch, letteralmente a lotti o in parti, consente di trasformare un
utente in un programmatore DOS.
Questa modalità è utile ogniqualvolta si devono programmare alcune attività ripetitive,
mediante “un lotto” di comandi, dove non è richiesto direttamente l’intervento
dell’operatore.
Script batch
È un insieme d’istruzioni scritte, una per ogni riga, in un file di testo in formato ASCII, che
la macchina DOS esegue in modo sequenziale, una dopo l’altra.
Un file batch non può avere lo stesso nome di uno eseguibile, perché, per convenzione,
MS-DOS esegue sempre i file EXE e COM prima di quelli batch.
Alcuni comandi, denominati batch, utilizzabili esclusivamente in questo tipo di script, che
realizzano le funzioni seguenti.
 L’input di alcuni parametri.
 Il controllo dell’output delle istruzioni, ECHO.
MS-DOS
um 15 di 138
 L’introduzione di commenti, REM.
 Il controllo del flusso dello script IF, GOTO, PAUSE, CALL.
Creazione dei file batch.
1. Edit.
2. COPY CON:[FILENAME].BAT <INVIO> ------------ CTRL+Z <INVIO>.
Durante l’esecuzione di uno script batch, per visualizzare messaggi sullo schermo si
utilizza il comando seguente.
ECHO messaggio
Dove messaggio è il testo che si vuole presentare.
ECHO seguito da un punto, presenta una riga vuota, iniziando a scrivere in quella
successiva.
Durante lo svolgimento dello script batch, MS-DOS visualizza sia le istruzioni, che sta
eseguendo, sia i loro risultati.
ECHO OFF
Annulla l’output sul video dei comandi eseguiti da MS-DOS.
Per annullare anche la visualizzazione dello stesso ECHO OFF si usa la sintassi.
@ECHO OFF
Per riprendere la visualizzazione dei comandi si deve fornire il comando seguente.
ECHO ON
Quando MS-DOS incontra un comando non valido non lo esegue passando all’istruzione
successiva, in questo caso l’operatore, può interrompere l’esecuzione dello script
digitando contemporaneamente CTRL+C.
In alcuni casi può essere conveniente sospendere l’esecuzione dello script, anche solo
momentaneamente, utilizzando il comando PAUSE.
L’esecuzione è ripresa quando l’operatore digita un qualsiasi tasto.
Esempio: nello script batch precedente quando si cambia l’unità attiva da C ad A, se nel
drive non è presente un floppy il SO sospende l’esecuzione del comando.
Prima di cambiare l’unità corrente si può avvertire l’operatore con un messaggio, ECHO e
sospendere momentaneamente l’esecuzione con PAUSE.
REM commento
Consente d’inserire nel file dello script un commento, quando l’interprete dei comandi
incontra REM, iniziale di REMark, ignora tutti i caratteri successivi posti sulla stessa riga.
I commenti sono utili sia per rendere leggibile uno script batch a persone diverse dagli
autori, sia per lo stesso autore quando, dopo un certo tempo, deve riprendere il file per
modificarlo.
Per fornire un input ad uno script batch, ogni applicazione specifica l’elaborazione da
eseguire sui dati d’ingresso per passare ai risultati, nel caso di script batch.
 I risultati sono gli effetti delle operazioni, quali ad esempio, la copia di un file su disco
oppure la visualizzazione sullo schermo del contenuto di una cartella con DIR.
 I dati in ingresso sono invece i parametri delle istruzioni.
Le variabili batch, o parametri sostituibili, sono nove variabili predefinite che il SO mette a
disposizione del programmatore DOS e indicate, per convenzione, con i simboli da %1
MS-DOS
um 16 di 138
fino a %9.
Ognuna delle variabili precedenti può essere utilizzata in uno script batch per contenere il
valore del parametro di un comando.
I valori delle variabili batch sono introdotti dall’operatore quando digita il nome dello script.
Esempio, lo script batch RINOMINA.BAT.
REN %1 %2
Consente di cambiare il nome di un file con la sintassi seguente.
REN nome_vecchio nome_nuovo
Digitare.
A:\>RINOMINA CAMBIAD.DAT CAMBIA_DIR.DAT
Assegna i valori CAMBIAD.DAT e CAM_DIR.DAT alle variabili batch %1 e %2.
Esegue il comando REN con i nuovi parametri.
In questo modo, l’operatore può creare delle istruzioni personalizzate.
Il numero 1 che individua una variabile batch in %1, rappresenta l’ordine con cui devono
essere introdotti i parametri dall’operatore quando digita il nome dello script batch.
L’interprete MS-DOS esegue le istruzioni in uno script batch in sequenza.
Vi sono alcuni comandi batch che consentono di alterare l’ordine sequenziale di
esecuzione, ad esempio, saltando l’esecuzione di alcune righe oppure richiamando
all’interno dello script un altro file batch.
In uno script batch, l’esecuzione può essere trasferita nei modi seguenti.
1. All’interno dello stesso script.
2. All’esterno, ad un altro file batch.
GOTO etichetta
Trasferisce, nello stesso script, l’esecuzione alla riga individuata dal parametro etichetta
preceduto da un due punti (:etichetta).
Richiamare all’interno di uno script batch un altro script.
1. Scrivere in una linea il nome dei file batch da richiamare.
2. Utilizzare il comando CALL nome_file_batch
Se si usa il comando CALL, l’interprete MS-DOS richiama il file batch esterno e, dopo
averne terminato l’esecuzione, ritorna allo script batch chiamante riprendendo
l’esecuzione dalla linea successiva che contiene CALL.
Se invece si richiama un file batch solo con il suo nome, MS-DOS lo esegue terminando
l’esecuzione dello script chiamante.
IF condizione comando
Esegue il comando, di norma GOTO, solo se la condizione è vera, TRUE, viceversa
l’interprete ignora l’istruzione.
La condizioni più frequenti sono le seguenti.
1. La verifica del valore assunto da una variabile batch, con la sintassi: IF
“%1”==“VALORE” COMANDO.
2. Verifica dell’esistenza di un file, con il formato IF EXIST NOMEFILE COMANDO che
esegue il comando solo se esiste nella directory corrente il file con il nome indicato.
Esempio, progettare un menu.
È possibile creare un menu che permette all’operatore di effettuare delle scelte e quindi
automatizzare le procedure di gestione dell’elaboratore.
MS-DOS
um 17 di 138
La gestione dei clienti di una azienda in un disco con la seguente struttura.
Può essere organizzata creando con l’editor del DOS in ogni cartella di livello inferiore dei
file con lo stesso nome ELENCO.TXT, ma contraddistinti dal loro percorso.
Ad esempio, il file ELENCO.TXT nella cartella \EUROPA\PRODOTTO.B contiene l’elenco
dei clienti europei del prodotto B.
Per la gestione del disco con i clienti, si possono creare due script batch nella cartella
radice di A.
Il primo, MENU.BAT, presenta sullo schermo il menu e consente all’operatore di effettuare
una scelta, mentre il secondo, SCELTA.BAT, apre effettivamente i file elenco con l’editor
del DOS.
File MENU.BAT
CLS
@ECHO OFF
ECHO
GESTIONE CLIENTI
ECHO Scelta dell'elenco:
ECHO.
ECHO 1. Italia:
prodotto A
ECHO 2. Italia:
prodotto B
ECHO 3. Europa:
prodotto A
ECHO 4. Europa:
prodotto B
ECHO 5. Extra Europa:
prodotto A
ECHO 6. Extra Europa:
prodotto B
ECHO 7. Fine script
PROMPT Digitare SCELTA seguito dal numero:
Il comando PROMPT cambia la riga di comando dell’interprete indicando all’operatore la
sintassi per richiamare lo script batch SCELTA.BAT.
File SCELTA.BAT
@ECHO OFF
IF %1 ==1 I:\ITALIA\PRODOTTO.A
IF %1 ==2 I:\ITALIA\PRODOTTO.B
IF %1 ==3 I:\EUROPA\PRODOTTO.A
IF %1 ==4 I:\EUROPA\PRODOTTO.B
IF %1 ==5 I:\EXTRAEUROPA\PRODOTTO.A
IF %1 ==6 I:\EXTRAEUROPA\PRODOTTO.B
REM ****** Scelta fine script batch ********************************
IF %1 ==7 GOTO FINE
REM ****** Apro l'elenco clienti
********************************
MS-DOS
um 18 di 138
REM
con l'editor di MS-DOS
EDIT ELENCO.TXT
REM ****** Prima di richiamare MENU.BAT e' necessario rendere
REM
attiva la cartella radice dove si trovano i documenti.
MENU
REM ****** Fine script batch
********************************
:FINE
PROMPT $p$g
Dopo aver aperto il file ELENCO.TXT con i clienti, lo script visualizza nuovamente il menu
richiamando il file batch MENU.BAT.
Eseguendo lo script.
I:\>MENU <INVIO>
E digitando al nuovo prompt dei comandi è richiamato il file SCELTA.BAT che apre l’editor
per il file ELENCO.TXT nel catalogo I:\ITALIA \PRODOTTO.A.
Se s’introduce SCELTA con l’opzione sette lo script termina.
File TEST1.BAT
REM collegamenti tra file batch
ECHO sono in TEST1
CALL TEST2
ECHO sono ancora in TEST1.
File TEST2.BAT
REM collegamenti tra file batch
ECHO sono in TEST2.
File MYFILE.BAT
REM è possibile parametrizzare sequenze di comandi, i parametri vanno da %0 a %9
REM vanno specificati ad ogni richiamo, il parametro %0 è il il nome del file batch
copy %1 %2
type %2
type %0.bat
c>MYFILE A:prog1 B:prog2 <INVIO>
copy A:prog1 B:prog2
type B:prog2
type MYFILE.BAT.
File 1.BAT
REM uso del comando ECHO è in on per default
ECHO OFF
MS-DOS
um 19 di 138
CLS
REM questo messaggio non è visualizzato
REM questo sì indipendentemente dal valore di ECHO
ECHO Ciao, mondo!
ECHO ON
REM ECHO e’ di nuovo in on
File 2.BAT
REM uso del comando GOTO
REM prima linea
REM seconda linea
GOTO fine
REM terza linea
: FINE
REM quarta linea
Se si aspetta un parametro dopo il nome del file batch, il controllo è il seguente.
IF %1==GOTO FINE
File 3.BAT
REM uso del comando IF
ECHO OFF
IF %1==rosa GOTO UNO
IF %1==profumo GOTO DUE
ECHO sei nei guai
GOTO FINE
: UNO
ECHO che pensiero gentile
GOTO FINE
: DUE
ECHO come sei romantico
: FINE
File 4.BAT
REM vuoi entrare in pascal (y/n)
MS-DOS
um 20 di 138
ECHO OFF
IF %1==n GOTO FINE
turbo
: FINE
File 5.BAT
:LOOP
IF %1==“ GOTO FINE
DIR C: %1
SHIFT ;slitta ai valori successivi
GOTO LOOP
:FINE ;
c>5 ws turbo basic
File ECO.BAT
ECHO %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
ECHO riferimento 1
SHIFT
ECHO %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
ECHO riferimento 2
SHIFT
ECHO %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
ECO 1 2 3 4 5 6 7 8 9 10 11
ECO 1 2 3 4 5 6 7 8 9
riferimento 1
1 2 3 4 5 6 7 8 9 10
riferimento 2
2 3 4 5 6 7 8 9 10 11
Esempio, progettare un nuovo comando, CAMBIA.BAT che cambi il nome ad un file con
un nome qualsiasi ed estensione DA (NOMEFILE.DA), modificando l’estensione in .A
(NOMEFILE.A).
SET nome1=%1.DA
SET nome2=%1.A
ECHO Cancello %nome2% ...
IF EXIST %nome2% DEL %nome2%
ECHO ... e chiamo %nome1%, %nome2%
REN %nome1% nome2%
Esempio, stampare l’elenco di tutti i file di una cartella.
ECHO OFF
cmd.exe /d /c dir %1 /o >lista.txt
ECHO ON
Esempio, eliminare i file WAV, LOG e INI dalla cartella RECENT.
ECHO OFF
for %%t in (wav log ini) do del "%userprofile%\Recent\*.%%t"
ECHO Fatto! Ripulita la cartella Recent
ECHO ON
MS-DOS
um 21 di 138
PROCESSI
Introduzione
In Unix i concetti che riguardano i processi e la memoria sono chiaramente separati e
sono indipendenti dalla macchina.
I processi possono creare processi figli usando la chiamata di sistema fork e possono
modificare la dimensione del loro segmento di dati usando la chiamata di sistema brk;
nessuno di questi dipende in alcun modo dall’architettura di base della macchina.
In MS-DOS, il modello di un processo e l’uso della sua memoria sono strettamente
connessi e notevolmente molto vincolati ai dettagli dell’architettura delle iAPx86 e del
sistema PC IBM.
Inoltre, il modello del programmatore dei processi e la memoria non sono separabili per
l’implementazione.
Per esempio, collocare un processo negli indirizzi 0400H e 0800H è diverso e il
programmatore deve stare in guardia sulle diverse proprietà di ognuno di essi.
MS-DOS non è un sistema multiprogrammato come Unix e non può supportare più
processi contemporaneamente.
Non è nemmeno un sistema a monoprogrammazione: esso sta a metà tra questi due tipi
di sistemi.
Quando s’inizializza il sistema, un processo, il COMMAND.COM parte e attende un input.
Quando è digitata una riga, il COMMAND.COM fa partire un nuovo processo mediante la
funzione 4B00H, alloca memoria, scrive un PSP (Program Segment Prefix) per la nuova
applicazione all’offset zero della memoria allocata, carica la nuova applicazione e le passa
il controllo aspettando finché non abbia finito.
Come si vede, ciò non è diverso da Unix, dove la shell normalmente attende che un
processo sia completato prima di dare il prompt.
La differenza consiste nel fatto che, in Unix, qualsiasi utente è libero di scrivere una shell
che non attende e che dà subito il prompt.
Inoltre, la shell standard non deve attendere se l’utente mette un (&) dopo il comando; ad
ogni modo, in Unix, dopo la partenza di un processo figlio, il genitore non deve attendere
poiché può continuare l’esecuzione in parallelo con il figlio.
In MS-DOS il genitore e il figlio non possono girare in parallelo; quando un processo fa
una fork di un figlio, il genitore è automaticamente sospeso finché il figlio non termina e il
genitore non può fare nulla per evitare ciò.
Vi possono essere molti processi presenti in memoria, ma solo uno di essi è attivo, i
rimanenti sono sospesi in attesa che un figlio finisca.
Per questo motivo, sebbene MS-DOS permetta a molti processi di esistere
contemporaneamente, esso non è un vero sistema a multiprogrammazione.
È possibile, in ogni caso “barare” e raggiungere un grado limitato di multiprogrammazione
manipolando direttamente le strutture dati del SO.
Questo trucco funziona solo perché MS-DOS gira su macchine che non hanno o non
usano la protezione della memoria.
MS-DOS ha due tipi di file binari, che danno origine a due tipi differenti di processi.
File con estensione COM (Core iMage) massima priorità
È un semplice file eseguibile, esso non ha intestazione e ha un solo segmento.
Il file eseguibile è un’immagine esatta byte per byte del codice eseguibile; il file è caricato
nella memoria così com’è ed è eseguito, non è rilocabile, è compatto e caricato
velocemente.
Questo tipo di modello di processo proviene dal CP/M.
MS-DOS
um 22 di 138
Un processo generato da un file COM ha un segmento di codice, più dati e più stack lungo
non più di 64 KB e COMMAND.COM gli alloca tutta la memoria disponibile e inizializza lo
stack pointer a 100H in cima al segmento da 64 KB.
Se il processo non prevede di fare una fork dei figli, esso può girare così, mentre, se ne
prevede, esso deve restituire la parte non usata di memoria al SO con una chiamata di
sistema INT 48H.
Se tralascia di liberare memoria, il tentativo di fare una fork di un figlio fallirà e quindi il
sistema si ferma, HALT e deve essere resettato.
Se un COM che non ha ancora rilasciato parte della memoria fornitagli dal sistema, ne
richiede altra, riceverà quell’occupata dalla parte residente di COMMAND.COM che dovrà
essere ricaricato a processo ultimato.
Per minimizzare questo rischio un’applicazione COM deve ridurre il blocco che il sistema
gli ha allocato inizialmente INT 4AH e rilasciare tutta la memoria allocata.
C:\> DEBUG <INVIO>
-A
0D0D:0100 MOV AH,2 <INVIO>
0D0D:0102 MOV DL ,7<INVIO>
0D0D:0104 INT 21H <INVIO>
0D0D:0106 INT 20H <INVIO>
0D0D:0108 <INVIO>
- U 100L8 <INVIO>
0D0D:0100 B402
MOV AH,02
0D0D:0102 B207
MOV DL,07
0D0D:0104 CD21
INT 21
0D0D:0106 CD20
INT 20
-R
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0D0D ES=0D0D SS=0D0D CS=0D0D IP=0100 NV UP EI PL NZ NA PO NC
0D0D:0100 B402
MOV AH,02
-T
AX=0200 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0D0D ES=0D0D SS=0D0D CS=0D0D IP=0102 NV UP EI PL NZ NA PO NC
0D0D:0102 B207
MOV DL,07
-T
AX=0200 BX=0000 CX=0000 DX=0007 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0D0D ES=0D0D SS=0D0D CS=0D0D IP=0104 NV UP EI PL NZ NA PO NC
0D0D:0104 CD21
INT 21
-P
AX=0207 BX=0000 CX=0000 DX=0007 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0D0D ES=0D0D SS=0D0D CS=0D0D IP=0106 NV UP EI PL NZ NA PO NC
0D0D:0106 CD20
INT 20
-P
Programma terminato regolarmente
- N beep.com <INVIO>
- R CX <INVIO>
CX 0000
: 8 <INVIO>
- W <INVIO>
- Q <INVIO>
C:\> DEBUG BEEP.COM 012345 <INVIO>
- R <INVIO>
AX=0000 BX=0000 CX=0008 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
MS-DOS
um 23 di 138
DS=0D7A ES=0D7A SS=0D7A CS=0D7A IP=0100 NV UP EI PL NZ NA PO NC
Sicuramente il valore esadecimale dei segmenti sul PC sarà diverso da quello di
quest’esempio, questo perché MS-DOS carica DEBUG e qualsiasi altra applicazione
eseguibile a partire dal primo segmento libero trovato in memoria.
Gli eseguibili di tipo COM presentano la caratteristica di avere i quattro registri di
segmento allineati sul primo segmento trovato libero in memoria da MS-DOS.
- D 0D7A:0000L100
0D7A:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 51 07 8A 03 . ........O.Q...
0D7A:0010 51 07 17 03 51 07 40 07-01 01 01 00 02 FF FF FF Q...Q.@.........
0D7A:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 1E 0D 4C 01 ..............L.
0D7A:0030 31 0C 14 00 18 00 7A 0D-FF FF FF FF 00 00 00 00 1.....z.........
0D7A:0040 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0D7A:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 30 31 32 .!...........012
0D7A:0060 33 34 35 20 20 20 20 20-00 00 00 00 00 20 20 20 345 .....
0D7A:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00
........
0D7A:0080 07 20 30 31 32 33 34 35-0D 4D 20 30 31 32 33 34 . 012345.M 01234
0D7A:0090 35 0D 30 0D 73 65 20 64-65 6C 20 53 6F 75 6E 64 5.0.se del Sound
0D7A:00A0 20 42 6C 61 73 74 65 72-20 6E 6F 6E 20 76 61 6C Blaster non val
0D7A:00B0 69 64 6F 2E 20 41 64 20-65 73 65 6D 70 69 6F 3A ido. Ad esempio:
0D7A:00C0 0D 69 63 61 72 65 20 75-6E 20 69 6E 64 69 72 69 .icare un indiri
0D7A:00D0 7A 7A 6F 0D 2E 30 2E 0D-00 00 00 00 00 00 00 00 zzo..0..........
0D7A:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0D7A:00F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
- Q <INVIO>
I primi 256 byte da 0000H a 00FFH, 16 paragrafi di ogni processo MS-DOS formano un
blocco speciale, il PSP e anche quest’idea è stata presa direttamente dal CP/M.
Il PSP è costruito dal SO al momento della creazione del processo.
Per i file COM, esso occupa una parte di spazio degli indirizzi del processo e può essere
indirizzato utilizzando gli indirizzi da 0 a 255; per questa ragione, tutti i processi COM
iniziano da 100H e non dall’indirizzo 0.
Il PSP contiene la dimensione dell’applicazione, un pointer al blocco di ambiente,
l’indirizzo del gestore di CTRL+C, la stringa di comando, un pointer al PSP del genitore, la
tabella dei descrittori dei file e tutta una serie d’informazioni destinate a MS-DOS, per
controllare l’applicazione in esecuzione; creato da INT 4B00H.
I tre interrupt che iniziano all’offset 0AH permettono al processo padre di eseguire il
processo figlio.
L’indirizzo del gestore di CTRL+C può essere cambiato dall’applicazione.
Quando l’utente digita CTRL+C per interrompere il processo corrente, è chiamato questo
gestore, il meccanismo è analogo a quello con cui Unix gestisce sigint.
Il buffer della coda di comando inizia all’offset 80H e può contenere al massimo 127 byte,
il primo byte riporta il numero di caratteri introdotti dopo il comando, escluso il CR
(Carriage Return) che è in ogni caso memorizzato nel buffer.
I caratteri introdotti da tastiera sono, quindi, memorizzati a partire dall’offset 81H, sono tolti
il nome dell’applicazione chiamata ed eventuali comandi di ridirezione d’I/O.
Può essere sfruttato vantaggiosamente ogni volta che un’applicazione contiene dei
parametri passati insieme al nome dell’applicazione stessa.
Il PSP è creato automaticamente dalla funzione Execute Program; Load Overlay, invece,
non costruisce il PSP in quanto l’overlay è considerato come un segmento che fa parte
dell’applicazione chiamante e che quindi non ha bisogno di una struttura PSP autonoma.
MS-DOS
um 24 di 138
OFFSET
00H
02H
04H
05H
0AH
0EH
12H
16H
2CH
2EH
50H
52H
5CH
6CH
80H
81H
-D
0D7A:0100
0D7A:0110
0D7A:0120
0D7A:0130
0D7A:0140
0D7A:0150
0D7A:0160
0D7A:0170
SIZE
2
2
1
5
4
4
4
16
2
22
2
0A
10
14
1
7F
CONTENUTI
INT 20 (CODICE OPERATIVO CDH)
SEGMENTO FINE BLOCCO ALLOCAZIONE
RISERVATO
CHIAMATA ALLA VECCHIA FUNZIONE DOS
CS:IP INT 22H (PROGRAM TERMINATE ADDRESS)
CS:IP INT 23H (CTRL-C)
CS:IP INT 24H (CRITICAL ERROR)
PARENT PROGRAM SEGMENT PREFIX
POINTER ALL’ENVIRONMENT BLOCK (SET DI MS-DOS)
RISERVATO
INT 21H
RISERVATO
FCB1
FCB2
LUNGHEZZA CODA COMANDO
CODA COMANDO
B4 02 B2 07 CD 21 CD 20-6F 6E 74 72 6F 6C 6C 6F .....!. ONTROLLO
20 64 69 20 43 54 52 4C-2B 43 20 73 75 70 70 6C DI CTRL+C SUPPL
65 6D 65 6E 74 61 72 65-2E 0D 0A 0D 0A 42 52 45 EMENTARE.....BRE
41 4B 20 5B 4F 4E 20 7C-20 4F 46 46 5D 0D 0A 0D AK [ON | OFF]...
0A 44 69 67 69 74 61 74-6F 20 73 65 6E 7A 61 20 .DIGITATO SENZA
70 61 72 61 6D 65 74 72-69 2C 20 42 52 45 41 4B PARAMETRI, BREAK
20 76 69 73 75 61 6C 69-7A 7A 61 20 6C 27 69 6D VISUALIZZA L’IM
70 6F 73 74 61 7A 69 6F-6E 65 20 63 6F 72 72 65 POSTAZIONE CORRE
Ci sono prima i dati, in questo esempio non ci sono dati, poi il codice macchina
dell’applicazione, la corrispondenza dei byte che rappresentano istruzioni in linguaggio
macchina corrispondono al disassemblato, comando U.
EB (Environment Block)
Contiene una copia dedicata all’applicazione dell’ambiente DOS.
Precede sempre l’applicazione, non possiede dimensione fissa, ma è fissata al momento
del caricamento; contiene tutte le variabili della shell nella forma VARIABILE = VALORE.
Si visualizza/memorizza con SET, ogni entry dell’ambiente è una stringa ASCII chiusa da
un byte uguale a 0: questo formato è chiamato ASCIIZ e termina con il carattere ASCII 0.
Rispetto all’ambiente, MS-DOS si comporta come Unix, tranne per il fatto che in Unix il
puntatore d’ambiente non è posto ad un indirizzo prefissato, ma è un parametro del main.
Al termine dell’insieme delle variabili di ambiente, iniziano i processi di ambiente caricati
con COMMAND.COM o in risposta ad EXEC.
COMSPEC=C:\COMMAND.COM0
PROMPT=$p$g0
0
0001 C:\PROVA\PROVA.EXE0
Esempio di variabili di ambiente in un PC.
CONFIG=DOS
COMSPEC=C:\DOS\COMMAND.COM
BLASTER=A220 I5 D1 T4
SOUND=C:\SBPRO
MS-DOS
um 25 di 138
PROMPT=$P$G
PATH=C:\;C:\DOS;C:\WINDOWS;C:\UT;C:\SBPRO\PLAYCD;C:\TP\BIN;C:\BORLANDC\B
IN;C:\LLHOME
TEMP=C:\WINDOWS\TEMP
TMP=C:\WINDOWS\TEMP
LLHOME=C:\LLHOME
DOSSEG
.MODEL TINY
.CODE
ORG 100H
BEGIN:
MOV AH,2
MOV DL,7
INT 21H
MOV AX,4C00H
INT 21H
END BEGIN
.ASM = 164 byte
.OBJ = 194 byte
.COM = 10 byte
CODE
SEGMENT
ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE
ORG 100H
BEGIN:
MOV AH,2
MOV DL,7
INT 21H
MOV AX,4C00H
INT 21H
CODE ENDS
END BEGIN
.ASM = 195 byte
.OBJ = 137 byte
.COM = 10 byte
SP = FFFE
STACK
64 KB
0110 inizia lo stack perchè non ci sono dati
CODE
PSP
CODE
CODE
DATA
DATA
STACKSEG
MS-DOS
IP = 0100
CS, DS, ES, SS = 0AB7
SEGMENT
ENDS
SEGMENT
ENDS
SEGMENT
um 26 di 138
STACKSEG ENDS
GRP
GROUP STACKSEG, DATA, CODE
CODE
SEGMENT
ASSUME CS:GRP, ES:GRP, DS:GRP, SS:GRP
ORG 100H
BEGIN:
MOV AH,2
MOV DL,7
INT 21H
MOV AX,4C00H
INT 21H
CODE
ENDS
END BEGIN
Due o più segmenti in un’unità logica per essere indirizzata da un solo segmento.
.ASM = 324 byte
.OBJ = 217 byte
.COM = 76 byte
File con estensione EXE (EXEcutable)
Un processo creato da uno di questi file può avere un segmento di codice, uno di dati, uno
di stack e molti segmenti extra così come ritiene necessario.
A differenza dei file COM, i file EXE contengono informazioni di rilocazione, in modo che
possono essere rilocati al volo quando sono caricati.
Il SO riconosce la differenza tra i file guardando i primi due byte e non guardando
l’estensione del nome di file.
I file EXE sono rilocati prima del PSP, così l’indirizzo 0 è il primo byte prima del PSP e
questa strategia evita di perdere 256 byte dello spazio degli indirizzi.
DOSSEG
.MODEL SMALL
STACK 200H
.DATA
.CODE
BEGIN:
MOV AX,@DATA
MOV DS,AX
MOV AH,2
MOV DL,7
INT 21H
MOV AX,4C00H
INT 21H
END BEGIN
.ASM = 217 byte
.OBJ = 404 byte
.EXE = 256 (PSP) + 31 (CODE) + 256 (RILOCAZIONE) = 543 byte
Gli eseguibili EXE presentano la caratteristica di mantenere separate, anche fisicamente,
le tre aree logiche di CODE, DATA e STACK dell’applicazione per sfruttare pienamente le
capacità di gestione segmentata della memoria.
C:\> DEBUG BEEP.EXE <INVIO>
MS-DOS
um 27 di 138
- R < INVIO >
DS = ES = 0AB7 CS = 0AC7 SS = 0AC9 IP=0010 salta i primi 16 byte
AX = BX = DX = BP = SI = DI = 0000
CX = 001F (31D) SP=0200
- Q < INVIO >
0AB7:0000 = DS, ES:0000
0AB7:0000 = DS, ES:00FF
(PSP, in DS non ci sono dati)
0AB7:0100 = CS:0000
(0AB70 + 0100 = 0AC70)
0AB7:0110 = CS:001F
(perchè CX = 1F)
0AB7:0120 = SS:0000
(0AB70 + 0120 = 0AC90)
0AB7:0320 = SS:0200
SP = 0200
STACK
SS = 0AC9
CODE
IP = 0010
.................................. CS = 0AC7
.....
DS, ES = 0AB7
PSP
STACKSEG SEGMENT STACK ‘STACK’
DB 200 DUP (?)
STACKSEG ENDS
DATA
SEGMENT
DATA
ENDS
CODE
SEGMENT
ASSUME CS:CODE, DS:CODE, ES:CODE, SS:STACKSEG
BEGIN:
MOV AX,DATA
MOV DS,AX
MOV AH,2
MOV DL,7
INT 21H
MOV AX,4C00H
INT 21H
CODE ENDS
END BEGIN
.ASM = 312 byte
.OBJ = 198 byte
.EXE = 256 (PSP) + 527 (CODE) + 256 (RILOCAZIONE) = 1039 byte
c:\> debug beep.exe <INVIO>
- R <INVIO>
DS = ES = 0AB7 CS = 0AE7 SS = 0AC7 IP=0000
AX = BX = DX = BP = SI = DI = 0000
CX = 020F (527D) SP=0200
- Q <INVIO>
0AB7:0000 = DS, ES:0000
0AB7:0000 = DS, ES:00FF
(PSP, in DS non ci sono dati)
0AB7:0100 = SS:0000
(0AB70 + 0100 = 0AC70)
MS-DOS
um 28 di 138
0AB7:02F0 = SS:0200
0AB7:0300 = CS:0000
0AB7:050F = CS:020F
(0AB70 + 0300 = 0AE70)
CODE
IP = 0000
CS = 0AE7
SP = 0200
STACK
PSP
SS = 0AC7
DS, ES = 0AB7
Quando un’applicazione è caricata sono richieste informazioni per il calcolo della memoria
necessaria e l’assegnazione dei valori iniziali ai diversi registri.
Queste informazioni si trovano nella struttura file header, che è costruita dal linker ed è
collocata all’inizio dei file di tipo EXE.
In fase di caricamento il sistema prova ad allocare la memoria indicata da MAXALLOC, se
questo non è possibile, cerca allora di assegnare tutta la memoria disponibile, purché
questa abbia almeno le dimensioni indicate in MINALLOC, se anche questo tentativo non
ha successo, il caricamento è interrotto.
Per questo motivo MAXALLOC riceve spesso il valore FFFFH, in modo da assicurare che
il SO allochi al processo tutta la memoria disponibile.
Al file header fa seguito una tabella di rilocazione, relocation table, per il calcolo degli
indirizzi assoluti in funzione del punto di caricamento e infine il codice compilato
dell’applicazione vera e propria.
Dato che è pronto per il caricamento, un file di tipo EXE è chiamato anche modulo di
caricamento, load module.
OFFSET
00H
02H
04H
06H
08H
0AH
0CH
0EH
10H
12H
14H
16H
18H
1AH
1CH
variabile
variabile
variabile
CONTENUTI
Identificatore del tipo di file 4DH, 5AH, <M,Z>, Mark Zbikowski
“Piccolo, ma onnipresente monumento posto a ricordo di se stesso”.
Numero di byte contenuti nell’ultima pagina, lunghezza file modulo 512.
Lunghezza del file in pagine di 512 byte, header compreso.
Numero dei riferimenti presenti nella tabella di rilocazione.
Lunghezza file header in paragrafi da 16 byte.
Numero minimo di paragrafi necessari al programma: MINALLOC.
Numero massimo di paragrafi richiesti dal programma: MAXALLOC.
Valore iniziale di SS (Stack Segment) da rilocare.
Valore iniziale di SP (Stack Pointer).
Somma di controllo sulle word del file: CRC (Cyclic Redundancy Check).
Valore iniziale di IP (Instruction Pointer).
Valore iniziale di CS (Code Segment) da rilocare.
Offset del primo elemento della tabella di rilocazione.
Numero di overlay, è uguale a zero per la parte residente del programma.
Riservato.
Tabella di rilocazione.
Riservato.
Programma e dati.
In MS-DOS un processo qualsiasi può essere caricato direttamente passando il suo nome
all’interprete di comandi oppure all’interno di un altro processo in esecuzione.
MS-DOS
um 29 di 138
La tabella di rilocazione è formata da un numero variabile di oggetti da rilocare, ognuno
dei quali è formato da due campi: un offset, 2 byte e un numero di segmento, riferiti a una
word che richiede modifica prima che il controllo sia passato al modulo caricato.
1. La parte formattata dello header è trasferita in memoria, 1BH byte.
2. Una porzione di memoria allocata in rapporto alla dimensione del modulo di
caricamento e di MINALLOC e MAXALLOC, MS-DOS tenta di allocare FFFFH
paragrafi per ottenere la dimensione del massimo blocco disponibile; se essa è minore
di MINALLOC e MAXALLOC, sarà segnalato un errore; se il blocco è maggiore di
MAXALLOC, MS-DOS allocherà un blocco pari a (MAXALLOC + dimensione del
blocco da caricare), altrimenti il sistema allocherà il blocco libero più grosso.
3. Il PSP costruito nella parte inferiore della memoria allocata.
4. La dimensione del load module valutata in base alle informazioni contenute nei campi
04H-05H, 08H-09h e 02H-03H dello header; il loader localizza in memoria il segmento
appropriato dove caricare il load module, start segment.
5. Il load module è trasferito in memoria a partire dallo start segment.
6. La tabella di rilocazione è trasferita in un’area di lavoro in RAM.
7. Per ogni elemento della tabella di rilocazione, si aggiunge il valore dello start segment
al campo segmento; il valore calcolato, più il contenuto del campo offset, un puntatore
a una word nel load module alla quale aggiungere il valore dello start segment; il nuovo
valore della word è infine riscritto nell’immagine in memoria del load module, questo
procedimento è la rilocazione.
8. I registri SS e SP sono inizializzati come indicato nei campi 0EH-0FH e 10H-11H; il
loader incrementa poi SS del valore dello start segment; i registri ES (Extra Segment) e
DS (Data Segment) sono inizializzati con l’indirizzo di segmento del PSP; infine il
valore dello start segment aggiunto al valore iniziale per CS indicato nello header; il
risultato, insieme al valore iniziale per IP, campo 14H-15H, il punto iniziale CS:IP al
quale trasferire il controllo per iniziare l’esecuzione dell’applicazione.
Un file EXE è convertito in COM con il comando seguente EXE2BIN.
Un figlio, in MS-DOS, di solito eredita i file aperti dal genitore e le loro posizioni, a meno
che i file non siano aperti con una modalità speciale per inibire che siano ereditati.
Se un figlio legge o scrive un file aperto, quando esce, il genitore vede la nuova posizione
del file e può passarla al figlio successivo.
Qualsiasi file aperto dal figlio è automaticamente chiuso quando esce e la memoria è
liberata.
Un figlio può anche restituire uno stato di uscita al suo genitore; tutte queste caratteristiche
sono esattamente le stesse di Unix.
A differenza di Unix, MS-DOS non supporta alcun tipo di paginazione o swapping.
Quando un processo fa una fork di un figlio, vi è pericolo che non ci sia sufficiente
memoria per il figlio e per i suoi discendenti.
Per ridurre la probabilità che ciò accada, molti processi che possono avere figli sono
costruiti in due parti.
Nella prima figura si vede il sistema subito dopo l’inizializzazione e dopo che è partito il
COMMAND.COM; nella successiva si vede la stessa dopo che è stato fatto partire l’EDIT.
Si supponga che l’editor permetta all’utente di tornare al COMMAND.COM senza perdere
il contesto di EDIT.
In Unix, l’editor creerà una shell con una fork e lascerà che il sistema lo scarichi; questa
soluzione in MS-DOS è impossibile.
L’editor probabilmente sarà costituito da una piccola applicazione di avvio (stub) e
dall’editor stesso.
Prima di fare una fork di COMMAND.COM, l’editor può copiare la sua immagine di
memoria su un file su disco e ridurre la sua allocazione di memoria in modo che contenga
solo lo stub e poi fare la fork, ottenendo così la terza situazione in figura.
Se l’utente decide di formattare un floppy si ottiene la situazione indicata nell’ultima figura.
Quando l’applicazione di formattazione termina, si torna alla situazione immediatamente
MS-DOS
um 30 di 138
precedente.
Quando l’utente digita EXIT per uscire da COMMAND.COM, lo stub dell’editor prende di
nuovo il controllo e legge la parte rimanente del suo processo affinché possa continuare
da dove era stato interrotto.
Di solito quando un processo esce, la sua memoria è recuperata e il processo scompare
definitivamente.
MS-DOS ha anche una modalità alternativa per cui un processo che esce dà istruzioni al
SO di non riprendere la memoria che ha usato, ma di trattarlo in modo diverso.
Questa caratteristica ha generato una piccola industria: costruzione e vendita del S/W
TSR.
CARICAMENTO DI UN OVERLAY
Quando un’applicazione richiede il caricamento di un overlay, deve indicare a MS-DOS
l’indirizzo del segmento nel quale l’overlay dovrà essere trasferito.
L’applicazione chiamante potrà poi richiamare l’overlay, che restituirà infine il controllo
all’applicazione chiamante stessa.
MS-DOS non controlla se l’applicazione chiamante possiede la memoria dove l’overlay è
caricato, perciò è possibile che un uso incauto di INT 4B03H distrugga un blocco di
controllo della memoria causando uno stato di inconsistenza della struttura logica della
RAM e un possibile errore di allocazione.
Perciò un’applicazione che carica un overlay deve adattare la sua capacità di memoria alla
dimensione dell’overlay stesso.
chiamate di sistema
A differenza di Unix, MS-DOS non fa alcuna distinzione tra le chiamate di sistema fork ed
exec; le funzioni di entrambi sono combinate nella chiamata LOAD_AND_EXECUTE.
In Unix la ragione per cui esse sono divise è quella di permettere di manipolare i descrittori
di file dopo la fork, ma prima della exec.
In MS-DOS, la shell prima salva i suoi descrittori di file, poi sistema quelli del figlio e quindi
lo esegue.
Quando il figlio termina, la shell memorizza nuovamente i descrittori del file.
Il primo parametro denomina il file binario e il secondo è un puntatore ad una struttura che
contiene i puntatori alla linea di comando e all’ambiente.
La chiamata LOAD_OVERLAY è simile alla precedente, eccetto che l’overlay non è fatto
partire; esso è solo caricato in memoria e dipende dal genitore decidere se chiamare
qualche procedura nell’overlay con una chiamata di procedura ordinaria.
La chiamata END_PROCESS equivale alla chiamata exit di Unix, ma KEEP_PROCESS
esiste solo in MS-DOS; quindi, quando un’applicazione termina, non distrugge la sua
immagine di memoria e resta residente.
MS-DOS
um 31 di 138
Perché non vi sia una chiamata di sistema WAIT, il genitore ha bisogno di un altro modo
per sapere il valore dello stato restituito dal figlio; a ciò si ovvia con una chiamata di
sistema GET_RETURN_CODE_OF_CHILD_PROCESS, che restituisce lo stato del figlio
che è stato eseguito per ultimo.
FUNZIONE 4BH
Categoria
Gestione processi.
1) load and execute
Descrizione
L’applicazione è caricata e passata direttamente in run.
Input
AX = 4B00H DS:DX = punta al file da caricare come processo.
ES:BX = punta ad un record contenete i parametri della funzione.
2) load overlay
Descrizione
L’applicazione è caricata come overlay, ma non è eseguita.
Input
AX = 4B03H DS:DX = punta al file da caricare come processo.
ES:BX = punta ad un record contenete i parametri della funzione.
In entrambi i casi il modulo di sistema provvede al rilocamento del codice rispetto all’inizio
dell’area di caricamento, calcolando i nuovi indirizzi e riferimenti.
31H Keep process
4CH End process
4DH Get return code of child process
62H Get PSP
implementazione
La gestione dei processi in MS-DOS è semplice perché non c’è multiprogrammazione.
Quando un processo attiva una chiamata di sistema LOAD_AND_EXECUTE, MS-DOS
esegue i seguenti passi.
1. Trova un blocco di memoria sufficientemente grande per contenere un processo figlio;
per un file EXE, la dimensione si può dedurre dall’informazione nell’intestazione; per
uno COM è allocata tutta la memoria disponibile, ma l’applicazione può restituire la
memoria non usata nel caso ciò sia richiesto.
2. Inserisce il PSP nei primi 256 byte di memoria allocata; alcune delle informazioni sono
dal PSP del genitore e altre informazioni, come la linea di comando, sono uniche per
questo processo; un puntatore che ritorna al PSP del genitore del processo è
compreso nel PSP del figlio, in un certo senso il PSP è analogo alla struttura utente in
Unix.
3. Carica il file binario eseguibile nella memoria allocata iniziando dal primo byte al di
sopra del PSP; per i file EXE si deve aggiungere una costante di rilocazione a tutti gli
indirizzi rilocabili; per i COM non cambia nulla.
4. Fa partire l’applicazione, l’indirizzo di partenza di un EXE è contenuto nell’intestazione;
quello di un file COM è l’indirizzo 0100H per saltare oltre il PSP.
I PSP hanno un ruolo importante in MS-DOS.
Una variabile globale nel sistema punta al PSP del processo corrente.
Il PSP contiene tutte le informazioni di stato necessarie per eseguire il processo; poiché il
PSP contiene il puntatore di ritorno al PSP del genitore, dato il puntatore a quello corrente,
MS-DOS può eseguire la catena all’indietro fino al COMMAND.COM e localizzare tutti i
processi, sospesi, nel sistema.
Il PSP contiene anche l’indirizzo a cui ritornare dopo l’uscita.
Il puntatore che MS-DOS mantiene al PSP del processo corrente ha un ruolo importante
anche nella programmazione TSR.
Le chiamate di sistema non documentate servono per leggere e scrivere questo puntatore,
permettendo ad un programmatore TSR di salvare il puntatore del PSP corrente e
d’installare il suo.
Fatto ciò, il TSR può chiamare MS-DOS per fare l’I/O al suo posto.
MS-DOS
um 32 di 138
Questo trucco funziona solo se accade che l’applicazione utente, piuttosto che il SO, è
attivo al momento in cui prende il controllo il TSR.
Ad ogni modo è disponibile un’altra chiamata di sistema per scoprire quale era attivo,
permettendo al TSR di posticipare il suo lavoro finché la chiamata di sistema corrente, se
ne esiste una, è terminata.
In alternativa, il TSR può localizzare il puntatore al segmento dei dati interni di MS-DOS e
sviarlo su un altro, facendo in modo che il sistema “dimentichi” momentaneamente ciò che
stava facendo.
Utilizzare chiamate di sistema di questo genere è una pratica pericolosa e poco pulita,
anche se virtualmente tutti i TSR funzionano in questo modo.
La schedulazione della CPU è banale poiché c’è un solo processo attivo che è eseguito
continuamente, tranne quando un TSR prende il controllo.
File RUN.ASM
Mostra come sia possibile caricare un processo da parte di un altro già in esecuzione per
mezzo della funzione LOAD_OVERLAY, accetta come parametro il nome di
un’applicazione, alloca uno spazio di memoria sufficiente a contenerla, costruisce un PSP,
carica il processo come overlay e infine gli passa il controllo dell’esecuzione.
La memoria da allocare al nuovo processo è calcolata addizionando la dimensione del
modulo di caricamento, la dimensione minima di memoria stimata necessaria indicata in
MINALLOC, la dimensione dello stack e infine 10H paragrafi (256 byte) per il PSP del
nuovo processo.
Dato che molti dei parametri presenti nel PSP non sono strettamente necessari
all’esecuzione e altri devono coincidere con quelli originali del processo chiamante, il
nuovo PSP è costruito per semplicità copiando quello già esistente.
Una volta dato inizio alla nuova applicazione, RUN non ottiene più il controllo
dell’esecuzione.
;caricamento di un processo come overlay e sua esecuzione
stackseg segment para stack ‘stack’
db 200h dup (?)
stackseg ends
end_process macro
mov al,1
mov ah,4ch
int 21h
endm
data segment word ‘data’
file_name db 20h dup (0)
file_header db 1ch dup (0)
;buffer per il file header
par_block db 04h dup (0)
;parametri programma
local_psp dw 0
file_handle dw 0
;handle per il file in ingresso
req_mem dw 0
;memoria richiesta
area_ptr dw 0
;indica l’inizio dell’area assegnata al nuovo processo
load_ptr dw 0
;indica il punto di caricamento di overlay 10 paragrafi oltre;l’inizio dell’area ssegnata
new_ss dw 0
;stack segment nuovo file
new_sp dw 0
new_cs dw 0
;code segment nuovo file
new_ip dw 0
;prima istruzione nel nuovo processo
data ends
cseg segment word ‘cseg’
assume cs:cseg,ds:data,ss:stackseg
MS-DOS
um 33 di 138
begin: mov ax,ds
mov bx,data
mov ds,bx
mov local_psp,ax
reduce_memory:
mov bx,100h
mov ah,4ah
int 21h
jnc get_file_name
end_process
get_file_name:
cld
mov di,offset file_name
mov ax,data
mov es,ax
mov ax,local_psp
mov ds,ax
mov si,80h
lodsb
xor ah,ah
mov cx,ax
loop_1:
lodsb
cmp al,32
ja copy_inp_string
dec cx
jmp loop_1
copy_inp_string:
stosb
dec cx
rep movsb
open_file_handle:
mov ax,data
mov ds,ax
mov dx,offset file_name
mov ah,3dh
mov al,0h
int 21h
jnc read_from_file
end_process
read_from_file:
mov file_handle,ax
mov bx,ax
mov dx,offset file_header
mov cx,28
mov ah,3fh
int 21h
jnc close_file_handle
end_process
close_file_handle:
mov bx,file_handle
mov ah,3eh
int 21h
jnc request_memory
MS-DOS
;il psp è contenuto in ds
;es punta al psp di run
;riduzione con set_block della memoria allocata
;256 paragrafi = 4kbyte es punta al psp di run
;esce se tutto ok cf = 0
;lettura filename via linea comando
;si e di vanno incrementati
;es:di punta a file_name
;ds = local_psp via ax
;ds:di punta alla stringa di comando
;lunghezza della stringa in al
;cx = numero di byte da leggere
;eliminazione blank dalla stringa d’ingresso
;controllo primo char valido
;ascii > 32 (spazio)
;byte da leggere -1
;legge char successivo
;lettura stringa d’ingresso
;es:di punta già a file_name
;copia byte successivi, numero in cx
;apertura del file in lettura
;ds:dx punta a file_name
;risultato chiamata da ax
;handle per il file
;ds:dx punta a file_header
;numero byte da leggere
;uscita se ok cf = 0
;uscita se ok cf = 0
um 34 di 138
end_process
request_memory:
;calcolo memoria da allocare al nuovo processo
mov ax,word ptr file_header[4]
mov cx,32
;conversione paragrafi
mul cx
;ax * 32
add ax,word ptr file_header[0ah] ;memoria minima da allocare
add ax,word ptr file_header[10h] ;spazio richiesto dallo stack
add ax,10h
;10 paragrafi = area psp del processo
mov req_mem,ax
;memoria richiesta in paragrafi
mov bx,ax
;memoria richiesta in bx
mov ah,48h
;funzione dos allocate_memory
int 21h
jnc make_new_psp
;uscita se ok cf = 0
end_process
make_new_psp:
mov area_ptr,ax
;ax pointer all’area libera
add ax,10h
;spazio richiesto da psp
mov load_ptr,ax
;segmento di caricamento di overlay
mov es,area_ptr
;il psp del processo padre è copiato nel figlio
mov di,0
mov ds,local_psp
mov cx,100h
rep movsb
;copiatura
mov ax,data
mov ds,ax
load_new_program:
;caricamento overlay
mov bx,load_ptr
;costruzione parameter block
mov word ptr par_block[0],bx
mov word ptr par_block[2],bx
mov ax,data
mov es,ax
mov bx,offset par_block
;es:bx punta a parameter block
mov dx,offset file_name
;ds:dx punta a file_name
mov ah,4bh
mov al,03h
int 21h
jnc new_registers
;uscita se ok cf = 0
end_process
new_registers:
;calcolo i registri per il nuovo processo
mov ax,word ptr file_header[0eh]
add ax,load_ptr
;ss iniziale è rilocato rispetto a inizio area caricamento
mov new_ss,ax
mov ax,word ptr file_header[10h]
mov new_sp,ax
;sp iniziale non è rilocato
mov ax,word ptr file_header[16h]
add ax,load_ptr
;cs iniziale è rilocato rispetto a inizio area caricamento
mov new_cs,ax
mov ax,word ptr file_header[14h]
mov new_ip,ax
;ip iniziale non è rilocato
mov bx,new_cs
;caricamento registri per esecuzione nuovo processo
mov cx,new_ip
cli
mov ax,new_ss
;passaggio al nuovo stack
mov ss,ax
MS-DOS
um 35 di 138
mov ax,new_sp
mov sp,ax
mov ax,area_ptr
mov ds,ax
mov es,ax
pushf
push bx
push cx
iret
cseg ends
end begin
;ds es puntano al psp del nuovo processo
;new_cs nuovo segmento codice
;new_ip nuovo pointer all’istruzione
;passaggio al nuovo processo
File PARENT.ASM
Usa l’EXEC per caricare ed eseguire un child process di nome CHILD.EXE.
stdin equ 0
; standard input
stdout equ 1
; standard output
stderr equ 2
; standard error
stksize equ 128
; size of stack
cr
equ 0dh
; ASCII carriage return
lf
equ 0ah
; ASCII linefeed
DGROUP group _DATA,_ENVIR,_STACK
_TEXT segment byte public ‘CODE’
; executable code segment
assume cs:_TEXT,ds:_DATA,ss:_STACK
stk_seg dw
?
; original SS contents
stk_ptr dw
?
; original SP contents
main proc far
; entry point from MS-DOS
mov ax,_DATA
; set DS = our data segment
mov ds,ax
;now give back extra memory; so child has somewhere to run...
mov ax,es
; let AX = segment of PSP base
mov bx,ss
; and BX = segment of stack base
sub bx,ax
; reserve seg stack - seg psp
add bx,stksize/16
; plus paragraphs of stack
mov ah,4ah
; fxn 4AH = modify memory block
int 21h
jc
main1
; display parent message ...
mov dx,offset DGROUP:msg1
; DS:DX = address of message
mov cx,msg1_len
; CX = length of message
call pmsg
push ds
; save parent’s data segment
mov stk_seg,ss
; save parent’s stack pointer
mov stk_ptr,sp
; now EXEC the child process
mov ax,ds
; set ES = DS
mov es,ax
mov dx,offset DGROUP:cname ; DS:DX = child pathname
mov bx,offset DGROUP:pars ; EX:BX = parameter block
mov ax,4b00h
; function 4BH subfunction 00H
int 21h
; transfer to MS-DOS
cli
; (for bug in some early 8088s)
mov ss,stk_seg
; restore parent’s stack pointer
mov sp,stk_ptr
sti
; (for bug in some early 8088s)
pop ds
; restore DS = our data segment
jc
main2
; jump if EXEC failed otherwise EXEC succeeded,
MS-DOS
um 36 di 138
; convert and display child’s termination and return codes...
mov ah,4dh
; fxn 4DH = get return code
int 21h
; transfer to MS-DOS
xchg al,ah
; convert termination code
mov bx,offset DGROUP:msg4a
call b2hex
mov al,ah
; get back return code
mov bx,offset DGROUP:msg4b ; and convert it
call b2hex
mov dx,offset DGROUP:msg4 ; DS:DX = address of message
mov cx,msg4_len
; CX = length of message
call pmsg
; display it
mov ax,4c00h
; no error, terminate program
int 21h
; with return code = 0
main1: mov bx,offset DGROUP:msg2a ; convert error code
call b2hex
mov dx,offset DGROUP:msg2 ; display message ‘Memory
mov cx,msg2_len
; resize failed...’
call pmsg
jmp main3
main2: mov bx,offset DGROUP:msg3a ; convert error code
call b2hex
mov dx,offset DGROUP:msg3 ; display message ‘EXEC
mov cx,msg3_len
; call failed...’
call pmsg
main3: mov ax,4c01h
; error, terminate program
int 21h
; with return code = 1
main endp
; end of main procedure
b2hex proc near
; convert byte to hex ASCII
; call with AL = binary value BX = addr to store string
push ax
shr al,1
shr al,1
shr al,1
shr al,1
call ascii
; become first ASCII character
mov [bx],al
; store it
pop ax
and al,0fh
; isolate lower 4 bits, which
call ascii
; become the second ASCII character
mov [bx+1],al
; store it
ret
b2hex endp
ascii proc near
; convert value 00-0FH in AL
add al,’0’
; into a “hex ASCII” character
cmp al,’9’
jle ascii2
; jump if in range 00-09H,
add al,’A’-’9’-1
; offset it to range 0A-0FH,
ascii2: ret
; return ASCII char. in AL
ascii endp
pmsg proc near
; displays message on standard output
; call with DS:DX = address CX = length
mov bx,stdout
; BX = standard output handle
mov ah,40h
; function 40h = write file/device
MS-DOS
um 37 di 138
int 21h
; transfer to MS-DOS
ret
; back to caller
pmsg endp
_TEXT ends
_DATA segment para public ‘DATA’
cname db
‘CHILD.EXE’,0
;pathname of child process
pars dw
_ENVIR
; segment of environment block
dd tail
; long address, command tail
dd fcb1
; long address, default FCB #1
dd fcb2
; long address, default FCB #2
tail db
fcb1-tail-2
; command tail for child
db ‘dummy command tail’,cr
fcb1 db
0
; copied into default FCB #1 in
db 11 dup (‘ ‘)
; child’s program segment prefix
db 25 dup (0)
fcb2 db
0
; copied into default FCB #2 in
db 11 dup (‘ ‘)
; child’s program segment prefix
db 25 dup (0)
msg1 db
cr,lf,’Parent executing!’,cr,lf
msg1_len equ $-msg1
msg2 db
cr,lf,’Memory resize failed, error code=‘
msg2a db
‘xxh.’,cr,lf
msg2_len equ $-msg2
msg3 db
cr,lf,’EXEC call failed, error code=‘
msg3a db
‘xxh.’,cr,lf
msg3_len equ $-msg3
msg4 db
cr,lf,’Parent regained control!’
db
cr,lf,’Child termination type=‘
msg4a db
‘xxh, return code=‘
msg4b db
‘xxh.’,cr,lf
msg4_len equ $-msg4
_DATA ends
_ENVIR segment para public ‘DATA’ ; example environment block to be passed to child
db ‘PATH=‘,0
; basic PATH, PROMPT,
db ‘PROMPT=$p$_$n$g’,0
; and COMSPEC strings
db ‘COMSPEC=C:\COMMAND.COM’,0
db 0
; extra null terminates block
_ENVIR ends
_STACK segment para stack ‘STACK’
db stksize dup (?)
_STACK ends
end main
File CHILD.ASM
È un semplice processo caricato da PARENT.
stdin equ 0
; standard input
stdout equ 1
; standard output
stderr equ 2
; standard error
cr
equ 0dh
; ASCII carriage return
lf
equ 0ah
; ASCII linefeed
DGROUP group _DATA,STACK
_TEXT segment byte public ‘CODE’
assume cs:_TEXT,ds:_DATA,ss:STACK
MS-DOS
um 38 di 138
main
proc far
mov ax,_DATA
mov ds,ax
mov dx,offset msg
; DS:DX = address of message
mov cx,msg_len
; CX = length of message
mov bx,stdout
; BX = standard output handle
mov ah,40h
; AH = fxn 40H, write file/device
int 21h
; transfer to MS-DOS
jc
main2
; jump if any error
mov ax,4c00h
; no error, terminate child
int 21h
; with return code = 0
main2: mov ax,4c01h
; error, terminate child
int 21h
; with return code = 1
main endp
_TEXT ends
_DATA segment para public ‘DATA’
msg db
cr,lf,’Child executing!’,cr,lf
msg_len equ $-msg
_DATA ends
STACK segment para stack ‘STACK’
dw
64 dup (?)
STACK ends
end main
File ROOT.ASM
Usa l’EXEC per caricare ed eseguire un overlays di nome OVERLAY.
stdin equ 0
; standard input
stdout equ 1
; standard output
stderr equ 2
; standard error
stksize equ 128
; size of stack
cr
equ 0dh
; ASCII carriage return
lf
equ 0ah
; ASCII linefeed
DGROUP group _DATA,_STACK
_TEXT segment byte public ‘CODE’ ; executable code segment
assume cs:_TEXT,ds:_DATA,ss:_STACK
stk_seg dw
?
; original SS contents
stk_ptr dw
?
; original SP contents
main proc far
; entry point from MS-DOS
mov ax,_DATA
; set DS = our data segment
mov ds,ax
; now give back extra memory
mov ax,es
; AX = segment of PSP base
mov bx,ss
; BX = segment of stack base
sub bx,ax
; reserve seg stack - seg psp
add bx,stksize/16
; plus paragraphs of stack
MS-DOS
um 39 di 138
mov ah,4ah
; fxn 4AH = modify memory block
int 21h
; transfer to MS-DOS
jc
main1
; jump if resize failed display message ‘Root ‘segment executing...’
mov dx,offset DGROUP:msg1 ; DS:DX = address of message
mov cx,msg1_len
; CX = length of message
call pmsg
; allocate memory for overlay
mov bx,1000h
; get 64 KB (4096 paragraphs)
mov ah,48h
; fxn 48h, allocate mem block
int 21h
; transfer to MS-DOS
jc
main2
; jump if allocation failed
mov pars,ax
; set load address for overlay
mov pars+2,ax
; set relocation segment for overlay
mov word ptr entry+2,ax
; set segment of entry point
push ds
; save root’s data segment
mov stk_seg,ss
; save root’s stack pointer
mov stk_ptr,sp
; now use EXEC to load overlay
mov ax,ds
; set ES = DS
mov es,ax
mov dx,offset DGROUP:oname ; DS:DX = overlay pathname
mov bx,offset DGROUP:pars
; EX:BX = parameter block
mov ax,4b03h
; function 4BH, subfunction 03H
int 21h
; transfer to MS-DOS
cli
; (for bug in some early 8088s)
mov ss,stk_seg
; restore root’s stack pointer
mov sp,stk_ptr
sti
; (for bug in some early 8088s)
pop ds
; restore DS = our data segment
jc
main3
; jump if EXEC failed otherwise EXEC succeeded...
push ds
; save our data segment
call dword ptr entry
; now call the overlay
pop ds
; restore our data segment display message that root segment regained control...
mov dx,offset DGROUP:msg5 ; DS:DX = address of message
mov cx,msg5_len
; CX = length of message
call pmsg
; display it
mov ax,4c00h
; no error, terminate program
int 21h
; with return code = 0
main1: mov bx,offset DGROUP:msg2a ; convert error code
call b2hex
mov dx,offset DGROUP:msg2 ; display message ‘Memory
mov cx,msg2_len
; resize failed...’
call pmsg
jmp main4
main2: mov bx,offset DGROUP:msg3a ; convert error code
call b2hex
mov dx,offset DGROUP:msg3
; display message ‘Memory
mov cx,msg3_len
; allocation failed...’
call pmsg
jmp main4
main3: mov bx,offset DGROUP:msg4a ; convert error code
call b2hex
mov dx,offset DGROUP:msg4 ; display message ‘EXEC
mov cx,msg4_len
; call failed...’
call pmsg
MS-DOS
um 40 di 138
main4: mov ax,4c01h
int 21h
main endp
b2hex proc near
value
push ax
shr al,1
shr al,1
shr al,1
shr al,1
call ascii
mov [bx],al
pop ax
and al,0fh
call ascii
mov [bx+1],al
ret
b2hex endp
ascii proc near
add al,’0’
cmp al,’9’
jle ascii2
add al,’A’-’9’-1
ascii2: ret
ascii endp
pmsg proc near
DS:DX = address,
; error, terminate program
; with return code = 1
; end of main procedure
; convert byte to hex ASCII call with AL = binary
; BX = addr to store string
; become first ASCII character
; store it
; isolate lower 4 bits, which
; become the second ASCII character
; store it
; convert value 00-0FH in AL
; into a “hex ASCII” character
; jump if in range 00-09H,
; offset it to range 0A-0FH,
; return ASCII char. in AL.
; displays message on standard output call with
; CX = length
; BX = standard output handle
; function 40H = write file/device
; transfer to MS-DOS
; back to caller
mov bx,stdout
mov ah,40h
int 21h
ret
pmsg endp
_TEXT ends
_DATA segment para public ‘DATA’
; static & variable data segment
oname db
‘OVERLAY.OVL’,0
; pathname of overlay file
pars dw
0
; load address (segment) for file
dw
0
; relocation (segment) for file
entry dd
0
; entry point for overlay
msg1 db
cr,lf,’Root segment executing!’,cr,lf
msg1_len equ $-msg1
msg2 db
cr,lf,’Memory resize failed, error code=‘
msg2a db
‘xxh.’,cr,lf
msg2_len equ $-msg2
msg3 db
cr,lf,’Memory allocation failed, error code=‘
msg3a db
‘xxh.’,cr,lf
msg3_len equ $-msg3
msg4 db
cr,lf,’EXEC call failed, error code=‘
msg4a db
‘xxh.’,cr,lf
msg4_len equ $-msg4
msg5 db
cr,lf,’Root segment regained control!’,cr,lf
msg5_len equ $-msg5
_DATA ends
_STACK segment para stack ‘STACK’
MS-DOS
um 41 di 138
db
stksize dup (?)
_STACK ends
end main
; defines program entry point
File OVERLAY.ASM
Caricata da ROOT, non usa lo stack perché usa quello di ROOT.
stdin equ 0
; standard input
stdout equ 1
; standard output
stderr equ 2
; standard error
cr
equ 0dh
; ASCII carriage return
lf
equ 0ah
; ASCII linefeed
_TEXT segment byte public ‘CODE’
assume cs:_TEXT,ds:_DATA
ovlay proc far
; entry point from root segment
mov ax,_DATA
; set DS = local data segment
mov ds,ax
; display overlay message ...
mov dx,offset msg
; DS:DX = address of message
mov cx,msg_len
; CX = length of message
mov bx,stdout
; BX = standard output handle
mov ah,40h
; AH = fxn 40H, write file/device
int 21h
; transfer to MS-DOS
ret
; return to root segment
ovlay endp
_TEXT ends
_DATA segment para public ‘DATA’
msg db
cr,lf,’Overlay executing!’,cr,lf
msg_len equ $-msg
_DATA ends
end
File EXECSORT.ASM
Usa l’EXEC per eseguire il filtro MS-DOS SORT come un child process.
stdin equ 0
; standard input
stdout equ 1
; standard output
stderr equ 2
; standard error
stksize equ 128
; size of stack
cr
equ 0dh
; ASCII carriage return
lf
equ 0ah
; ASCII linefeed
jerr macro target
; Macro to test carry flag
local notset
; and jump if flag set.
jnc notset
; Uses JMP DISP16 to avoid
jmp target
; branch out of range errors
notset:
endm
DGROUP group _DATA,_STACK
; ‘automatic data group’
_TEXT segment byte public ‘CODE’ ; executable code segment
assume cs:_TEXT,ds:DGROUP,ss:_STACK
stk_seg dw
?
; original SS contents
stk_ptr dw
?
; original SP contents
main proc far
; entry point from MS-DOS
mov ax,DGROUP
; set DS = our data segment
mov ds,ax
MS-DOS
um 42 di 138
mov ax,es
mov bx,ss
sub bx,ax
add bx,stksize/16
mov ah,4ah
int 21h
jerr main1
mov bx,stdin
mov ah,45h
int 21h
jerr main1
mov oldin,ax
mov dx,offset DGROUP:infile
mov ax,3d00h
int 21h
jerr main1
mov bx,ax
mov cx,stdin
mov ah,46h
int 21h
jerr main1
mov bx,stdout
mov ah,45h
int 21h
jerr main1
mov oldout,ax
mov dx,offset dGROUP:outfile
mov cx,0
mov ah,3ch
int 21h
jerr main1
mov bx,ax
mov cx,stdout
mov ah,46h
int 21h
jerr main1
push ds
mov stk_seg,ss
mov stk_ptr,sp
mov ax,ds
mov es,ax
mov dx,offset DGROUP:cname
mov bx,offset DGROUP:pars
mov ax,4b00h
int 21h
cli
mov ss,stk_seg
mov sp,stk_ptr
sti
pop ds
jerr main1
mov bx,oldin
mov cx,stdin
mov ah,46h
MS-DOS
; let AX = segment of PSP base
; and BX = segment of stack base
; reserve seg stack - seg psp
; plus paragraphs of stack
; fxn 4AH = modify memory block
; transfer to MS-DOS
; dup the handle for stdin
; transfer to MS-DOS
; jump if dup failed
; save dup’d handle
; now open the input file
; mode = read-only
; transfer to MS-DOS
; jump if open failed
; force stdin handle to
; track the input file handle
; transfer to MS-DOS
; jump if force dup failed
; dup the handle for stdout
; transfer to MS-DOS
; jump if dup failed
; save dup’d handle
; now create the output file
; normal attribute
; transfer to MS-DOS
; jump if create failed
; force stdout handle to
; track the output file handle
; transfer to MS-DOS
; save EXECSORT’s data segment
; save EXECSORT’s stack pointer
; set ES = DS
; DS:DX = child pathname
; EX:BX = parameter block
; function 4BH, subfunction 00H
; transfer to MS-DOS
; (for bug in some early 8088s)
; restore execsort’s stack pointer
; (for bug in some early 8088s)
; restore DS = our data segment
; jump if EXEC failed
; restore original meaning of
; standard input handle for
; this process
um 43 di 138
int 21h
jerr main1
; jump if force dup failed
mov bx,oldout
; restore original meaning
mov cx,stdout
; of standard output handle
mov ah,46h
; for this process
int 21h
jerr main1
; jump if force dup failed
mov bx,oldin
; close dup’d handle of
mov ah,3eh
; original stdin
int 21h
; transfer to MS-DOS
jerr main1
; jump if close failed
mov bx,oldout
; close dup’d handle of
mov ah,3eh
; original stdout
int 21h
; transfer to MS-DOS
jerr main1
; jump if close failed display success message
mov dx,offset DGROUP:msg1 ; address of message
mov cx,msg1_len
; message length
mov bx,stdout
; handle for standard output
mov ah,40h
; fxn 40H = write file or device
int 21h
; transfer to MS-DOS
jerr main1
mov ax,4c00h
; no error, terminate program
int 21h
; with return code = 0
main1: mov ax,4c01h
; error, terminate program
int 21h
; with return code = 1
main endp
; end of main procedure
_TEXT ends
_DATA segment para public ‘DATA’
; static & variable data segment
infile db
‘MYFILE.DAT’,0
; input file for SORT filter
outfile db
‘MYFILE.SRT’,0
; output file for SORT filter
oldin dw
?
; dup of old stdin handle
oldout dw
?
; dup of old stdout handle
cname db
‘SORT.EXE’,0
; pathname of child SORT process
pars dw
0
; segment of environment block (0 = inherit parent’s)
dd
tail
; long address, command tail
dd
-1
; long address, default FCB #1 (-1 = none supplied)
dd
-1
; long address, default FCB #2 (-1 = none supplied)
tail db
0,cr
; empty command tail for child
msg1 db
cr,lf,’SORT was executed as child.’,cr,lf
msg1_len equ $-msg1
_DATA ends
_STACK segment para stack ‘STACK’
db
stksize dup (?)
_STACK ends
end main
; defines program entry point
Quest’applicazione richiede i file SORT.EXE e MYFILE.DAT nella directory corrente e
manda in uscita MYFILE.SRT.
MS-DOS
um 44 di 138
TSR (TERMINATE AND STAY RESIDENT)
Introduzione
Ad una prima occhiata, avere un processo morto in giro che non può essere attivato non
sembra un’attrattiva interessante; è, però da ricordare che i processi in MS-DOS possono
installare i loro driver d’interrupt.
In particolare, un processo può installare un driver di una nuova tastiera che è chiamato
per ogni interruzione di tastiera che sul PC si ha quando è premuto o rilasciato qualsiasi
tasto, compreso CTRL, ALT e SHIFT.
Questo driver può essere allocato all’interno del processo inaccessibile TSR.
Il driver esamina velocemente il tasto per vedere se esso è un tasto speciale o una
combinazione di tasti, chiamata hot key, che attiva il codice TSR.
In caso contrario, il carattere è messo nella coda d’input di caratteri del SO e il TSR ritorna
dall’interruzione all’applicazione.
Se è una hot key, il TSR inizia a lavorare e fare ciò che era stato programmato.
Scrivere un TSR è complicato e devono essere risolti molti problemi.
Prima di tutto il TSR deve copiare l’immagine del video attuale e salvarla da un’altra parte,
così essa può essere recuperata quando il TSR termina il suo lavoro.
Esso deve inoltre eseguire il suo lavoro senza chiamare MS-DOS poiché questi dovrebbe
essere stato attivo al momento dell’interruzione.
MS-DOS non è rientrante, il che significa che non può gestire una seconda chiamata
finché non è terminata la prima.
Tra le altre cose, il TSR non può usare MS-DOS per leggere la tastiera per gli input
successivi e non può usarlo per scrivere sul video e per accedere ai file.
Esso, inoltre, non può usare il BIOS perché anche questo dovrà trovarsi nel mezzo di una
chiamata al momento della battuta.
Ne consegue che il TSR deve avere un proprio I/O o trovare dei buoni sotterfugi per
raggirare MS-DOS in modo che pensi che esso sia l’applicazione attualmente in
esecuzione, manipolando le strutture dei dati interni di MS-DOS.
L’applicazione DOSKEY è un TSR che è fornito standard con MS-DOS.
MS-DOS contiene alcuni accorgimenti che rendono possibile ai TSR fare chiamate di
sistema raggirando MS-DOS; nessuna di queste è documentata ufficialmente nel manuale
Microsoft, il Microsoft MS-DOS Programmer’s Reference Manual.
La Microsoft mette in guardia i programmatori dall’usare chiamate di sistema non
documentate perché si riserva di modificarle o eliminarle nelle versioni future.
Al contrario, le chiamate di sistema ufficiali non sono rimosse quasi mai e non ha
importanza quanto esse siano obsolete.
Le applicazioni residenti sono, come indica il nome, collocate permanentemente in
memoria e in seguito eseguite solo su richiamo esplicito da parte di un’altra applicazione,
per un tasto premuto dall’operatore o per mezzo di un interrupt.
Un esempio di TSR è la parte principale di COMMAND.COM, che una volta caricata resta
in memoria e i cui moduli sono richiamati con interruzioni S/W.
Altro esempio è dato dalla routine di stampa, PRINT.COM, al primo richiamo PRINT
s’installa in memoria e quindi vi rimane, pronta ad entrare in funzione quando richiesto.
In MS-DOS è generato un tick di sistema con una frequenza di 18.2065 volte al secondo,
questo tick è utilizzato per comandare il processo di stampa che quindi appare funzionante
parallelamente ad un qualsiasi altro processo in esecuzione.
MS-DOS
um 45 di 138
Al termine di questa procedura di sistema è chiamato il processo il cui indirizzo
corrisponde all’INT 1CH normalmente il vettore relativo ad 1CH punta ad IRET.
Se però questo vettore è ridefinito, si ha modo di fare eseguire automaticamente
un’applicazione programma 18.2065 volte al secondo.
L’intercettazione del tick di sistema è la chiave per il funzionamento del multitasking.
In MS-DOS è possibile scrivere proprie routine da rendere residenti e associarle ad
interrupt particolari, questa tecnica d’intercettazione rappresenta un mezzo molto potente
nello sviluppo di applicazioni e sistemi.
È, infatti, possibile intercettare qualsiasi interrupt, anche quelli generati automaticamente
in situazione di errore per esempio: division by zero, oppure chiamate in casi particolari,
quali l’immissione da tastiera di caratteri CTRL+ C e CTRL+BREAK.
FUNZIONE 31H
Descrizione
Categoria
Input
Output
TERMINATE AND STAY RESIDENT (KEEP PROCESS)
Applicazioni residenti.
Servizi di sistema.
DX = numero di paragrafi del TSR.
AL = codice di uscita.
FUNZIONE 25H
Descrizione
Categoria
Input
SET INTERRUPT VECTOR
Inizializza un vettore d’interrupt.
Servizi di sistema.
AH = 25H
AL = numero d’interrupt da 0 a FFH.
DS:DX = pointer alla routine d’interrupt (DS = CS, DX = IP).
Si consiglia di leggere e salvare il vecchio vettore prima di aggiornarlo, con la funzione
35H, in modo da poterlo ripristinare una volta terminata l’applicazione.
Esempio per applicazioni COM, non è necessario inizializzare DS perché coincide con CS.
MOV AH,25H
MOV AL,80H
MOV DX,OFFSET serv_80h
INT 21H
serv_80h
PROC NEAR
....
serv_80h
ENDP
Esempio per applicazioni EXE, si deve inizializzare DS con il valore di segmento nel quale
risiede la routine.
PUSH DS
MOV AH,25H
MOV AL,80H
MOV DX,SEG serv_80h
MOV DS,DX
MOV DX,OFFSET serv_80h
INT 21H
POP DS
serv_80h
PROC NEAR
....
serv_80h
ENDP
MS-DOS
um 46 di 138
FUNZIONE 35H
Descrizione
Categoria
Input
Output
GET INTERRUPT VECTOR
Legge un vettore di interrupt.
Servizi di sistema.
AH = 35H
AL = numero d’interrupt da 0 a FFH.
ES:BX = pointer al vettore d’interrupt (ES = CS, BX = IP).
Il metodo più pratico per accedere dall’esterno ad un processo residente è per mezzo di
un interrupt S/W.
Per questo occorre che l’indirizzo del punto di entrata del processo sia scritto nella tabella
degli interrupt collocata nella parte più bassa della memoria.
File RTCLOCK.ASM
Mantiene un orologio interno il cui valore è mostrato in continuazione nella parte superiore
dello schermo nella forma HH:MM:SS e non influisce sull’esecuzione di altri processi attivi
al momento.
Il tick di sistema è uguale a 1/18.2065 è aggiornato 18.2065 volte al secondo, alla
mezzanotte il tick è posto a zero e il conteggio ricomincia.
Il tick è letto da INT 1AH funzione 00H e messo in CX:DX.
1 giorno
18.2065 * 60 * 60 * 24 = 1573041.6 tick.
1 ora
18.2065 * 60 * 60 = 65543.4 tick.
1 minuto
18.2065 * 60 = 1092.4 tick.
Ora corrente = tick correnti / 65543.4.
resto1 = numero di tick in più rispetto l’ora corrente.
minuti correnti = resto1 / 1092.34.
resto2 = numero di tick in più rispetto ai minuti correnti.
secondi correnti = resto2 / 18.2065.
65545 non è rappresentabile in una word per cui non si può usare DIV, basta dividere per
due il numero di tick correnti, per esempio 32772.7
Si divide in due parti, una d’inizializzazione e una residente.
Initialize è eseguita una sola volta, al primo richiamo di RTCLOCK.
In questa parte si ricorre a MS-DOS per associare resident_clock all’interruzione 1CH e
per terminare subito l’esecuzione, lasciando però il codice residente in memoria, 40
paragrafi sono sufficienti a contenere l’intero processo.
resident_clock deve salvare su stack che appartiene al processo originale interrotto, lo
stato dei registri di cui fa uso e ripristinarli al termine dell’esecuzione.
Non è necessario salvare AX, DX e DS in quanto i loro valori sono già stati messi su stack
dalla routine originale MS-DOS di gestione tick di sistema.
Lo stato corrente della variabile time di sistema è ottenuto con un richiamo al BIOS INT
1AH Times Of Day, questa variabile è contenuta in macchina come il numero di tick
trascorsi da mezzanotte.
Questo valore può eccedere i 16 bit di lunghezza, per cui la parte alta di time è ritornata in
CX e la parte meno significativa in DX.
RTCLOCK deve estrarre da time i valori attuali di ore, minuti e secondi e convertirli in
caratteri ASCII, formattandoli nella stringa outstr da mostrare sullo schermo direttamente
nella RAM video in quanto permette un trasferimento molto rapido.
La posizione esatta di quest’area dipende dal tipo di scheda grafica, nell’applicazione essa
è definita con la costante vidseg.
Le caratteristiche principali alle quali devono rispondere i moduli di servizio degli interrupt
sono, infatti, compattezza e rapidità di esecuzione.
Una volta completate queste operazioni, il controllo torna alla procedura originale con il
ripristino dallo stack dei valori dei registri e l’istruzione IRET.
MS-DOS
um 47 di 138
STACKSEG SEGMENT PARA STACK ‘STACK’
DB 200H DUP (?)
STACKSEG ENDS
VIDSEG EQU 0B800H
;0B00H per video monocromatici
OUT_MODE EQU 112
;normale = 7 alta intensità = 15 reverse = 112
BYTE_TO_DEC MACRO
;conversione di un byte con valore 0..99 contenuto in AL
XOR AH,AH
;nei char ASCII corrispondenti in AH e AL
MOV BL,10
;AL modulo 10
DIV BL
;quoziente in AL resto in AH
ADD AX,3030H
;conversione in ASCII
ENDM
DATA SEGMENT WORD ‘DATA’
TIME DB 16 DUP (OUT_MODE) ;stringa uscita schermo
HOURS DB 0
MINUTES DB 0
DATA ENDS
CSEG SEGMENT WORD ‘CSEG’
ASSUME CS:CSEG,DS:DATA
RESIDENT_CLOCK:
;sezione residente in memoria
CLI
PUSH BX
PUSH CX
PUSH SI
PUSH DI
PUSH ES
STI
MOV AX,DATA
MOV DS,AX
MOV AH,0H
;servizio bios time of day
INT 1AH
;richiamo funzione bios, il risultato (numero tick) in
CX:DX
MOV AX,DX
;la parte bassa va in AX
MOV DX,CX
;la parte alta va in DX
SHR DX,1
DX / 2
SHR AX,1
;AX / 2
AND CL,00000001B
;se c’è riporto nella parte alta trasporto in AX
CMP CL,0
JE CONT_1
ADD AH,10000000B
CONT_1:
MOV CX,32772
;65543 tick / ora approssimato da 2 * 32772
DIV CX
CMP AX,24
;DX:AX / CX risultato in AX
JB CONT_2
;azzeramento se ore>=24
XOR AX,AX
CONT_2:
MOV HOURS,AL
MOV AX,DX
;resto della prima divisione
XOR DX,DX
MOV CX,546
;1092 conteggi / minuto approssimato da 2 * 546
DIV CX
CMP AX,60
;DX:AX / CX risultato in AX
JB CONT_3
;azzeramento se minuti >=60
XOR AX,AX
MS-DOS
um 48 di 138
CONT_3:
MOV MINUTES,AL
MOV AX,DX
;resto della seconda divisione
XOR DX,DX
MOV CX,10
;18.2 conteggi / secondo approssimato da 91 * 2 / 10
MUL CX
;AX * CX risultato in DX:AX
MOV CX,91
DIV CX
;DX:AX / CX risultato in AX
CMP AX,60
JB CONT_4
;azzeramento se secondi >=60
XOR AX,AX
CONT_4:
BYTE_TO_DEC
;conversione di secondi, minuti e ore in ASCII
MOV TIME[12],AL
MOV TIME[14],AH
MOV AL,MINUTES
BYTE_TO_DEC
MOV TIME[6],AL
MOV TIME[8],AH
MOV AL,HOURS
BYTE_TO_DEC
MOV TIME[0],AL
MOV TIME[2],AH
MOV TIME[4],”:”
MOV TIME[10],”:”
CLD
MOV SI,OFFSET TIME
;DS:DX punta a TIME
MOV BX,VIDSEG
MOV ES,BX
MOV DI,8CH
;ES:DI punta a destinazione nella memoria video
MOV CX,16
;16 byte da copiare
REP
MOVSB
;copia nella memoria video
CLI
POP ES
POP DI
POP SI
POP CX
POP BX
STI
IRET
;uscita da RTCLOCK, termine parte residente
INITIALIZE:
;parte non residente eseguita una sola volta
ASSUME DS:CSEG
MOV AX,CSEG
MOV DS,AX
;DS:DX punta resident_clock
MOV DX,OFFSET RESIDENT_CLOCK
MOV AL,1CH
MOV AH,25H
INT 21H
MOV DX,40
;DX = numero paragrafi residenti 40 * 16 = 640 byte
MOV AL,0
;codice di uscita processo
MOV AH,31H
INT 21H
CSEG ENDS
END INITIALIZE
MS-DOS
um 49 di 138
Un altro tipo di TSR orologio residente, la parte transiente ha i seguenti compiti.
Salva in A = SEG:OFF il vettore d’interrupt corrente da intercettare; modifica il vettore
d’interrupt in modo che punti alla prima istruzione della parte residente; termina
informando MS-DOS che deve essere liberata solo la parte di memoria occupata dalla
parte transiente.
La parte residente rimane in memoria mentre le altre applicazioni sono in esecuzione e
deve effettuare le seguenti operazioni: salva nello stack lo stato del sistema; esegue il
processo; ripristina dallo stack lo stato del sistema; salta all’indirizzo contenuto in A.
div_ore EQU 32772
div_min EQU 546
div_sec EQU 91
dati SEGMENT
buf_video DW ?
porta_stato DW ?
vecchio_vettore DD ?
colonna DW 0000h
dati ENDS
codice SEGMENT
ASSUME CS:codice,DS:dati
conv
PROC NEAR
MOV CL,10
DIV CL
ADD AX,3030h
RET
conv ENDP
visualizza PROC NEAR
PUSHF
PUSH DX
MOV DX,porta_stato
PUSH AX
CLI
CLD
ciclo_1:IN AL,DX
TEST AL,1
JNZ ciclo_1
ciclo_2:IN AL,DX
TEST AL,1
JZ ciclo_2
POP AX
MOV AH,1Eh
STOSW
POP DX
POPF
RET
visualizza ENDP
parte_res: PUSH CX
PUSH DI
PUSH ES
MOV AX,dati
MOV DS,AX
MOV AX,buf_video
MOV ES,AX
MS-DOS
;32772 * 2 = 65544 = 60 * 60 * 18.2065
;546 * 2 = 1092 = 60 * 18.2065
;91 * 2 = 182 cioè circa 18.2065 * 10
;converte un numero minore
;di 100 in AX nei due caratteri
;ASCII corrispondenti in AL e AH
;salva anche DX nello stack
;e carica porta_stato in DX
;sfondo blu e carattere giallo
;ripristina DX
;Salva CX, DI ed ES
;AX, DX e DS sono già stati
;salvati dal SO
;carica in AX il segmento dati
;e lo sposta in DS
;carica buf_video in AX
;e lo sposta in ES
um 50 di 138
MOV DI,colonna
MOV AL,’ ‘
CALL visualizza
MOV AH,0
INT 1Ah
SHR DX,1
SHR CX,1
JNC L_0
OR DX,8000h
L_0: XCHG DX,CX
MOV AX,CX
MOV CX,div_ore
DIV CX
CMP AX,24
JNE L_1
XOR AX,AX
L_1: CALL conv
MOV CH,AH
CALL visualizza
MOV AL,CH
CALL visualizza
MOV AL,’:’
CALL visualizza
XOR AX,AX
XCHG AX,DX
MOV CX,div_min
DIV CX
CMP AX,60
JNE L_2
XOR AX,AX
L_2: CALL conv
MOV CH,AH
CALL visualizza
MOV AL,CH
CALL visualizza
MOV AL,’:’
CALL visualizza
MOV AX,DX
XOR DX,DX
MOV CX,10
MUL CX
MOV CX,div_sec
DIV CX
CMP AX,60
JNE L_3
XOR AX,AX
L_3: CALL conv
MOV CH,AH
CALL visualizza
MOV AL,CH
CALL visualizza
MOV AL,’ ‘
CALL visualizza
POP ES
MS-DOS
;carica la colonna di inizio in DI
;in AL uno spazio
;e visualizza a partire da colonna
;carica 0 in AH e richiama il BIOS
;per la lettura del contatore dei tick di sistema
;dividi per due DX
;e CX
;se il bit meno significativo di CX è a 0 salta a L_0 altrimenti
;metti ad 1 il bit più significativo di DX
;scambia DX con CX e sposta CX in AX
;ora i tick di sistema si trovano nella coppia DX:AX
;carica 32772 in CX
;e dividi
;confronta con 24
;se non uguale salta altrimenti
;considera zero il quoziente
;chiama la procedura di conversione
;sposta temporaneamente AH in CH
;e visualizza prima cifra ore
;recupera CH e visualizza
;seconda cifra ore
;visualizza il
;carattere “:”
;azzera AX
;sposta il resto in AX e 0 in DX
;carica 546 in CX
;e dividi per CX
;confronta con 60
;se non uguale salta altrimenti
;considera 0 il quoziente
;chiama la procedura di conversione
;salva temporaneamente AH in CH
;visualizza prima cifra minuti
;recupera CH e visualizza
;seconda cifra minuti
;visualizza il
;carattere “:”
;sposta il resto in AX
;azzera DX
;carica 10 in CX
;e moltiplica
;carica 91 in CX
;e dividi per CX
;confronta con 60
;se non uguale salta altrimenti
;considera 0 il quoziente
;chiama la procedura di conversione
;salva temporaneamente AH in CH
;e visualizza prima cifra secondi
;recupera CH
;e visualizza seconda cifra
;visualizza uno
;spazio
;ripristina i
um 51 di 138
POP DI
;registri ES
POP CX
;DI e CX e
JMP vecchio_vettore
;salta all’indirizzo contenuto in vecchio_vettore
parte_trans PROC NEAR
MOV AX,dati
;carica il segmento dati in AX
MOV DS,AX
;e lo sposta in DS
CALL det_porta_stato
;chiama la procedura che determina l’indirizzo della porta di stato del CRT controller
MOV porta_stato,DX
;e lo salva in porta_stato
CALL det_buf_video
;routine che determina l’indirizzo del buffer video
MOV buf_video,DX
;e lo salva in buf_video
SUB colonna,10
;sottrae 10 (spazio utilizzato per stampare l’ora) a colonna
SHL colonna,1
;e moltiplica per due (infatti ogni carattere è rappresentato nel buffer video con due byte
; uno di codice ed uno per l’attributo)
MOV AL,1Ch
;legge il vettore corrente
MOV AH,35h
;dell’interrupt 1CH e lo salva
INT 21h
;in vecchio_vettore
MOV WORD PTR vecchio_vettore,BX
MOV WORD PTR vecchio_vettore+2,ES
MOV AX,codice
;carica segmento codice in AX
MOV DS,AX
;e lo sposta in DS
MOV DX,OFFSET parte_res
;offset di parte_res in DX
MOV AL,1Ch
;modifica il vettore 1Ch in
MOV AH,25h
;modo che punti a parte_res
INT 21h
MOV DX,30
;carica in DX il numero di paragrafi necessari alla parte
;residente (480 byte)
;parte_res = PSP (256 byte) + dati + occupazione
MOV AL,0
;carica in AL il codice di terminazione
MOV AH,31h
;carica 31h in AH
INT 21h
;e termina rimanendo residente
parte_trans ENDP
det_buf_video PROC NEAR
PUSH BX
PUSH AX
MOV AH,0Fh
INT 10h
MOV BYTE PTR colonna,AH
;salva AH (numero di caratteri per riga) nella variabile colonna
MOV DX,128
CMP AH,40
JE no80
SHL DX,1
no80:XCHG DX,AX
MUL BH
CMP DL,06
JG mono
ADD AX,0800h
mono:ADD AX,0B000h
MOV DX,AX
POP AX
POP BX
RET
MS-DOS
um 52 di 138
det_buf_video ENDP
det_porta_stato PROC NEAR
PUSH DS
XOR DX,DX
MOV DS,DX
MOV DX,WORD PTR DS:[0463h]
ADD DX,6
POP DS
RET
det_porta_stato ENDP
codice
ENDS
END parte_trans
TSRInt EQU 64H
STDOUT EQU 1
RESIDENT_DATA SEGMENT word public ‘DATA’
Message DB 0Dh,0Ah,’Hello, World’,0Dh,0Ah
RESIDENT_DATA ENDS
RESIDENT_TEXT SEGMENT byte public ‘CODE’
ASSUME cs:RESIDENT_TEXT,ds:RESIDENT_DATA
TSRAction PROC far
sti
push ds
push ax
push bx
push cx
push dx
mov dx,seg RESIDENT_DATA
mov ds,dx
mov dx,offset Message
mov cx,16
;CX = length
mov bx,STDOUT
;BX = file handle
mov ah,40h
int 21h
pop dx
pop cx
pop bx
pop ax
pop ds
iret
TSRAction ENDP
RESIDENT_TEXT ENDS
TRANSIENT_STACK SEGMENT word stack ‘TSTACK’
DB 80h dup(?)
TRANSIENT_STACK ENDS
TRANSIENT_TEXT SEGMENT para public ‘TCODE’
ASSUME cs:TRANSIENT_TEXT,ss:TRANSIENT_STACK
HelloTSR PROC far
; CS:IP -> SnapTSR, SS:SP -> stack, DS,ES -> PSP
; Install this TSR’s interrupt handler
mov ax,seg RESIDENT_TEXT
mov ds,ax
mov dx,offset RESIDENT_TEXT:TSRAction
mov al,TSRInt
mov ah,25h
MS-DOS
um 53 di 138
int 21h
; Terminate and stay resident
mov dx,cs
;DX = paragraph address of start of transient portion (end of resident portion)
mov ax,es
;ES = PSP segment
sub dx,ax
;DX = size of resident portion
mov ax,3100h
;AH = INT 21h function number (TSR) AL = 00H (return
code)
int 21h
HelloTSR ENDP
TRANSIENT_TEXT ENDS
END HelloTSR
Bisogna eseguire INT 64H per visualizzare il messaggio seguente.
#include <dos.h>
int main (void)
{union REGS reg;
int86(0x64,&reg,&reg);
return(0);
}
Perché I TSR SONO COSì PROBLEMATICI?
Perché MS-DOS non è rientrante: in altre parole se il DOS sta operando con
un’applicazione, non può sospendere tale operazione per eseguire qualcos’altro e
ritornare poi al suo impiego iniziale.
Affinché un TSR sappia di poter interrompere il processo DOS è necessario.
1. Esaminare un flag indicante la possibilità di effettuare l’interruzione.
2. Intercettare un interrupt, tutti i TSR sono attivati da un interrupt.
Le routine di servizio degli interrupt ISR (Interrupt Service Routine) devono essere scritte
come funzioni di tipo FAR, devono terminare con IRET, devono all’inizio inserire tutti i
registri nello stack con PUSH, devono al termine recuperare tutti i registri con POP.
Ad esempio INT 64H si utilizza quale flag indicante se il TSR è già stato caricato.
BorlandC dispone, come supporto per i TSR, del modificatore del tipo di funzione
denominato INTERRUPT che preserva tutti i registri e termina con IRET.
 Non far coesistere due o più TSR.
 Non bypassare mai MS-DOS e il BIOS.
Definire una propria DTA (Data Transfer Area) per accedere ai dischi: il DOS trasferisce le
informazioni nella DTA allocata per ogni applicazione, la DTA di default è parte del PSP di
cui tutte le applicazioni dispongono, quando un TSR interrompe un’altra applicazione esso
eredita il PSP dell’applicazione quindi se esso effettua un I/O corre il rischio di
sovrascrivere le informazioni già presenti nella DTA dell’altra applicazione.
BorlandC dispone di una var _psp.
PROGETTO BASE DI UN TSR
Tutti i TSR sono costituiti da tre parti principali.
1. INIZIALIZZAZIONE DEL TSR
Inizializza ogni cosa in base alle esigenze dell’applicazione.
Reindirizzamento dei vettori di interrupt usati.
Chiamata alla funzione DOS 0x31 in BorlandC è la funzione seguente.
void keep (unsigned char status,unsigned mem_size);
MS-DOS
um 54 di 138
Dove.
mem_size è un valore a 16 bit che indica la quantità di RAM da allocare per il TSR:
operazione complessa.
2. ISR
Per intercettare la pressione di un tasto si dovrà sostituire INT 9H con uno appositamente
creato: è importante ricordarsi di memorizzare l’indirizzo della routine ISR associata a tale
interrupt.
A questo punto, ogni volta che sarà premuto un tasto, si avrà la generazione di un INT 9H,
fatto che si tradurrà in una chiamata alla nuova ISR di tastiera.
La nuova ISR dovrà chiamare la routine originale di ISR e poi determinare se il tasto
premuto corrisponde al tasto chiave: se il TSR dovrà essere attivato solo se la situazione
corrente lo consente.
Inoltre il tasto chiave dovrà essere eliminato dalla coda d’input, in modo tale che lo stesso
non sia poi preso in considerazione dall’applicazione interrotta.
Il TSR dovrà disporre anche di un’altra routine ISR per determinare se la operazione
corrente del DOS può essere interrotta.
3. L’APPLICAZIONE
Il TSR deve operare attraverso una finestra perché così l’utente può continuare a vedere
parte dell’applicazione interrotta.
Inoltre, la quantità di RAM e il tempo richiesto per memorizzare e ripristinare lo schermo è
minore.
TSR E MODI GRAFICI
È possibile usare un TSR in modo grafico, però è opportuno attendere la modalità testo
per questi motivi.
1. Ci sono pochi modi testo 80X25 colori, bianco e nero, monocromatico mentre vi sono
molti modi grafici.
2. In modo testo 80X25 servono 4000 byte per memorizzare lo schermo.
3. Tutti i modi grafici richiedono più memoria: almeno 64 KB.
QUANDO PUò ESSERE EFFETTUATA L’INTERRUZIONE
Un’operazione DOS può essere interrotta quando non sta facendo nulla, al contrario non
si deve interrompere il DOS mentre sta effettuando un accesso al disco o durante la
scrittura sullo schermo.
Ma esaminando PRINT si sono trovate due funzioni.
1. L’interrupt di attesa evento DOS.
Quando il DOS attende l’input dall’utente, entra in un loop nel quale è controllata la
pressione di un tasto.
Parte di questo loop consiste nell’esecuzione di INT 28H chiamato dalle 12 funzione DOS
d’I/O carattere.
Ogni volta che INT 28H è eseguito il DOS può essere interrotto.
L’applicazione dovrebbe intercettare INT 28H e usarlo per richiamare il TSR solo se il
tasto chiave è stato premuto.
Il problema però è che il DOS usa INT 28H solo per funzioni d’I/O carattere, quindi è
necessario un altro meccanismo che consenta di controllare con maggior frequenza la
chiamata al TSR, molte applicazioni non chiamano mai l’INT 28H.
2. Il flag di DOS attivo.
Durante la fase di attività del DOS vi è un byte che è messo a 1, mentre è a 0 se è inattivo.
La locazione di questo flag può essere gestita con la chiamata a INT 34H che restituisce il
segmento del flag in ES e l’offset in BX.
Prima di essere attivato, l’applicazione dovrà assicurarsi che tale flag sia a 0, altrimenti il
MS-DOS
um 55 di 138
TSR dovrà rimanere inattivo.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <ctype.h>
#include <fcntl.h>
#include <conio.h>
#include <bios.h>
#include <io.h>
#define BORDER 1
#define MAX_FRAME 3
#define REV_VID 0x70
#define NORM_VID 7
#define VID_SIZE 4000
#define STK_SIZE 0x2000
/* prototipi di funzione della finestra */
void save_video(int num), restore_video(int num);
void write_string(int x, int y, char *p, int attrib);
void write_char(int x, int y, char ch, int attrib);
void tsrdisplay_header(int num), tsrdraw_border(int num);
void tsrwindow_gets(int num , char *s);
void tsrwindow_cleol(int num), tsrwindow(int num);
void tsrwindow_cls(int num), set_vid_mem(void);
void tsrdeactive(int num),tsrwindow_bksp(int num),goto_xy(int x, int y);
int make_tsrwindow(int num, char *header, int startx, int starty, int endx, int endy, int
border);
int tsrwindow_xy(int num, int x, int y),tsrwindow_puts(int num, char *str);
int video_mode(void), tsrwindow_putchar(int num, char ch);
int tsrwindow_getche(int num);
int tsrwindow_upline(int num), tsrwindow_downline(int num),readkey(void);
/* prototipi di funzione del TSR */
void cursor_pos(void),activate_tsr(void);
void interrupt tsr_keystroke(void);
void interrupt dos_idle(void);
void interrupt new_int8(void);
void interrupt (*old_int28)();
void interrupt (*old_int8)();
void interrupt (*old_key)();
void interrupt (*old_int64)();
void notepad(void), calc(void),code(void);
int push(int i), pop(void);
char far *vid_mem;char video;
struct window_frame {
int startx, endx, starty, endy;
/* angoli della finestra */
int curx, cury;
/* posizione corrente del cursore nella finestra */
unsigned char *p;
/* puntatore al buffer */
char *header;
/* titolo della finestra */
int border;
/* stato del bordo: presente/assente */
int active;
/* stato della finestra: 1 se attiva, altrimenti 0 */
} frame[MAX_FRAME];
char wp[VID_SIZE];
/* buffer che sarà’ usato dalla funzione save_video() per
MS-DOS
um 56 di 138
memorizzare il contenuto dello schermo */
/* se l'applicazione è attiva allora busy è definita a 1, altrimenti a 0.*/
char busy = 0,far *dos_active;
unsigned char stck[STK_SIZE];
unsigned int sp, ss;
int old_row, old_col, key;
int main(void)
{ union REGS r;
struct SREGS s;
clrscr();
/* verifica che il TSR non sia già stato caricato perchè esso userebbe nuove
porzioni di RAM, se l'applicazione esce dopo aver rediretto i vettori
d’interrupt ma prima di aver chiamato la function DOS 31H, avviene che ad
ogni esecuzione di ridirezione salterà in posizioni sconosciute. */
old_int64 = getvect(0x64);
/* interrupt non usato */
if(!old_int64)
setvect(0x64, new_int8); /* attiva un flag */
else {
printf("L'applicazione residente e’ gia’ stata caricata.");
return (1);
}
/* ottiene l’indirizzo del flag dos_active */
r.h.ah = 0x34;
int86x(0x21, &r, &r, &s);
dos_active = MK_FP(s.es, r.x.bx);
/* prende gli indirizzi della vecchia ISR e li memorizza */
old_key = getvect(9);
/* interrupt di tastiera */
old_int28 = getvect(0x28);
/* interrupt 28H */
old_int8 = getvect(8);
/* interrupt di orologio */
/* reindirizza i vettori d’interrupt alle nuove routine, è importante collegare
le nuove ISR a quelle originali perchè, come nel caso dell’interrupt da
tastiera e di orologio, le routine ISR originali svolgono alcuni compiti cruciali */
setvect(9, tsr_keystroke);
setvect(0x28, dos_idle);
setvect(8, new_int8);
printf("F1: Blocco Appunti F2: Calcolatore F3: Cripta file");
printf(" F4: Disattiva\n");
key = 0;
/* passa i codici di tastiera alle funzioni */
set_vid_mem();
/* prende l’indirizzo della memoria video */
/* inizializza tutte le finestre */
make_tsrwindow(0, " Blocco appunti [Esc per uscire] ", 20, 5, 60, 16, BORDER);
make_tsrwindow(1, " Calcolatore ", 20, 8, 60, 12, BORDER);
make_tsrwindow(2, " Cripta file ", 20, 8, 60, 10, BORDER);
keep(0, 2000);
/* termina e rimane residente */
return (0);
}
/* questa è la funzione che intercetta l’interrupt di tastiera (INT 9H), richiama
la ISR originale che legge il tasto e lo accoda nel buffer di tastiera e verifica
se è stato premuto un tasto chiave, questa funzione non richiama nessuna
function DOS o BIOS per leggere il tasto dal buffer, al contrario lo interroga
direttamente per due motivi:
- risulta più semplice controllare direttamente il buffer
- consente la modifica diretta del buffer
la function non effettua direttamente l’attivazione del TSR perché alcune
MS-DOS
um 57 di 138
applicazioni non possono essere interrotte durante l’interrupt da tastiera
IL BUFFER DI TASTIERA
il DOS prevede che il limite max per il buffer sia di 15 caratteri, ogni volta
che è premuto un tasto è generato l’INT 9H, la function ISR per l’input da
tastiera legge il carattere dalla porta e lo accoda nel buffer, quando è
chiamata una function DOS o BIOS per l’input di un carattere dalla tastiera,
solo il contenuto del buffer è esaminato e non la porta relativa: quindi anche
le funzioni di un programmatore possono controllare direttamente il buffer
di tastiera permettendo così al TSR di verificare l’eventuale pressione di un
tasto chiave, il buffer di tastiera è situato all’indirizzo: 0000:041E, dato che
ogni codice di scansione tastiera richiede 2 byte, la lunghezza richiesta
per il buffer di 15 caratteri è pari a 30 byte, in realtà il buffer è lungo 32
byte a causa del fatto che in coda ad esso è inserito automaticamente un
codice di CR, il buffer è strutturato a coda circolare con pointer d'inizio
coda (0000:041A) che punta all’ultimo carattere inserito da tastiera e
fine coda (0000:041C) che punta al carattere che sarà utilizzato
alla prima richiesta di input del DOS o del BIOS */
void interrupt tsr_keystroke(void)
{ int far *t2 = (int far *) 1050;
/* indirizzo puntatore di inizio coda */
char far *t = (char far *) 1050; /* indirizzo puntatore di inizio coda */
(*old_key)();
/* prima chiama la vecchia ISR */
if(*t != *(t+2)) {
/* se non e’ vuoto */
t += *t-30+5;
/* avanza alla posizione del carattere */
if(*t>=59 && *t<=62) {
switch(*t) {
/* controlla il codice di scansione */
/* la ragione per cui è utilizzata la codifica del tasto piuttosto che
il suo codice di scansione è dovuta al fatto che per modificare
il tasto chiave basta cambiare una sola linea di codice */
case 59: key = 1;
/* F1 - blocco appunti */
break;
case 60: key = 2;
/* F2 - calcolatore */
break;
case 61: key = 3;
/* F3: cripta file */
break;
case 62: key = 4;
/* F4: disattiva il TSR */
break;
*(t2+1) = *t2;
}
}
}
/* nuovo interrupt 8, controlla se il DOS è libero, cioè se busy=0 e se key=tasto
chiave, se entrambe le condizioni sono vere allora il tsr è attivato. */
void interrupt new_int8(void)
{ (*old_int8)();
/* chiama l’interrupt 8 originale */
/* se il DOS è inattivo, il TSR non è stato ancora attivato e se è stato
premuto un tasto chiave, allora attiva il TSR */
if(!*dos_active && !busy && key)
activate_tsr();
}
/* questa funzione intercetta l’INT 28H (evento di DOS in attesa), controlla
se il DOS è libero, cioè se busy=0 e se key=tasto chiave, se entrambe
le condizioni sono vere allora il TSR è attivato */
void interrupt dos_idle(void)
{ (*old_int28)();
/* chiama la ISR originale dell’interrupt 0x28 */
MS-DOS
um 58 di 138
if(!busy && key)
activate_tsr();
}
/* richiama il TSR */
void activate_tsr(void)
{ /* definisce lo stack del TSR */
disable();
/* disabilita gli interrupt durante la sostituzione */
ss = _SS;
sp = _SP;
_SS = _DS;
_SP = (unsigned) &stck[STK_SIZE-2];
enable();
/* abilita gli interrupt */
cursor_pos();
/* prende la posizione corrente del cursore */
/*controlla il modo video, non richiama nulla se non si trova in modo testo a 80 colonne */
video = video_mode();
if(!busy && (video==7 || video==3 || video==2)) {
busy = !busy;
/* non consente una seconda attivazione */
switch(key) {
case 1: notepad();
break;
case 2: calc();
break;
case 3: code();
break; }
busy = !busy;
}
if(key==4) /* disattiva il TSR */
write_string(old_col, old_row, "TSR disattivato.", NORM_VID);
goto_xy(old_col, old_row);
/* ripristina la posizione del cursore */
/* ripristina il vecchio stack */
disable();
_SP = sp;
_SS = ss;
enable();
if(key==4) {
/* ripristina le ISR originali e libera la memoria */
setvect(8, old_int8);
setvect(9, old_key);
setvect(0x28, old_int28);
setvect(0x64, old_int64);
freemem(_psp);
/* libera il blocco usato dall'applicazione */
} else key = 0;
}
/********************************************************************/
/* Funzioni di applicazione della finestra pop-up
*/
/* Calcolatore a quattro operatori basato sul sistema RPN */
/********************************************************************/
#define MAX 100
int *p;
/* puntatore allo stack */
int *tos;
/* punta alla cima dello stack */
int *bos;
/* punta alla coda dello stack */
int stack[MAX];
void calc(void)
{ int answer, a, b;
char in[80], out[80];
MS-DOS
um 59 di 138
p = stack;
tos = p;
bos = p+MAX-1;
tsrwindow(1);
do {
tsrwindow_xy(1, 0, 0);
tsrwindow_cleol(1);
tsrwindow_puts(1, ": ");
/* prompt del calcolatore */
tsrwindow_gets(1, in);
tsrwindow_puts(1, "\n");
tsrwindow_cleol(1);
switch(*in) {
case '+': a = pop();
b = pop();
answer = a+b;
push(a+b);
break;
case '-': a = pop();
b = pop();
answer = b-a;
push(b-a);
break;
case '*': a = pop();
b = pop();
answer = b*a;
push(b*a);
break;
case '/': a = pop();
b=pop();
if(a==0) {
tsrwindow_puts(0,"Divisione per 0.\n");
break;
}
answer = b/a;
push(b/a);
break;
default: push(atoi(in));
continue;
}
itoa(answer, out, 10);
tsrwindow_puts(1, out);
} while(*in);
tsrdeactive(1);
}
/* aggiunge un numero allo stack, restituisce 1 se l’operazione
ha successo, altrimenti restituisce 0 */
push(int i)
{ if(p>bos)
return (0);
*p=i;
p++;
return (1);
}
/* toglie dallo stack l’ultimo elemento inserito, restituisce 0
MS-DOS
um 60 di 138
se nello stack non vi è alcun elemento */
pop(void)
{ p--;
if(p<tos) {
p++;
return (0);
}
return (*p);
}
/*********************************************************/
/* Blocco appunti di tipo pop-up
*/
/*********************************************************/
#define MAX_NOTE 10
char notes[MAX_NOTE][80];
void notepad(void)
{ static first=1;
register int i, j, k;
union inkey {
char ch[2];
int i;
} c;
char ch;
/* inizializza gli appunti, se necessario */
if(first) {
for(i=0; i<MAX_NOTE; i++)
*notes[i] = '\0';
first = !first;
}
tsrwindow(0);
/* visualizza gli appunti esistenti */
for(i=0; i<MAX_NOTE; i++) {
if(*notes[i])
tsrwindow_puts(0, notes[i]);
tsrwindow_putchar(0, '\n');
}
tsrwindow_xy(0, 0, 0);
for(i=0;;) {
c.i = readkey();
/* legge il tasto */
if(tolower(c.ch[0])==27) {
/* ESC per uscire */
tsrdeactive(0);
break;
}
/* se si tratta di un tasto normale */
if(isprint(c.ch[0]) || c.ch[0]=='\b') {
tsrwindow_cleol(0);
notes[i][0] = c.ch[0];
j = 1;
tsrwindow_putchar(0, notes[i][0]);
do {
ch = tsrwindow_getche(0);
if(ch=='\b') {
if(j>0) {
j--;
tsrwindow_bksp(0);
MS-DOS
um 61 di 138
}
}
else {
notes[i][j] = ch;
j++;
}
} while(notes[i][j-1]!='\r');
notes[i][j-1] = '\0';
if(i<MAX_NOTE-1)
i++;
tsrwindow_putchar(0, '\n');
}
else {
/* se si tratta di un tasto speciale */
switch(c.ch[1]) {
case 72:
/* freccia in su */
if(i>0) {
i--;
tsrwindow_upline(0);
}
break;
case 80:
/* freccia in giu */
if(i<MAX_NOTE-1) {
i++;
tsrwindow_downline(0);
}
break;
case 63:
/* F5: cancella il blocco appunti */
tsrwindow_cls(0);
for(k=0; k<MAX_NOTE; k++)
*notes[k] = '\0';
tsrwindow_xy(0, 0, 0);
}
}
}
}
/*****************************************************************/
/* semplice funzione che rende criptico il contenuto di un file, codifica
semplicemente ciascun byte del file effettuandone il complemento,
quindi per decodificare e’ sufficiente effettuare ancora una codifica,
infatti il complemento del complemento di un byte e’ il byte stesso, la
parte di codifica del file e’ piccola, ciò che rende complesso è
il fatto che il tutto deve avvenire all’interno del TSR. */
void code(void)
{ int fd, num;
char ch, fname[80], far *old_dta;
long sk;
old_dta = getdta();
/* memorizza la vecchia DTA */
setdta(MK_FP(_psp, 0x80));
/* costruisce la nuova DTA */
tsrwindow(2);tsrwindow_xy(2, 0, 0);
tsrwindow_puts(2, "Inserire il nome del file: ");
tsrwindow_gets(2, fname);
if((fd = _open(fname, O_RDWR)) < 0) {
tsrwindow_xy(2, 0, 0);
tsrwindow_cleol(2);
MS-DOS
um 62 di 138
tsrwindow_puts(2, "File non apribile. Premere un tasto.\n");
tsrwindow_getche(2);
tsrdeactive(2);
setdta(old_dta);
/* ripristina la vecchia DTA */
return;
}
num = 1;
/* non si possono usare le routine standard ANSI C per l’I/O perché le
function come fopen(), fread(), fwrite() non usano il sistema di
allocazione dinamica della memoria utile in un TSR */
for(sk = 0; num==1 ; sk++) {
lseek(fd, sk, SEEK_SET);
num = _read(fd, &ch, 1);
ch = ~ch;
/* effettua il complemento di ogni byte */
lseek(fd, sk, SEEK_SET);
if(num==1) _write(fd, &ch , 1);
};
_close(fd);
tsrdeactive(2);
setdta(old_dta);
/* ripristina la vecchia DTA */
}
/* FUNZIONI DI FINESTRA: visualizza una finestra pull-down */
void tsrwindow(int num)
/* numero di finestra */
{ if(!frame[num].active) {
/* non correntemente utilizzata */
save_video(num);
/* memorizza lo schermo corrente */
frame[num].active=1;
}
/* imposta il flag allo stato attivo */
if(frame[num].border) tsrdraw_border(num);
tsrdisplay_header(num);
/* visualizza la finestra */
}
/* costruisce una struttura per una finestra pull-down, è restituito 1 se la
struttura può’ essere costruita, altrimenti è restituito 0 */
make_tsrwindow(
int num,
/* numero di finestra*/
char *header,
/* titolo della finestra */
int startx, int starty,
/* coordinate dell’angolo in alto a sinistra */
int endx, int endy,
/* coordinate dell’angolo in basso a destra */
int border
/* se vale 0 non vi e’ alcun bordo */
)
{ if(num>MAX_FRAME) {
tsrwindow_puts(0, "Troppe finestre.\n");
return (0);
}
if((startx>78) || (startx<0) || (starty>24) || (starty<0)) {
tsrwindow_puts(0, "Errore dimensionale.");
return (0);
}
if((endx>79) || (endy>25)) {
tsrwindow_puts(0, "La finestra non ci sta.");
return (0);
}
/* costruisce la struttura */
frame[num].startx = startx;
frame[num].endx = endx;
MS-DOS
um 63 di 138
frame[num].starty = starty;
frame[num].endy = endy;
frame[num].p = wp;
frame[num].header = header;
frame[num].border = border;
frame[num].active = 0;
frame[num].curx = 0;
frame[num].cury = 0;
return (1);
}
/* disattiva una finestra e la elimina dallo schermo */
void tsrdeactive(int num)
{ /* riposiziona il cursore nell’angolo in alto a sinistra */
frame[num].curx = 0;
frame[num].cury = 0;
frame[num].active = 0;
restore_video(num);
}
/* visualizza il titolo della finestra nell’apposita posizione */
void tsrdisplay_header(int num)
{ register int x, len; x = frame[num].startx;
/* calcola la corretta posizione per centrare il titolo della finestra, se il
valore risultante e’ negativo il titolo non ci sta all’interno della finestra */
len = strlen(frame[num].header);
len = (frame[num].endx - x - len) / 2;
if(len<0)
return;
/* non lo visualizza */
x = x +len;
write_string(x, frame[num].starty,frame[num].header, NORM_VID);
}
/* disegna un bordo intorno alla finestra */
void tsrdraw_border(int num)
{ register int i;
char far *v, far *t;
v = vid_mem;
t = v;
for(i=frame[num].starty+1; i<frame[num].endy; i++) {
v += (i*160) + frame[num].startx*2;
*v++ = 179;
*v = NORM_VID;
v = t;v += (i*160) + frame[num].endx*2;
*v++ = 179;
*v = NORM_VID;
v = t;
}
for(i=frame[num].startx+1; i<frame[num].endx; i++) {
v += (frame[num].starty*160) + i*2;
*v++ = 196;
*v = NORM_VID;
v = t;
v += (frame[num].endy*160) + i*2;
*v++ = 196;
*v = NORM_VID;v = t; }
/* disegna gli angoli del bordo */
MS-DOS
um 64 di 138
write_char(frame[num].startx, frame[num].starty, 218, NORM_VID);
write_char(frame[num].startx, frame[num].endy, 192, NORM_VID);
write_char(frame[num].endx, frame[num].starty, 191, NORM_VID);
write_char(frame[num].endx, frame[num].endy, 217, NORM_VID);
}
/* scrive una stringa nella posizione corrente del cursore nella finestra
specificata, restituisce 0 se la finestra non e’ attiva, altrimenti restituisce 1 */
tsrwindow_puts(int num, char *str)
{ /* verifica che la finestra sia attiva */
if(!frame[num].active)
return (0);
for( ; *str; str++) tsrwindow_putchar(num, *str);
return (1);
}
/* scrive un carattere nella posizione corrente del cursore all’interno della
finestra specificata, restituisce 0 se la finestra non e’ attiva,
altrimenti restituisce 1 */
tsrwindow_putchar(int num, char ch)
{ int x, y;
char far *v;
/* verifica che la finestra sia attiva */
if(!frame[num].active)
return (0);
x = frame[num].curx + frame[num].startx + 1;
y = frame[num].cury + frame[num].starty + 1;
v = vid_mem;
v += (y*160) + x*2;
/* calcola l’indirizzo */
if(y>=frame[num].endy)
return (1);
if(x>=frame[num].endx)
return (1);
if(ch=='\n') {
/* carattere di newline */
y++;
x = frame[num].startx+1;
v = vid_mem;
v += (y*160) + x*2;
/* calcola l’indirizzo */
frame[num].cury++;
/* incrementa la Y */
frame[num].curx = 0;
/* azzera la X */
}
else {
frame[num].curx++;
*v++ = ch;
/* scrive il carattere */
*v++ = NORM_VID;
/* attributo video normale */
} tsrwindow_xy(num, frame[num].curx, frame[num].cury);
return (1);
}
/* posiziona il cursore in una finestra alla locazione specificata, restituisce 0
se e’ fuori dai limiti, altrimenti restituisce un valore diverso da 0 */
tsrwindow_xy(int num, int x, int y)
{ if(x<0 || x+frame[num].startx>=frame[num].endx-1)
return (0);
if(y<0 || y+frame[num].starty>=frame[num].endy-1)
return (0);
frame[num].curx = x;
MS-DOS
um 65 di 138
frame[num].cury = y;
goto_xy(frame[num].startx+x+1, frame[num].starty+y+1);
return (1);
}
/* legge una stringa da una finestra */
void tsrwindow_gets(int num, char *s)
{ char ch, *temp;temp = s;
for(;;) {
ch = tsrwindow_getche(num);
switch(ch) {
case '\r':
/* è stato premuto il tasto INVIO */
*s = '\0';return;
case '\b':
/* tasto di cancellazione */
if(s>temp) {
s--;
frame[num].curx--;
if(frame[num].curx<0)
frame[num].curx = 0;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
write_char(frame[num].startx+ frame[num].curx+1,
frame[num].starty+frame[num].cury+1, ' ', NORM_VID);
}
break;
default: *s = ch;
s++;
}
}
}
/* input di dati all’interno di una finestra, restituisce il codice di scansione a 16 bit */
tsrwindow_getche(int num)
{ union inkey {
char ch[2];
int i;
} c;
if(!frame[num].active)
return 0;
/* la finestra non e’ attiva */
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
c.i = readkey();
/* legge il tasto */
if(c.ch[0]) {
switch(c.ch[0]) {
case '\r':
/* è stato premuto il tasto INVIO */
break;
case '\b':
/* tasto di cancellazione */
break;
default:
if(frame[num].cury+frame[num].starty < frame[num].endy-1) {
write_char(frame[num].startx+frame[num].curx+1,
frame[num].starty+frame[num].cury+1, c.ch[0], NORM_VID);
frame[num].curx++;
}
}
if(frame[num].curx < 0)
frame[num].curx = 0;
if(frame[num].curx+frame[num].startx > frame[num].endx-2)
MS-DOS
um 66 di 138
frame[num].curx--;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
}
return (c.i);
}
/* cancella fino al termine della linea */
void tsrwindow_cleol(int num)
{ register int i, x, y;
x = frame[num].curx;
y = frame[num].cury;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
for(i=frame[num].curx; i<frame[num].endx-1; i++)
tsrwindow_putchar(num,' ');
tsrwindow_xy(num, x, y);
}
/* cancella una finestra */
void tsrwindow_cls(int num)
{ register int i, j;
char far *v;
for(i=frame[num].starty+1; i<frame[num].endy; i++)
for(j=frame[num].startx+1; j<frame[num].endx; j++) {
v = vid_mem;
v += (i*160) + j*2;
*v++ = ' ';
/* scrive uno spazio */
*v++ = NORM_VID;
}
frame[num].curx = 0;
frame[num].cury = 0;
}
/* muove il cursore di una linea verso l’alto, restituisce un valore
diverso da 0 se l’operazione riesce, altrimenti restituisce 0 */
tsrwindow_upline(int num)
{ if(frame[num].cury > 0) {
frame[num].cury--;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
return (1);
}
return (0);
}
/* muove il cursore di una linea verso il basso, restituisce un valore
diverso da 0 se l’operazione riesce, altrimenti restituisce 0 */
tsrwindow_downline(int num)
{ if(frame[num].cury < frame[num].endy-frame[num].starty-1) {
frame[num].cury++;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
return (1);
}
return (1);
}
/* torna indietro di un carattere */
void tsrwindow_bksp(int num)
{ if(frame[num].curx>0) {
frame[num].curx--;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
MS-DOS
um 67 di 138
tsrwindow_putchar(num, ' ');
frame[num].curx--;
tsrwindow_xy(num, frame[num].curx, frame[num].cury);
}
}
/*********************************************************/
/* Funzioni video di basso livello
*/
/**************************************** ****************/
/* visualizza una stringa con l’attributo specificato */
void write_string(int x, int y, char *p, int attrib)
{ char far *v;
v = vid_mem;
v += (y*160) + x*2;
/* calcola l’indirizzo */
for(; *p; ) {
*v++ = *p++;
/* scrive il carattere */
*v++ = attrib;
/* scrive l’attributo */
}
}
/* scrive un carattere con l’attributo specificato */
void write_char(int x, int y, char ch, int attrib)
{ char far *v;
v = vid_mem;
v += (y*160) + x*2;
*v++ = ch;
/* scrive il carattere */
*v = attrib;
/* scrive l’attributo */
}
/* memorizza una porzione dello schermo */
void save_video(int num)
{ register int i,j;
char *buf_ptr, far *v, far *t;
buf_ptr = frame[num].p;
v = vid_mem;
for(i=frame[num].startx; i<frame[num].endx+1; i++)
for(j=frame[num].starty; j<frame[num].endy+1; j++) {
t = (v + (j*160) + i*2);
*buf_ptr++ = *t++;
*buf_ptr++ = *t;
*(t-1) = ' ';
}
/* cancella la finestra */
}
/* ripristina una porzione dello schermo */
void restore_video(int num)
{ register int i,j;
char far *v, far *t, *buf_ptr;
buf_ptr = frame[num].p;
v = vid_mem;
t = v;
for(i=frame[num].startx; i<frame[num].endx+1; i++)
for(j=frame[num].starty; j<frame[num].endy+1; j++) {
v = t;
v += (j*160) + i*2;
*v++ = *buf_ptr++;
/* scrive il carattere */
*v = *buf_ptr++;
}
/* scrive l’attributo */
MS-DOS
um 68 di 138
frame[num].active = 0;
/* restore_video */
}
/* restituisce il modo video corrente */
video_mode(void)
{ union REGS r;
r.h.ah = 15;
/* prende il modo video */
return int86(0x10, &r, &r) & 255;
}
/* restituisce il codice a 16 bit della scansione di tastiera */
readkey(void)
{ union REGS r;
r.h.ah = 0;
return int86(0x16, &r, &r);
}
/* posiziona il cursore alle coordinate X,Y specificate */
void goto_xy(int x, int y)
{ union REGS r;
r.h.ah = 2;
/* funzione di indirizzamento cursore */
r.h.dl = x;
/* coordinata colonna */
r.h.dh = y;
/* coordinata riga */
r.h.bh = 0;
/* pagina video */
int86(0x10, &r, &r);
}
/* dispone il puntatore vid_mem alla partenza della memoria video */
void set_vid_mem(void)
{ int vmode = video_mode();
if((vmode!=2) && (vmode!=3) && (vmode!=7)) {
printf("Il modo video dev’essere testo a 80 colonne.");
exit(1);
}
/* determina l’indirizzo appropriato della RAM video */
if(vmode==7)
vid_mem = (char far *) MK_FP(0xB000, 0000);
else
vid_mem = (char far *) MK_FP(0xB800, 0000);
}
/* legge e memorizza le coordinate del cursore */
void cursor_pos(void)
{ union REGS i, o
;i.h.bh = 0;
i.h.ah = 3;
int86(16, &i, &o);
old_row = o.h.dh;
old_col = o.h.dl;
}
MS-DOS
um 69 di 138
MEMORIA
memoria convenzionAle
Da 0 a (640 KB - 1), dato che MS-DOS gestisce direttamente la memoria convenzionale,
non è necessario un gestore di memoria aggiuntivo per l’utilizzo di questo tipo di memoria.
Tutte le applicazioni richiedono memoria convenzionale.
HMA (HIGH MEMORY area)
Da 1 M a 1 M + (64 KB - 16) (10FFEFH), occupa i primi 64 KB di memoria estesa.
Lo schema d’indirizzamento introduce anche un insolito cavillo che è usato da MS-DOS: i
registri del segmento con valori tra F001H e FFFFH hanno una parte dei loro segmenti
che si trova prima di 1 MB.
Per esempio, con CS uguale a F001H, un salto a FFF4H va all’indirizzo 100004H, quattro
byte prima dell’inizio della memoria.
Allo stesso modo, con DS uguale a FFFFH, un’istruzione che prova a caricare il byte a
FFFFH farà riferimento all’indirizzo 10FFFFH, che equivale a 1 MB + 65519.
I 65520 byte tra 100000H e 10FFEFH sono chiamati HMA; sull’8088, l’H/W ignora il 21simo bit (A0..A19) per cui gli indirizzi sono mappati da zero a 65519.
Sull’80286 e le CPU successive, il loro comportamento dipende da come è collegato il
piedino dell’indirizzo A20 sulla CPU; se esso è collegato per funzionare come gli altri
piedini, si può usare come memoria HMA e lo stesso MS-DOS vi può risiedere, ma, se
esso è messo a terra, forzato a 0, allora tutti gli indirizzi tra 100000H e 10FFFFH saranno
compresi tra 00000H e FFFFFH.
Per essere pienamente compatibile con l’8088, il piedino deve essere messo a terra
perché qualche S/W furbo può generare indirizzi sopra 1MB aspettandosi che questi
saranno nascosti tra gli indirizzi bassi.
In teoria, sull’8088 l’indirizzo 10004H è un sinonimo legale di 4, wrap around, ma la sua
legalità non sottintende, comunque, che sia una buona pratica di programmazione.
L’indirizzo più alto cui si può accedere con questo meccanismo è dato da FFFFH:FFFFH
ovvero, 10FFEFH, pertanto anche se ufficialmente l’HMA impegna 64 KB, in realtà non ne
sono utilizzabili gli ultimi 16 byte.
Il venditore di H/W, allora, è di fronte ad una scelta: o abilitare HMA e in tal modo
permettere a MS-DOS di girare sopra 1 MB, liberando 64 KB di memoria convenzionale o
rendere compatibile l’8088.
Il gestore è HIMEM.SYS, MS-DOS gestisce questa area con il comando DOS = HIGH.
Le funzioni dello standard XMS (Extended Memory System)
INT 2FH
4300H
Check XMS installation.
INT 2FH
4310H
Get XMS driver entry point.
INT 2FH
00H
Get XMS version number.
INT 2FH
01H
Request high memory area.
INT 2FH
02H
Release high memory area.
INT 2FH
03H
Global enable A20.
INT 2FH
04H
Global disable A20.
INT 2FH
05H
Local enable A20.
INT 2FH
06H
Local disable A20.
INT 2FH
07H
Query A20 line.
INT 2FH
8H
Query free extended memory.
INT 2FH
9H
Allocate extended memory block.
INT 2FH
AH
Release extended memory block.
MS-DOS
um 70 di 138
INT 2FH
INT 2FH
INT 2FH
INT 2FH
INT 2FH
INT 2FH
INT 2FH
BH
CH
DH
EH
FH
0H
1H
Move extended memory block.
Lock extended memory block.
Unlock extended memory block.
Get handle information.
Reallocate extended memory block.
Request upper memory block.
Release upper memory block.
I codici di errore delle chiamate al driver XMM (eXtended Memory Manager)
AX = 0001H
Nessun errore.
AX = 0000H
Errore, codice in BL.
80H
Funzione sconosciuta.
82H
Errore sulla linea A20.
8EH
Errore generale di XMM.
90H
HMA non disponibile.
91H
HMA già occupata.
A0H
Non c’è XMS libera.
A9H
Errore di parità.
AAH
UMB non bloccato.
B1H
Nessun UMB disponibile.
La verifica della presenza di XMS avviene tramite l’int 2FH: basta chiamarlo con AX
uguale a 4300H e verificare se in uscita risulta AL uguale a 80H.
In caso affermativo esiste nel PC un driver XMS, detto XMM.
Posto in AX 4310H e ripetuta la chiamata all’int 2FH, si ottiene in ES:BX l’indirizzo del
driver XMM, contrariamente ad altri servizi offerti nel PC, questo driver si chiama
direttamente con una CALL e non indirettamente tramite interrupt.
L’applicazione principale EXTMEM.C utilizza il modulo EXTMEM.H.
Dopo aver verificato la presenza di XMS e aver ottenuto l’indirizzo del driver XMM, il
programma controlla l’ammontare di XMS presente, nonché, tenuto conto degli EMB
(Extended Memory Block) già allocati da parte di altre applicazioni, la massima grandezza
che può essere assegnata ad un nuovo eventuale EMB.
Poiché i blocchi di EMB sono spostabili, (s)bloccabili e di dimensione variabile, può
accadere che l’XMS sia frammentata in più parti e che pertanto non sia possibile allocare
in un solo EMB il totale dello spazio ancora disponibile.
Si passa quindi, se c’è XMS libera, al tentativo di allocare un EMB da 64 KB.
Nel caso l’operazione riesca si mostrano se e quali blocchi EMB siano correntemente
allocati nella XMS, nonché il numero di handle ancora disponibili per la creazione di nuovi
blocchi, quindi si libera l’EMB ora utilizzato.
L’applicazione prosegue verificando lo stato della linea A20; ma non basta, occorre anche
che la linea sia abilitata.
Quindi si mostra il contenuto della word agli indirizzi, 0000:0000 e FFFF:0010 equivale a
10000:0000.
In generale i due valori, in quanto contenuto di due diverse locazioni di memoria, saranno
differenti, infine si controlla se è libera od occupata la HMA.
File EXTMEM.H
#include <dos.h>
#include <stdio.h>
#define XMS_INT
#define ASK_XMS
#define XMS_ADR
#define XMS_VER
#define XMS_USE_HMA
MS-DOS
0x2f
0x4300
0x4310
0x00
0x01
um 71 di 138
#define XMS_FREE_HMA
0x02
#define XMS_GLOBAL_A20_ON
0x03
#define XMS_GLOBAL_A20_OFF
0x04
#define XMS_LOCAL_A20_ON
0x05
#define XMS_LOCAL_A20_OFF
0x06
#define XMS_STATUS_A20
0x07
#define XMS_SIZE
0x08
#define XMS_ALLOC_EMB
0x09
#define XMS_FREE_EMB
0x0A
#define XMS_MEMCOPY
0x0B
#define XMS_LOCK_EMB
0x0C
#define XMS_UNLOCK_EMB
0x0D
#define XMS_INFO_EMB
0x0E
#define XMS_MODIFY_EMB
0x0F
#define XMS_ALLOC_UMB
0x10
#define XMS_FREE_UMB
0x11
#define XMS_NO_ERR
0x0001
typedef far (*LPFN) (void);
typedef struct {
unsigned a, b;
} XMS_DAT;
typedef struct {
unsigned a, b, c, d;
} XMS_INFO;
LPFN XMM_entry;
int Is_XMS(LPFN *);
XMS_DAT XMS_VerRev(void);
XMS_DAT XMS_GetSize(void);
XMS_DAT XMS_EMB_Alloc(unsigned);
XMS_INFO XMS_EMB_Info(unsigned);
unsigned XMS_Generic(char, unsigned);
int Is_XMS(LPFN *p)
{ struct REGPACK reg;
reg.r_ax = ASK_XMS;
intr(XMS_INT, &reg);
if ((reg.r_ax & 0x00ff) != 0x80)
return(0);
/* non trovo XMS driver */
reg.r_ax = XMS_ADR;
intr(XMS_INT, &reg);
*p = XMM_entry = (LPFN) MK_FP(reg.r_es, reg.r_bx);
return(1);
}
XMS_DAT XMS_VerRev(void)
{ int i,j;
XMS_DAT VerRev;
if (XMM_entry) {
asm mov ah,XMS_VER;
asm call XMM_entry;
asm mov i,ax;
/* numero di Versione */
asm mov j,bx;
/* numero di Revisione */
}
else {
puts("\nCall to XMS_VR, w/o XMM-entry setup!\007\n");
exit(2);
MS-DOS
um 72 di 138
}
VerRev.a =i;
VerRev.b =j;
return(VerRev);
}
XMS_DAT XMS_GetSize(void)
{ int i,j;
XMS_DAT Size;
if (XMM_entry) {
asm mov ah,XMS_SIZE;
asm call XMM_entry;
asm mov i,dx;
/* quantità di memoria XMS totale */
asm mov j,ax;
/* max EMB allocabile */
}
else {
puts("\nCall to XMS_GetSize, w/o XMM_entry setup!\007\n");
exit(XMS_SIZE);
}
Size.a = i;
Size.b = j;
return(Size);
}
XMS_DAT XMS_EMB_Alloc(unsigned Size)
{ int i = Size, j, k;
XMS_DAT Handle;
if (XMM_entry) {
asm mov ah,XMS_ALLOC_EMB;
asm mov dx,i;
asm call XMM_entry;
asm mov i,dx;
/* handle */
asm mov j,ax;
/* codoce errore */
asm mov bh,0
asm mov k,bx;
}
else {
puts("\nCall to XMS_EMB_Alloc, w/o XMM_entry setup!\007\n");
exit(XMS_ALLOC_EMB);
}
Handle.a = i;
Handle.b = (j ? 0 : k);
return(Handle);
}
XMS_INFO XMS_EMB_Info(unsigned Handle)
{ unsigned i = Handle, j;
unsigned char k, l;
XMS_INFO Info;
if (XMM_entry) {
asm mov ah,XMS_INFO_EMB;
asm mov dx,i;
asm call XMM_entry;
asm mov i,dx;
/* size (oppure 0 se errore) */
asm mov j,ax;
/* codice errore */
asm mov k,bh;
asm mov l,bl;
MS-DOS
um 73 di 138
}
else {
puts("\nCall to XMS_EMB_Info w/o XMM_entry setup!\007\n");
exit(XMS_INFO_EMB);
}
Info.a = i;
Info.b = (i ? 0 : 1);
Info.c = k;
Info.d = l;
return(Info);
}
unsigned XMS_Generic(char XMS_Id, unsigned Parm)
{ char i = XMS_Id;
unsigned j = Parm, k = 0;
if (XMM_entry) {
asm mov ah,i;
asm mov dx,j;
asm call XMM_entry;
asm mov j,ax;
asm mov bh,0
asm mov k,bx;
}
else {
puts("\nCall to XMS_Generic, w/o XMM_entry setup!\007\n");
exit(XMS_Id);
}
if (j == XMS_NO_ERR)
k = 0;
return(k);
}
File EXTMEM.C
#include <stdio.h>
#include <conio.h>
#include <process.h>
#include “extmem.h”
#define EMB_SIZE 64
#define HMA_SIZE 64
int main(void)
{ unsigned i,j;
float v, r;
LPFN lpfn_XMS;
XMS_DAT XMS_Ver, XMS_Size, XMS_EMB;
XMS_INFO XMS_EMBs;
clrscr();
if (!Is_XMS(&lpfn_XMS)) {
puts("\nNon c’e' memoria XMS (e relativo driver XMM)!\007\n");
exit(1);
}
puts("\nVerificata la presenza di memoria XMS e relativo driver XMM.");
XMS_Ver = XMS_VerRev();
v = (XMS_Ver.a >> 8) + (XMS_Ver.a & 0x00ff) * 0.01;
r = (XMS_Ver.b >> 8) + (XMS_Ver.b & 0x00ff) * 0.01;
printf("Versione XMM
: %.2f (Revisione: %.2f)\n", v, r);
MS-DOS
um 74 di 138
XMS_Size = XMS_GetSize();
printf("Memoria XMS presente : %5u KB\n", XMS_Size.a);
printf("Max EMB allocabile : %5u KB (meno HMA_SIZE)\n", XMS_Size.b);
if (((int)XMS_Size.a - HMA_SIZE) >= EMB_SIZE) {
XMS_EMB = XMS_EMB_Alloc(EMB_SIZE);
if (XMS_EMB.b)
printf("\n\007Errore %#x in XMS_ALLOC_EMB\n");
else {
printf("\nAllocazione EMB da %u KB ok. Handle #%u\n",EMB_SIZE,
XMS_EMB.a);
for (i=1; i<=XMS_EMB.a; i++) {
XMS_EMBs = XMS_EMB_Info(i);
printf("\nInfo su EMB #%u : ",i);
if (XMS_EMBs.b)
printf("(errore %#x)");
else {
printf("%5u KB %s", XMS_EMBs.a,(XMS_EMBs.c ? "(locked)" : ""));
if (i == XMS_EMB.a)
j = XMS_EMBs.d;
}
}
printf("\nDisponibili ancora : %5u handle XMS\n", j);
i = XMS_Generic(XMS_FREE_EMB, XMS_EMB.a);
if (i)
printf("\n\007\Errore %#x in XMS_FREE_EMB\n");
else
printf("\nDeallocazione EMB da %u KB ok!\n", EMB_SIZE);
}
}
i = XMS_Generic(XMS_STATUS_A20, 0);
printf("\nStato linea A20: %s\n", i ? "off" : "On");
if (i && XMS_Generic(XMS_GLOBAL_A20_ON,0))
printf("\007Impossibile attivare linea A20!!\n");
else {
puts("I prossimi due valori dovrebbero differire: ");
printf("Contenuto 0000:0000 : %5u\n", *(unsigned far *)MK_FP(0x00,0x00));
printf("Contenuto FFFF:0010 : %5u ", *(unsigned far *)MK_FP(0xffff,0x10));
printf(" (FFFF:0010 = 10000:0000)\n");
}
i = XMS_Generic(XMS_USE_HMA, 0xffff);
switch(1) {
case 0: puts("\nHMA allocata ok");
i = XMS_Generic(XMS_FREE_HMA, 0);
if (i)
puts("Errore deallocazione HMA!\007");
else
puts("HMA deallocazione ok");
break;
case 0x90: puts("\nNon c’e' HMA in questo PC!");
break;
case 0x91: puts("\nHigh Memory Area : in uso.");
break;
default: printf("\nErrore %#x, dopo XMS_USE_HMA\007", i);
}
MS-DOS
um 75 di 138
getch(); return(0);
}
xms
Da 1 MB a 16 MB - 1 per 80286, da 1 MB a 4 GB - 1 per 80386.
MS-DOS opera in real mode, la memoria estesa è accessibile solo in protected mode.
L’utilizzo di memoria estesa implica che il programmatore si è avvalso di strumenti
chiamati DOS EXTENDER, il che significa semplicemente l’introduzione di una serie di
nuove problematiche.
Un sistema chiamato DOS EXTENDER sostituisce completamente una serie di chiamate
a MS-DOS legate strettamente alla gestione della memoria.
In pratica, per utilizzare tutta la memoria presente in un PC è necessario riscrivere alcune
funzioni del SO.
Anche strumenti quali linker, compilatori, librerie delle funzioni di run-time e naturalmente
anche debugger e profiler devono essere in grado di operare con un particolare DOS
EXTENDER.
Anche Windows contiene le funzioni base per operare con XMS, alla precisa condizione
che le applicazioni siano appositamente create per operare nell’ambiente grafico.
La nuova serie di funzionalità introdotte con un DOS EXTENDER, ovvero l’insieme di
routine che sostituiscono parti di MS-DOS per ampliare le caratteristiche del SO, sono
divise in standard riconosciuti in base alle modalità di accesso che sono previste.
VCPI (Virtual Control Program Interface)
Introdotto dalla società DeskView, creatrice di un sistema multitasking che per operare
necessitava di più memoria, il sistema si è rapidamente diffuso per la serie di strumenti
che la stessa DeskView poneva a disposizione.
DPMI (DOS Protected Mode Interface)
La versione di Windows 3.0 introduceva, tra le varie novità, un sistema nuovo per la
gestione della memoria estesa, lo standard VCPI era reso di fatto obsoleto dal rilascio del
gestore di XMS chiamato HIMEM.SYS.
In pratica tra l’applicazione, che opera in protected mode e MS-DOS si pongono le routine
del DPMI.
Alcune metodologie di accesso alla memoria, in particolare per quanto riguarda la grafica,
devono essere profondamente ridefinite per operare opportunamente in protected mode.
La grafica, in un sistema che utilizza un DOS EXTENDER, implica che la CPU debba
passare dal real mode, ovvero in una modalità di accesso secondo MS-DOS, in protected
mode, questa fase di passaggio, effettuata ogniqualvolta sia necessario riferirsi a servizi
DOS indispensabili introduce un tempo di ritardo.
Le funzioni dello standard DPMI
INT 2FH
1686H
Get CPU mode.
INT 2FH
168AH
Get API entry point.
INT 31H
0100H
Allocate DOS memory block.
INT 31H
0101H
Release DOS memory block.
INT 31H
0200H
Get real mode interrupt vector.
INT 31H
0201H
Set real mode interrupt vector.
INT 31H
0204H
Get protected mode interrupt vector.
INT 31H
0205H
Set protected mode interrupt vector.
INT 31H
0400H
Get DPMI version.
uma (Upper memory area)
Da 640 KB a (1MB - 1), inizialmente era riservata per l’H/W del sistema, ad esempio la
MS-DOS
um 76 di 138
RAM video, le ROM BASIC e altre funzioni d’I/O.
Sopra i 640 KB non era presente alcuna RAM ordinaria, così il SO, i driver di dispositivo e
tutte le applicazioni utente e i dati erano limitati alla memoria convenzionale di 640 KB.
A posteriori, la divisione dello spazio degli indirizzi dell’8088 nella memoria convenzionale
di 640 KB e la UMA di 384 KB fu un errore.
I dispositivi d’I/O non necessitano molto dello spazio degli indirizzi, mentre le applicazioni
ne hanno maggiormente bisogno, così una divisione di 832 KB per le applicazioni e 192
KB per i dispositivi d’I/O sarebbe stata una scelta migliore.
Essa attualmente non può essere modificata perché esistono migliaia di schede d’I/O per il
PC, molte delle quali mettono le ROM e le RAM specializzate su indirizzi sparsi
dappertutto sull’UMA.
Anche se molti PC hanno da 200 KB a 300 KB di spazio d’indirizzi non utilizzato, chiamati
UMB (Upper Memory Block) nella memoria superiore, gli indirizzi esatti che sono liberi
variano da macchina a macchina; inoltre essi non sono blocchi contigui, bensì un insieme
di buchi tra le schede d’I/O.
A dispetto di tutte queste complicazioni, partendo con la versione 5.0 di MS-DOS, la
Microsoft decise di permettere all’80386 e alle CPU superiori di usare questo spazio degli
indirizzi mappando parti della memoria estesa nei buchi.
Allora, ad esempio, se una particolare macchina non ha dispositivi d’I/O, ROM o RAM
video agli indirizzi da 640 KB a 704 KB, da 768 KB a 800 KB e da 896 KB a 960 KB, può
fare in modo che MS-DOS mappi 160 KB della sua memoria estesa in queste celle,
usandole come RAM; per quanto riguarda la CPU, tutta la memoria che rientra in 1 M è
trattata allo stesso modo.
Fu l’IBM a decidere di allocare 384 KB superiori all’I/O creando una barriera a 640 KB.
Il mappare la memoria estesa nelle celle in UMA è solo un tentativo di eliminare alcuni
danni.
L’area superiore della memoria è disponibile solo per le applicazioni dall’80386 in avanti
poiché le CPU più piccole non hanno paginazione H/W e non possono mappare
fisicamente la memoria estesa negli indirizzi virtuali nell’intervallo da 640 KB a 1 MB.
Quando MS-DOS parte, legge il file CONFIG.SYS in cui l’utente può specificare che lo
stesso MS-DOS può essere sistemato in HMA invece che in memoria convenzionale; è
possibile anche specificare che i driver di dispositivo e i TSR si devono tenere nell’area
superiore della memoria con il comando DOS = UMB.
Tutto ciò ha l’effetto di liberare un po’ di memoria in più all’interno del limite di 640 KB.
Per gli utenti che hanno molti buffer, molti driver di dispositivo e molti TSR, portare tutto
nella parte superiore della memoria, compreso MS-DOS, può significare liberare una
considerevole parte della memoria convenzionale per le applicazioni utente.
Il gestore di memoria superiore è EMM386.EXE.
Overlay
Il bisogno di più di 640 KB di spazio degli indirizzi è anteriore all’80286; a quel tempo si
rivelò necessaria una soluzione compatibile con l’8088.
La soluzione S/W che fornisce MS-DOS consiste in una chiamata di sistema che permette
ad un’applicazione in esecuzione di caricare un file COM o EXE, chiamato overlay, nella
memoria e poi riprendere il controllo.
L’applicazione chiamante poi invoca una procedura di overlay e, quando questo ha finito,
può deallocare la memoria di overlay e continuare; è libero di caricare questo e, in un
secondo momento, altri overlay.
In questo modo è possibile avere un numero di applicazioni, arbitrariamente grandi, che
può essere contenuto in una quantità di memoria relativamente piccola, ma con sufficiente
spazio su disco.
La parola overlay significa letteralmente sovrapposto.
MS-DOS
um 77 di 138
Funzionamento
Si carica in memoria l’applicazione principale, chiamata root overlay, essa contiene il
codice per controllare il meccanismo di overlay, infatti nessun grosso aiuto è dato dal SO e
può contenere anche tabelle e strutture di dati condivise.
Poco tempo dopo essere partito, l’overlay di radice fa una chiamata al sistema che carica
l’overlay di passo uno; a caricamento completato esso può chiamare la procedura
principale nel passo uno usando l’istruzione di chiamata di procedura, eventualmente con
passaggio dei parametri.
Il passo uno gira e mette le informazioni nelle tabelle che si trovano nella root overlay.
Al momento in cui esso termina, la procedura principale del passo uno restituisce il
controllo al suo chiamante nella root overlay.
A questo punto può richiedere il caricamento del passo due e quindi chiamarlo.
Il passo due può leggere le informazioni che il passo uno ha messo nelle tabelle della root
overlay.
Se ne deduce che il meccanismo di overlay rende più facile la condivisione
dell’informazione tra i differenti blocchi dell’applicazione: molte applicazioni di grande
dimensione di MS-DOS usano questo meccanismo.
VROOMM (Virtual Runtime Object Oriented Memory Manager)
La Borland per il linguaggio C++ sotto MS-DOS, ha rilasciato questa tecnologia di gestione
degli overlay, sviluppata inizialmente per uso interno e implementata in Reflex 2.0 e
successivamente in Quattro.
Permette di definire una zona di memoria variabile, non fissa, per il caricamento delle
differenti parti di funzioni poste in overlay, possiede routine per il controllo del caricamento
dei moduli di overlay.
Questi controlli permettono di verificare quali sono i moduli più utilizzati e di effettuare
calcoli sulla memoria disponibile durante l’esecuzione per mantenere sempre in memoria,
quando possibile, i moduli più utilizzati.
Memoria virtuale
Le applicazioni Windows non utilizzano gli overlay, in quanto questi ultimi riserverebbero in
modo esclusivo alcune aree di memoria, mentre la memoria è un bene comune, posto a
disposizione di tutte le applicazioni attive, usano la memoria virtuale.
Questa tecnica permette di accogliere richieste di utilizzo di RAM superiori alla quantità
fisica presente.
In questo caso è il gestore della memoria che effettua automaticamente uno scarico dei
dati, appoggiandosi sull’hard disk, fornendo l’illusione alle applicazioni di avere una
quantità di memoria superiore di quella reale.
La memoria gestita con tecniche di memoria virtuale, può essere utilizzata sia per caricare
MS-DOS
um 78 di 138
applicazioni, sia dalle applicazioni stesse quando necessitano di ulteriore memoria per
eseguire elaborazioni complesse che richiedono la presenza di grosse quantità di dati.
Un particolare di estrema importanza è che le routine per la gestione degli overlay sono
parte integrante dell’applicazione, contrariamente alle routine di gestione di memoria
virtuale che sono incorporate nel SO e operano in modo trasparente a favore di tutte le
applicazioni.
Possono essere posti in overlay sia variabili, dinamiche e statiche, sia routine oggetti e
quindi metodi.
La scelta delle funzioni da porre in overlay dipende semplicemente dalle esigenze, per
esempio la funzione che visualizza la videata di presentazione contenente il nome
dell’applicazione e del suo creatore è una prima indicazione.
Questo perché non è utilizzata durante l’esecuzione dell’applicazione, ma solamente
all’inizio.
I moduli di overlay possono essere posti in memoria espansa, estesa e caricati o scaricati
da disco secondo il bisogno.
Per utilizzare gli overlay secondo il metodo proposto con il gestore VROOMM è
necessario attivare alcune opzioni del compilatore.
O/A/Dos Overlay
O/C/C/Model Large
O/C/E/Dos Overlay
O/L/S/Overlaid DOS EXE
MS-DOS
um 79 di 138
Esempio, il file Project chiamato VROOMM.PRJ, include quattro file sorgenti.
Il primo di essi è l’applicazione principale MAIN.CPP e tre sono i moduli da porre in
overlay chiamati rispettivamente 10VL.CPP, 20VL.CPP e 30VL.CPP.
// Funzione: applicazione principale dell’esempio di uso degli overlay, main.cpp
// Note:
l’applicazione fa parte del progetto VROOMM.PRJ non può funzionare se
// eseguito dall’interno dell’ambiente integrato !!
#include <stdio.h>
#include <conio.h>
void ciao1(void);
void ciao2(void);
void ciao3(void);
int main(void)
{ clrscr();
ciao1();
// richiamo della funzione ciao1
ciao2();
// richiamo della funzione ciao2
ciao3();
// richiamo della funzione ciao3
return (0);
}
// Funzione: prima parte dell’applicazione da porre in overlay, 10vl.cpp
// Note:
l’applicazione fa parte del progetto VROOMM.PRJ
#include <stdio.h>
void ciao1(void)
{ printf(“%s”,”Ciao 1\n”);}
// Funzione: seconda parte dell’applicazione da porre in overlay, 20vl.cpp
// Note:
l’applicazione fa parte del progetto VROOMM.PRJ
#include <stdio.h>
void ciao2 (void)
{ printf(“%s”,”Ciao 2\n”);}
// Funzione: terza parte dell’applicazione da porre in overlay, 30vl.cpp
// Note:
l’applicazione fa parte del progetto VROOMM.PRJ
#include <stdio.h>
void ciao3 (void)
{ printf(“%s”,”Ciao 3\n”);}
MS-DOS
um 80 di 138
È complesso comprendere se un modulo è stato inserito correttamente nella gestione di
overlay o meno, l’uso del TurboProfiler permette di controllare con esattezza, mediante
l’opzione View/Overlay, quali sono i moduli che sono posti sotto tale gestione,
indicandone anche le dimensioni del codice.
Un fatto molto importante, da sottolineare, è che l’utilizzo di routine contenute in moduli
posti nell’area di overlay e di conseguenza il loro caricamento da disco se necessario, è
gestito automaticamente dall’overlay manager di BorlandC e non è necessario indicare
nulla al gestore di overlay inserendo, come in altri linguaggi, particolari istruzioni specifiche
da parte del programmatore.
L’uso di overlay è tipico di applicazioni professionali, nelle quali uno dei requisiti principali
è la possibilità che qualsiasi utente, con qualsivoglia configurazione di PC e memoria,
possa utilizzare con completezza l’applicazione fornitogli.
Perché il modo di operare del gestore di overlay è comunque ottimizzato.
Ad esempio, è chiaro che se la memoria a disposizione degli overlay, in una certa
configurazione di PC, è sufficientemente grande, allora il gestore di overlay caricherà tutti i
moduli in memoria.
Cosa porre in overlay
Come utilizzare al meglio le caratteristiche fornite dal gestore VROOMM.
1. È possibile impostare quanta memoria lasciare al gestore di overlay utilizzando in
modo opportuno la variabile di ambiente _ovrbuffer; per esempio, per definire uno
spazio di overlay di 128 KB e la definizione da effettuare è la seguente:
unsigned _ovrbuffer = 0x2000; non c’è un numero magico di dimensione della
memoria.
2. Porre in overlay parti di applicazioni tra loro indipendenti; ad esempio, in un foglio
elettronico la gestione dei calcoli matematici e la visualizzazione dei grafici sono due
moduli candidati ideali per essere posti in overlay.
Cosa non porre in overlay
1. Gestioni particolari che ridefiniscono i vettori d’interrupt per il controllo di alcune
funzioni di SO o funzioni legate strettamente a tempi di esecuzione non è opportuno
che siano poste sotto il controllo di un gestore di overlay, per quanto sofisticato possa
essere.
2. Evitare di porre in overlay parti che devono essere utilizzate da più moduli; in questo
caso l’overlay, contenente fondamentali routine, sarebbe continuamente caricato e
scaricato dal disco, influenzando negativamente le prestazioni di tutta l’applicazione.
Ems (Expanded memory system)
L’overlay funziona in maniera adeguata per applicazioni che sono formate da grosse
quantità di codice che gira sequenzialmente, come i compilatori; essi funzionano meno
bene quando un’applicazione ha bisogno di operare su una grossa struttura dati che non
entra nello spazio degli indirizzi di 64 KB.
Tre ditte, la Lotus, la INTEL e la Microsoft si misero insieme e idearono uno schema H/W
detto memoria espansa con il quale una grande quantità di memoria si sarebbe potuta
montare e usare sull’8088.
La Lotus modificò il suo foglio elettronico 1-2-3 per poterlo usare, la Microsoft adeguò MSDOS per poterlo supportare e l’INTEL costruì una scheda speciale di memoria e il driver
MS-DOS
um 81 di 138
S/W relativo.
Anche se le CPU 80286, 80386 in avanti non necessitavano di memoria espansa, poiché
questa ormai esisteva, MS-DOS è fatto per supportarla e molte applicazioni la usano.
Infatti, dalle macchine 386 in poi una parte di EMS è usata di solito per riempire le celle
nella HMA e quello che rimane spesso è usato per simulare la memoria espansa.
Questo schema sviluppato da tre industrie è stato standardizzato ed è conosciuto come
LIM EMS (Lotus INTEL Microsoft Expanded Memory System), la versione 4.0 è quella che
implementa migliori tecniche per velocizzare l’accesso alla memoria.
L’idea di base di EMS è una vecchia tecnica chiamata commutazione di banco, bank
switching.
Lo spazio degli indirizzi di 1 MB del PC è diviso in 64 pagine ognuna di 16 KB.
La memoria, 32 MB è divisa in porzioni di 2048 pagine da 16 KB ognuna.
16 KB = 16384 byte = offset della pagina 14 bit.
64 KB = 4 pagine da 16 KB = indirizzo delle pagine nel segmento 2 bit.
32 MB = 512 segmenti = indirizzo dei segmenti 9 bit.
Indirizzo lungo 25 bit
L’H/W speciale sulla scheda della memoria espansa mappa le 64 pagine virtuali in un
insieme arbitrario di porzioni fisiche di memoria.
Sebbene assomigli molto ad una paginazione ordinaria in effetti non lo è; infatti è
esattamente l’opposto.
Con la paginazione, il problema consiste nel fatto che non c’è sufficiente memoria fisica
per mantenere uno spazio degli indirizzi virtuali per cui è necessario il mapping.
Per esempio, un’applicazione sul 386 potrebbe avere bisogno di 64 MB di memoria
mentre la macchina ne ha solo 16 MB; quello che fa la paginazione è assegnare una parte
dei 64 MB di disco per mantenere l’immagine intera e poi portarlo in pagine individuali così
come sono usate.
Il problema che l’EMS prova a risolvere è quello di inserire grosse applicazioni e strutture
dati in uno spazio degli indirizzi virtuali di 640 KB.
Si supponga che un’applicazione stia facendo un calcolo su una matrice 1000X1000 di
numeri in virgola mobile.
Anche se la macchina ha gli 8 MB necessari di memoria fisica, non vi è modo d’indirizzarli,
perché l’8088 non può generare indirizzi sopra 1 MB e quelli tra 640 KB e 1 MB sono
riservati per i dispositivi d’I/O.
L’effetto del S/W EMS è quello di permettere alle applicazioni di mappare una parte della
memoria fisica nella porzione da 512 KB a 640 KB (page frame) e lavorare su di essa; ad
esecuzione terminata essa è liberata e l’applicazione ve ne mappa un’altra parte. Al
contrario della paginazione, che è trasparente, la memoria espansa è completamente
visibile al programmatore o al più al compilatore o al suo sistema.
Nulla avviene in modo automatico; dopotutto, per elaborare l’array di 8 MB, l’intero vettore
dovrà essere eventualmente mappato nella page frame, un pezzo alla volta.
Solo l’applicazione o il compilatore sanno di quale parte hanno bisogno in ogni momento.
Su un 386 o più, che hanno l’H/W di paginazione, le pagine possono essere mappate dalla
memoria estesa in un posto qualsiasi dello spazio degli indirizzi, per cui, su queste
macchine, la memoria estesa si può usare per simulare la memoria espansa senza H/W
speciale.
Il gestore è EMM386.EXE, dato però che il gestore di EMS consente l’accesso solo a una
quantità limitata di EMS alla volta, l’utilizzo risulta più lento rispetto a XMS.
Per rendere possibile alle applicazioni di mappare e liberare la memoria in modo
indipendente dal fatto che si usi la memoria estesa o quella espansa, EMS standard
definisce le chiamate di sistema che le applicazioni possono fare e che il sistema può
supportare, per mezzo di un driver di dispositivo per la memoria.
Probabilmente sarebbe stato sufficiente fornire le quattro chiamate di sistema, ALLOCATE
MEMORY (43H), RELEASE MEMORY (45H), SAVE PAGE MAP (47H) e RESTORE
MS-DOS
um 82 di 138
PAGE MAP (48H), ma i progettisti di EMS definirono quasi 40 chiamate di sistema.
Inoltre, le precedenti 4 sono chiamate per chiedere tutti i tipi d’informazione di stato,
quante pagine sono libere?
La manipolazione della mappa, salva e ripristina una mappa di pagina e lo switch del
contesto.
L’ultimo è utile per le applicazioni tipo DOSSHELL e Windows, in cui molte applicazioni
possono girare contemporaneamente, ognuna con il suo insieme di pagine.
Il SO, per esempio, può allocare per i suoi scopi da 0 a 128 KB, poi allocare una parte dei
512 KB per l’applicazione 1, una seconda parte dei 512 KB per l’applicazione 2 e così via.
Quando l’applicazione 1 sta girando, la sua parte di memoria espansa è mappata nello
spazio degli indirizzi da 128 KB a 640 KB, ma quando è effettuato lo switch del contesto,
l’applicazione 1 è mappata fuori e un’altra applicazione è mappata al suo posto.
Disco RAM
Quando è ancora disponibile memoria estesa, poiché MS-DOS non permette che le
applicazioni girino su di essa ad eccezione di quando simulano la memoria espansa, la si
può usare per un disco RAM nella memoria RAM del sistema per simulare un’unità disco.
Tali dischi sono molto veloci perché le informazioni in essi contenute sono sempre in
memoria, per contro però sono temporanei nel senso che quando il PC non è alimentato i
dati memorizzati sono persi.
Memoria cache
Si usa una parte di RAM come cache per migliorare le prestazioni del disco.
Mappa di memoria del PC
DEC
0K
(640 - 1) K
640 K
(704 - 1) K
704 K
736 K
(768 - 1) K
768 K
800 K
(832 - 1) K
832 K
(896 - 1) K
896 K
(960 - 1) K
960 K
(1024 - 1) K
1024 K
(1088 - 1) K
1088 K
............
MS-DOS
HEX
000000
09FFFF
0A0000
0AFFFF
0B0000
0B8000
0BFFFF
0C0000
0C8000
0CFFFF
0D0000
0DFFFF
0E0000
0EFFFF
0F0000
0FFFFF
100000
10FFFF
110000
............
DESCRIZIONE
Memoria convenzionale.
Segmenti da 0 a 9.
VGA (Video Graphics Array) Graphics.
Buffer video monocromatico, oppure 32K di UMB
Buffer video colori.
VGA ROM.
32K di UMB.
64K di UMB.
ROM BASIC IBM, oppure EMS PAGE FRAME,
oppure 64K di UMB.
BIOS ROM.
HMA.
XMS.
um 83 di 138
Il comando MEM visualizza informazioni sulla quantità di memoria disponibile sia
convenzionale sia superiore.
Il comando MEM /F (Free) visualizza informazioni sulla quantità di memoria disponibile sia
convenzionale sia superiore.
Memoria convenzionale libera:
Segmento Totale
0124B
304 (0K)
0125E
88.992 (87K)
02818
491.120 (480K)
Spazio libero tot.: 580.416 (567K)
Memoria superiore disponibile:
Regione
Maggiore disp.
Totale disp. Dimensione tot.
1
0 (0K)
0 (0K)
158.480 (155K)
Il comando MEM /C (Classify) classifica le applicazioni secondo la memoria occupata.
Moduli che utilizzano memoria al di sotto di 1 MB:
Nome
Totale
=
Convenzionale
MSDOS
16.221 (16K)
16.221 (16K)
HIMEM
1.168 (1K)
1.168 (1K)
EMM386
3.120 (3K)
3.120 (3K)
COMMAND 5.056 (5K)
5.056 (5K)
win386
14.192 (14K)
13.008 (13K)
VSHIELD
51.696 (50K)
1.808 (2K)
DOSKEY
4.144 (4K)
4.144 (4K)
MOUSE
16.240 (16K)
16.096 (16K)
KEYB
6.944 (7K)
6.944 (7K)
WIN
2.096 (2K)
2.096 (2K)
COMMAND 5.296 (5K)
5.296 (5K)
ANSI
4.208 (4K)
0 (0K)
SBCD
11.584 (11K)
0 (0K)
IFSHLP
3.936 (4K)
0 (0K)
SMARTDRV 28.928 (28K)
0 (0K)
MS-DOS
Memoria superiore
0 (0K)
0 (0K)
0 (0K)
0 (0K)
1.184 (1K)
49.888 (49K)
0 (0K)
144 (0K)
0 (0K)
0 (0K)
0 (0K)
4.208 (4K)
11.584 (11K)
3.936 (4K)
28.928 (28K)
um 84 di 138
SHARE
17.920 (18K)
0 (0K)
17.920 (18K)
MSCDEX
40.688 (40K)
0 (0K)
40.688 (40K)
Libera
580.112 (567K)
580.112 (567K)
0 (0K)
Riepilogo della memoria:
Tipo di memoria
Totale =
Usata +
Libera
Convenzionale
655.360
75.248
580.112
Superiore
158.480
158.480
0
Riservato
393.216
393.216
0
Estesa (XMS)
7.181.552 6.132.976 1.048.576
memoria totale
8.388.608 6.759.920 1.628.688
Tot. inf. a 1 MB
813.840
233.728
580.112
Dim. massima di un programma eseguibile
580.096 (567K)
Dim. massima di un blocco libero di memoria superiore
0 (0K)
MS-DOS è residente nell’area di memoria alta.
Il comando MEM /D (Debug) visualizza lo stato di tutti i moduli di memoria, dei driver e
altre informazioni.
Informazioni sulla memoria convenzionale:
Segmento
Totale
Nome
Tipo
00000
1.039 (1K)
Vettore d’interruzione
00040
271 (0K)
Area per le comunicazioni ROM
00050
527 (1K)
Area per le comunicazioni DOS
00070
2.656 (3K) IO
Dati di sistema
CON
Driver periferiche di sistema
AUX
Driver periferiche di sistema
PRN
Driver periferiche di sistema
CLOCK$
Driver periferiche di sistema
A: - C:
Driver periferiche di sistema
COM1
Driver periferiche di sistema
LPT1
Driver periferiche di sistema
LPT2
Driver periferiche di sistema
LPT3
Driver periferiche di sistema
COM2
Driver periferiche di sistema
COM3
Driver periferiche di sistema
COM4
Driver periferiche di sistema
00116
5.072 (5K) MSDOS
Dati di sistema
00253
10.880 (11K) IO
Dati di sistema
1.152 (1K) XMSXXXX0 Periferica installata=HIMEM
3.104 (3K)
$MMXXXX0
Periferica
installata=EMM386
2.080 (2K) FILES=40
256 (0K) FCBS=4
512 (1K) BUFFERS=10
624 (1K)
LASTDRIVE=G
3.024 (3K) STACKS=9,256
004FB
80 (0K)
MSDOS
Programma di sistema
00500
64 (0K)
COMMAND Dati
00504
2.928 (3K)
COMMAND Programma
005BB
80 (0K) win386
Dati
005C0
2.064 (2K)
COMMAND Ambiente
00641
1.808 (2K)
VSHIELD
Programma
006B2
4.144 (4K)
DOSKEY
Programma
007B5
16.096 (16K)
MOUSE
Programma
MS-DOS
um 85 di 138
00BA3
6.944 (7K)
KEYB
Programma
00D55
288 (0K)
WIN
Ambiente
00D67
1.808 (2K)
WIN
Programma
00DD8
304 (0K)
win386
Ambiente
00DEB
12.624 (12K)
win386
Programma
01100
304 (0K)
COMMAND Dati
01113
2.928 (3K)
COMMAND Programma
011CA
2.064 (2K)
COMMAND Ambiente
0124B
304 (0K)
MEM
Ambiente
0125E
88.992 (87K)
MEM
Programma
02818
491.120 (480K)
MSDOS
- Libera -Informazioni sulla memoria superiore:
Segmento Regione
Totale
Nome
Tipo
0C952
1
19.680 (19K)
IO
Dati di sistema
4.192 (4K)
CON
Periferica installata=ANSI
11.568 (11K)
MSCD001 Periferica installata=SBCD
3.856 (4K)
IFS$HLP$ Periferica installata=IFSHLP
0CE20
1
144 (0K)
MOUSE
Ambiente
0CE29
1
28.928 (28K)
SMARTDRV Programma
0D539
1
49.888 (49K)
VSHIELD
Dati
0E167
1
17.920 (18K)
SHARE
Programma
0E5C7
1
40.688 (40K)
MSCDEX
Programma
0EFB6
1
1.184 (1K)
win386
Dati
Riepilogo della memoria:
Tipo di memoria
Totale =
Usata +
Libera
Convenzionale
655.360
75.248
580.112
Superiore
158.480
158.480
0
Riservato
393.216
393.216
0
Estesa (XMS)
7.181.552 6.132.976 1.048.576
memoria totale
8.388.608 6.759.920 1.628.688
Tot. inf. a 1 MB
813.840
233.728
580.112
Memoria accessibile utilizzando Int 15h
0 (0K)
Dim. massima di un programma eseguibile
580.096 (567K)
Dim. massima di un blocco libero di memoria superiore
0 (0K)
MS-DOS è residente nell’area di memoria alta.
XMS versione 2.00; driver versione 2.05
Implementazione della gestione della memoria
Così come MS-DOS evita di avere una tabella centrale dei processi tenendo traccia dei
processi per mezzo della catena dei PSP, esso usa lo stesso schema per la gestione della
memoria.
MS-DOS tiene traccia di tutti i blocchi contenuti nella memoria, sia di quelli liberi sia di
quelli allocati.
Questa operazione è eseguita verificando il contenuto di appositi blocchi di controllo, detti
MCB (Memory Control Block) che precedono qualsiasi blocco libero o allocato di memoria.
La verifica dell’MCB consente di determinare il tipo, la dimensione e le applicazioni
contenute nel singolo blocco, tra quelli in cui è suddivisa la memoria del sistema e cui
l’MCB considerato si riferisce.
L’MCB ha dimensioni pari a 16 byte, un paragrafo, ma solo i primi 5 sono utilizzati.
 1 byte = tipo di blocco: 4DH blocco in lista, 5AH fine lista.
 2, 3 byte = contiene il PID, 0000H libero; un valore diverso da 0 indica che la zona di
memoria specificata dall’MCB è allocata al PID.
 4, 5 byte = dimensione del blocco in paragrafi escluso MCB.
MS-DOS
um 86 di 138
Esempio.
0A00:0000
4D
0008
1600
0A01:0000
blocchi allocati di proprietà del PID 0008
Indirizzo successivo: 0A00+1600+1=2001
2001:0000
4D
0113
0010
2002:0000
blocchi allocati di proprietà del PID 0113
Indirizzo successivo: 2001+0010+1=2012
2012:0000
5A
0000
7AEC
2013:0000
blocchi liberi
Tecnicamente, gli MCB non formano una lista concatenata perché le intestazioni
contengono le dimensioni piuttosto che i puntatori, ma l’effetto che si ottiene è lo stesso.
Quando MS-DOS deve allocare la memoria, per caricare un processo figlio o un overlay, o
per soddisfare una chiamata di sistema 48H di un’applicazione, esamina la catena di
blocchi partendo dalla fine finché non trova un blocco sufficientemente grande.
Se l’MCB scelto è troppo grande, se ne prende una parte e si crea un nuovo MCB per
rappresentare la parte lasciata.
Quando la memoria è liberata, gli MCB adiacenti liberi non sono messi insieme perché la
catena di blocchi non è una lista concatenata doppia.
La fusione dei blocchi avviene in un secondo momento quando la ricerca attraverso la
catena parte dall’inizio.
Come conseguenza di questo metodo di gestione della memoria un’applicazione con
tabelle dinamiche, che costantemente alloca e libera memoria è probabile che possegga
pezzi di memoria sparsi dappertutto nello spazio degli indirizzi; ciò è in contrasto con il
modello Unix di un singolo segmento di dati che può crescere o restringersi come e
quando è necessario.
Di fatto la differenza è più piccola di quanto sembra poiché poche applicazioni Unix usano
direttamente la chiamata di sistema brk.
La maggior parte usa le funzioni del linguaggio C: malloc, free e realloc che hanno lo
stesso effetto delle chiamate di sistema di MS-DOS.
La differenza reale è che, in MS-DOS, il SO mantiene la lista libera, mentre, in Unix, essa
è mantenuta a due livelli.
Il SO tiene traccia dei blocchi di memoria allocati e deallocati e malloc gestisce il
contenuto dei segmenti dati.
Sebbene lo schema di MCB funzioni per la memoria UMA; esso non funziona per la XMS,
è quindi necessario installare uno o più driver di memoria estesa.
MS-DOS non prevede né la paginazione né lo swap, se un processo tenta di allocare la
memoria e non c’è nessuna parte di essa libera o se un processo tenta di fare una fork e
non vi è sufficiente memoria in cui inserire il figlio, la chiamata di sistema restituisce
semplicemente un codice di errore; il ripristino è lasciato completamente al chiamante.
chiamate di sistema
Le chiamate di sistema per la gestione della memoria in MS-DOS sono più complicate di
quelle in Unix, permettono alle applicazioni di allocare, liberare e ridimensionare i blocchi
di memoria.
Nell’allocare la memoria MS-DOS usa un algoritmo del tipo first fit o best fit, il primo che
può essere contenuto o quello che può essere contenuto nel modo migliore.
Serve anche indirettamente a controllare quanta memoria è ancora disponibile, se non
riesce a soddisfare una richiesta restituisce un codice di errore.
È quindi sufficiente presentare una richiesta per l’intera memoria indirizzabile FFFFH
paragrafi, che ovviamente non può essere soddisfatta, per avere in BX il numero dei
MS-DOS
um 87 di 138
paragrafi non ancora allocati.
FUNZIONE 48H
Descrizione
Categoria
Input
Output
ALLOCATED MEMORY
Alloca memoria.
Gestione memoria.
AX = 48H
BX = numero dei paragrafi o blocchi di memoria richiesti.
AX = pointer al segmento iniziale del blocco allocato.
BX = dimensione del maggiore dei blocchi a disposizione.
FUNZIONE 49H
Descrizione
Categoria
Input
RELEASE ALLOCATED MEMORY
Rilascia memoria.
Gestione memoria.
AX = 49H
ES = pointer al segmento da rilasciare.
FUNZIONE 4AH
Descrizione
Categoria
Input
MODIFY ALLOCATED MEMORY (SET BLOCK)
Modifica la memoria allocata.
Gestione memoria.
AX = 4AH
ES = pointer al segmento che va modificato
BX = nuova dimensione richiesta.
BX = numero massimo di blocchi liberi.
Output
File MEMTEST.ASM
Serve a dimostrare praticamente il funzionamento delle funzioni di allocazione memoria;
controlla lo spazio a disposizione, dopodiché riduce la memoria a propria disposizione a
100H 256 paragrafi, 4 KB, inizia quindi a richiedere ciclicamente blocchi di 1000H 4096
paragrafi, 64 KB alla volta, presentando sullo schermo il pointer all’area di volta in volta
allocata.
L’esecuzione dell’applicazione s’interrompe quando un errore segnala che non vi è più
memoria disponibile.
Normalmente quando un’applicazione è caricata le è allocata tutta la memoria disponibile,
spetta all’applicazione stessa ridurre autonomamente la memoria che le è stata assegnata
e restituire un certo numero di paragrafi al SO, se questo procedimento può non avere
importanza in sistemi sui quali è eseguita una sola applicazione alla volta, in sistemi
multitasking è molto importante che i processi rinuncino a possedere memoria della quale
non hanno bisogno.
STACKSEG SEGMENT PARA STACK ‘STACK’
DB
200H DUP (?)
STACKSEG ENDS
DISP_STRING MACRO STR
;presentazione stringa sul video
MOV AX,SEG STR
MOV DS,AX
MOV DX,OFFSET STR
;DS:DX punta a STR
MOV AH,09H
INT 21H
ENDM
CONV_TO_ASCII MACRO INP_BYTE ;conversione in ascii del byte d’ingresso
LOCAL CONT_1,CONT_2
;risultato in AX
MOV AL,INP_BYTE
MOV AH,INP_BYTE
AND AL,0FH
;mascheramento parte superiore
ADD AL,30H
;conversione ascii
CMP AL,39H
;char <=9?
MS-DOS
um 88 di 138
JBE CONT_1
;char ascii tra 0..9
ADD AL,7H
;char ascii tra A..F
CONT_1:
AND AH,0F0H
;mascheramento parte inferiore
MOV CL,4H
;spostamento a destra del
SHR AH,CL
;char in AH
ADD AH,30H
CMP AH,39H
JBE CONT_2
ADD AH,7H
CONT_2:
NOP
ENDM
DISP_RESULT MACRO STR,RES
;presentazione di una parola come risultato in
STR[28]
MOV BX,RES
PUSH BX
CONV_TO_ASCII BH
MOV STR[28],AH
;primo char in STR
MOV STR[29],AL
;secondo char in STR
POP BX
CONV_TO_ASCII BL
MOV STR[30],AH
;terzo char in STR
MOV STR[31],AL
;quarto char in STR
DISP_STRING STR
ENDM
DATA SEGMENT WORD ‘DATA’
OUTSTR
DB “PROGRAMMA MEMTEST CONTROLLO MEMORIA “,13,10,”$”
MSG1
DB “NUMERO DI BLOCCHI RICHIESTI:
“,13,10,”$”
MSG2
DB “NUMERO BLOCCHI DISPONIBILI:
“,13,10,”$”
MSG3
DB “RIDUZIONE A BLOCCHI:
“,13,10,”$”
MSG4
DB “INDIRIZZO SEGMENTO (DA AX ):
“,13,10,”$”
ERR_7
DB “ERRORE (7) NEI BLOCCHI DI CONTROLLO
“,13,10,”$”
ERR_8
DB “ERRORE (8) MEMORIA INSUFFICIENTE
“,13,10,”$”
ERR_9
DB “ERRORE (9) SEGMENTO ERRATO
“,13,10,”$”
REQ_M DW 0
;memoria richiesta
FREE_M DW 0
;memoria disponibile
NEW_S DW 0
;pointer ad un nuovo segmento
DATA ENDS
CSEG SEGMENT WORD ‘CSEG’
ASSUME CS:CSEG,DS:DATA,SS:STACKSEG
BEGIN:
MOV BX,DATA
MOV DS,BX
DISP_STRING OUTSTR
CHECK_MEMORY:
;controllo memoria disponibile
MOV REQ_M,0FFFFH
;prima richiesta di memoria
DISP_RESULT MSG1,REQ_M
MOV AH,4AH
;funzione dos set_block ES punta al PSP di MEMTEST
MOV BX,REQ_M
;BX = numero di blocchi
INT 21H
MOV FREE_M,BX
;memoria libera in BX
DISP_RESULT MSG2,FREE_M ;presentazione primo risultato
REDUCE_MEMORY:
;riduzione con set_block della memoria allocata
MS-DOS
um 89 di 138
MOV REQ_M,100H
DISP_RESULT MSG3,REQ_M
MOV AH,4AH
MOV BX,REQ_M
INT 21H
JNC REQUEST_MEMORY
JMP SHOW_ERROR
REQUEST_MEMORY:
MOV REQ_M,1000H
DISP_RESULT MSG1,REQ_M
MOV AH,48H
MOV BX,REQ_M
INT 21H
JC SHOW_ERROR
MOV NEW_S,AX
DISP_RESULT MSG4,NEW_S
JMP REQUEST_MEMORY
disponibile
SHOW_ERROR:
CMP AX,7
JNE ERROR_8
DISP_STRING ERR_7
JMP END_PROCESS
ERROR_8:
CMP AX,8
JNE ERROR_9
DISP_STRING ERR_8
JMP END_PROCESS
ERROR_9:
DISP_STRING ERR_9
END_PROCESS:
MOV AL,0
MOV AH,4CH
INT 21H
CSEG ENDS
END BEGIN
MS-DOS
;256 paragrafi = 4Kbyte
;continuazione se non ci sono errori nel CF = 0
;richiesta nuovo blocco di memoria
;4096 paragrafi = 64Kbyte
;funzione dos allocate_memory
;BX = numeri di blocchi
;uscita in caso di errore CF = 1
;AX = indirizzo segmento libero
;presentazione segmento
;il ciclo procede fino a quando c’è memoria
;presentazione casi di errore
;AX = codice di errore
;errore nei blocchi controllo
;memoria insufficiente
;segmento errato
um 90 di 138
Si può vedere chiaramente che i pointer alle aree assegnate si trovano precisamente a
1001H paragrafi di distanza, dove il paragrafo aggiuntivo è quello contenente l’MCB.
MS-DOS
um 91 di 138
FILE SYSTEM
Introduzione
La versione originale 1.0 di MS-DOS fu modellata a somiglianza del CP/M, che
comprendeva una sola cartella e l’uso di FCB (File Control Block), blocchi di controllo per
effettuare l’I/O e sono state mantenute nelle versioni successive per motivi di compatibilità.
La versione 2.0 aveva in più un file system gerarchico con i descrittori di file e le chiamate
di sistema, erano usate come in Unix.
Le chiamate usate dal CP/M non furono più usate ed erano considerate obsolete; le nuove
applicazioni scritte in questa versione non potevano più utilizzarle.
Dalla versione due sono disponibili nuove funzioni generiche d’I/O basate su handle
(identificatori) dei file, tecnica più moderna che riproduce il metodo usato da Unix.
L’handle di un file è una word, 16 bit, contenente un numero unico che serve da
identificatore.
Per creare oppure aprire un file, un’applicazione passa a MS-DOS un pathname e un
attributo da assegnare al file stesso.
MS-DOS associa ad esso un handle usato per tutte le successive manipolazioni del file,
che ha il primo numero libero, normalmente si possono aprire fino ad un massimo di N
handle, di cui i primi 5 sono predefiniti.
Tutti i parametri di servizio relativi al file posizione fisica, modo di accesso, protezioni,
sono registrati in una struttura dati riservata; le operazioni sul file fanno riferimento a
questa struttura tramite l’handle.
Una novità derivata da Unix è il trattare periferiche d’I/O come se fossero file sequenziali.
In MS-DOS sono predefiniti 5 di tali file; essi sono sempre aperti e associati ai seguenti
handle.
 0 standard input, tastiera, può essere ridirezionato da (<).
 1 standard output, schermo, può essere ridirezionato da (>).
 2 standard error, è sempre lo schermo.
 3 AUX uscita ausiliaria.
 4 PRN stampante.
Punti di paragone tra il file system di MS-DOS e quello di Unix.
CARATTERISTICHE
Sistema con directory gerarchiche.
Directory corrente.
Pathname assoluti e relativi.
Directory (.) e (..)
File speciali a caratteri.
File speciali a blocchi.
Lunghezza dei nomi dei file.
Separatore nei nomi.
“a” equivale ad “A”.
Proprietari, gruppi, protezione.
Concatenazioni (link).
File system montati.
Attributi di file.
Unix
Si
Si
Si
Si
Si
Si
14 o 255
/
No
Si
Si
Si
No
MS-DOS
Si
Si
Si
Si
Si
Si
8+3
\
Si
No
No
No
Si
Entrambi i sistemi permettono alla cartella radice di avere delle sotto cartelle e ognuna di
queste può avere a sua volta altre sotto cartelle arrivando ad un livello qualsiasi; in
entrambe sussiste il concetto di cartella di lavoro, i pathname relativi e quelli assoluti.
MS-DOS
um 92 di 138
Entrambi i sistemi usano i nomi (.) e (..) per la cartella corrente e per quella genitore e
supportano file speciali di caratteri per terminali, stampanti e altri dispositivi seriali e i file
speciali di blocchi per i dischi.
Nonostante queste affinità, tra i due sistemi ci sono, comunque, delle differenze.
I nomi dei file di Unix sono di 14 o 255 caratteri, a seconda della versione in uso, i nomi
dei file MS-DOS hanno una parte di base di 8 caratteri, seguita opzionalmente da
un’estensione che inizia sempre con un punto e contiene da 1 a 3 caratteri.
 BAT, file batch.
 SYS, driver di dispositivo.
 COM, file binario eseguibile formato da un solo segmento.
 EXE, file binario eseguibile formato da più segmenti con intestazione.
 OBJ, file oggetto prodotto da un compilatore.
 TXT, file testo in formato ASCII.
 DOC, file documento realizzato con un word processor.
In entrambi i casi, i nomi dei file sono formati da qualsiasi carattere legale.
Un’altra differenza per chi usa entrambi i sistemi è l’uso di (/) come componente
separatore in Unix e l’uso di (\) per la stessa funzione in MS-DOS.
La ragione di questa differenza è collegata all’utilizzo iniziale di MS-DOS di (/x) al posto di
(- x) nella shell per passare il flag (x) ad un’applicazione, un altro fossile del CP/M.
Poiché i flag sono analizzati dall’applicazione stessa, non solo dalla shell, alcune
applicazioni lo fanno secondo il metodo Unix.
Un’altra differenza è che per la shell di Unix “ABC”, “Abc” e “abc” sono file che non hanno
alcuna relazione tra loro; per la shell di MS-DOS, invece, rappresentano lo stesso file,
inoltre, in Unix ci sono proprietari, gruppi, protezione e file system montati mentre niente di
tutto ciò è presente in MS-DOS.
Una caratteristica che ha MS-DOS è la presenza di solo 4 attributi.
1. Readonly, il file non può essere modificato.
2. Archive, il file è stato modificato nell’ultima archiviazione.
3. System, il file system non può essere cancellato dal comando DEL.
4. Hidden, il file non è elencato dal comando DIR.
Il supportare molteplici dischi ma non avere l’operazione di mount crea un problema: come
fa il sistema a sapere su quale disco si trova il file?
È necessario fornire, oltre al nome del file, il nome del dispositivo, (A:) per il primo floppy,
(B:) per il secondo e (C:) per il primo hard disk.
chiamate di sistema
Le chiamate CREATE, OPEN, CLOSE, READ e WRITE in C hanno le stesse funzioni di
quelle di Unix; le differenze sono le seguenti.
1. Qualcuno decise di scrivere in questo caso CREATE con la “E”.
2. Al posto della modalità di protezione sono forniti i 4 bit di attributi.
Infatti, la chiamata successiva è LSEEK, leggermente mascherata dalla divisione
dell’offset del file in due word al posto di passarlo come un tutt’uno sebbene le librerie
d’interfaccia del C ne accettino uno completo e poi lo convertano in due più corti.
Le operazioni di rename e delete in C sono ovvie e in Unix corrispondono alle chiamate
rename e unlink, rispettivamente.
La chiamata get/set date/time in C non è realmente una chiamata di sistema.
La chiamata di sistema attuale prende la data e l’ora e la inserisce in registri differenti;
poiché le funzioni C non possono accettare come risultato due valori, la maggior parte
delle librerie e il compilatore dividono queste chiamate in due funzioni.
L’altra, non mostrata, prende l’ora in cui il file è stato modificato l’ultima volta; si noti che
queste chiamate sono necessarie poiché non esiste una chiamata STAT.
La chiamata get current directory in C è identica a quella in Unix, tranne per il fatto che
specifica quale dispositivo è coinvolto; in Unix ciò non è necessario.
MS-DOS
um 93 di 138
FUNZIONE 3CH
Descrizione
Categoria
Input
Output
FUNZIONE 3DH
Descrizione
Categoria
Input
Output
CREATE A FILE
Crea un nuovo file, se esiste già è aperto con lunghezza zero, in
ogni caso il file è aperto in read/write.
I/O su dischi.
AH = 3CH CX = attributi per il file
DS:DX = pointer al pathname.
Attributi file: 00 = normal
01 = read-only
02 = hidden
04 = system
Se (CF = 0) allora AX = file handle, altrimenti AX = codice di errore.
Codice di errore: 3 = pathname non trovato
4 = nessun file handle disponibile
5 = accesso negato, esempio Read-only
OPEN A FILE
Apre il file specificato con un prestabilito codice di accesso.
I/O su dischi.
AH = 3DH AL = codice di accesso
DS:DX = pointer al pathname.
Codice di accesso: 76543210
AAA modo di accesso: 210
000 read-only
001 write-only
010 read-write
R
riservato sempre zero
SSS
modo condiviso (share)
I
ereditarietà, solitamente 1.
Quando il file non è condiviso da più processi, porre SSS a 000.
Se (CF = 0) allora AX = file handle, altrimenti AX = codice di errore.
Codice di errore: 1 = numero di funzione non valido
2 = file non trovato
3 = pathname non trovato
4 = nessun file handle disponibile
5 = accesso negato, esempio Read-only
12 = codice di accesso non valido.
FUNZIONE 3EH
Descrizione
Categoria
Input
Output
CLOSE A FILE HANDLE
Chiude il file handle corrente.
I/O su dischi.
AH = 3EH BX = file handle.
Se (CF = 0) allora AX = indefinito, altrimenti AX = codice di errore.
Codice di errore: 6 = file handle invalido.
FUNZIONE 3FH
Descrizione
READ FROM FILE OR DEVICE, USING A HANDLE
Legge uno specificato numero di byte, da un file o da un dispositivo e
li memorizza in un buffer di memoria, la lettura inizia dal valore
corrente del file pointer.
I/O su dischi.
AH = 3FH BX = file handle
CX = numero di byte da leggere
DS:DX = pointer al buffer di memoria.
Se (CF = 0) allora AX = byte letti, altrimenti AX = codice di errore.
Codice di errore: 5 = accesso negato, esempio Read-only
6 = file handle non valido.
Categoria
Input
Output
MS-DOS
um 94 di 138
La funzione inizia a leggere i byte del file, a partire dal valore corrente del file pointer.
Terminata la lettura, il file pointer è incrementato del numero di byte letti e la funzione
ritorna con CF = 0, l’operazione di lettura ha avuto successo e AX riporta il numero di byte
letti.
È conveniente effettuare un controllo tra il numero di byte da leggere, specificati in CX e
quelli effettivamente letti il cui numero è riportato in AX, nel caso in cui AX risulti minore di
CX il file pointer è arrivato alla fine del file, oppure si è verificato un errore.
La funzione può essere usata per leggere i caratteri provenienti dalla tastiera, file handle
uguale a 0 o dalla linea seriale, file handle uguale a 3.
FUNZIONE 40H
Descrizione
WRITE TO FILE OR DEVICE, USING A HANDLE
Scrive uno specificato numero di byte, prelevati da un buffer di
memoria, in un file o in un dispositivo, la scrittura inizia a partire dal
valore corrente del file pointer.
Categoria
I/O su dischi.
Input
AH = 40H
BX = file handle
CX = numero di byte da scrivere
DS:DX = pointer al buffer di memoria.
Output
Se (CF = 0) allora AX = byte scritti, altrimenti AX = codice di errore.
Codice di errore: 5 = accesso negato, esempio Read-only
6 = file handle non valido.
Terminata l’operazione di scrittura il file pointer è aumentato del numero di byte scritti.
Se la funzione ritorna con CF uguale a 0, l’operazione ha avuto successo e AX riporta il
numero di byte scritti.
Se il disco è pieno, è probabile che nel file siano scritti un numero minore di byte rispetto a
quelli indicati da CX.
In questo caso la funzione ritorna senza codice di errore, ma AX indica il numero di byte
effettivamente scritti.
È conveniente confrontare, al termine della funzione, AX con CX per rilevare eventuali
perdite di dati dovute al disco pieno.
FUNZIONE 42H
Descrizione
MOVE FILE POINTER
Sposta il file pointer all’interno di un file di un numero di byte, può
essere spostato dall’inizio, dalla fine o dalla posizione corrente.
Categoria
I/O su dischi.
Input
AH = 42H
AL = modo di spostamento
BX = file handle
CX:DX = offset (in byte) a 32 bit con segno.
Modo di spostamento:
0 muove a partire dall’inizio del file
1 muove a partire dal valore corrente
2 muove a partire dalla fine del file
Output
Se (CF = 0) allora DX:AX = nuovo file pointer, altrimenti AX = cod. err.
Codice di errore: 1 = modo di spostamento non valido
6 = file handle non valido.
La funzione aggiorna il file pointer sommandogli il numero con segno a 32 bit specificato in
CX:DX.
È possibile spostare il file pointer sia prima dell’inizio del file sia dopo la fine.
In ogni caso, un’operazione di questo tipo causerà un errore in una successiva funzione di
scrittura o lettura del file.
È possibile determinare la lunghezza del file, utilizzando il modo 2 di spostamento con
CX:DX = 0.
Il nuovo file pointer riportato in DX:AX indica la lunghezza del file.
Posizionando il file pointer alla fine del file ed eseguendo successivamente un’operazione
di scrittura è possibile aumentare la lunghezza del file.
MS-DOS
um 95 di 138
FUNZIONE 43H
GET OR SET FILE ATTRIBUTES
Descrizione
Permette di ottenere o di settare gli attributi di uno specifico file.
Categoria
I/O su dischi.
Per ottenere gli attributi.
Input
AH = 43H
AL = 00H
DS:DX = pointer al pathname.
Output
Se (CF = 0) allora CX = attributi file, altrimenti AX = codice di errore.
Per settare gli attributi.
Input
AH = 43H AL = 1 CX = attributi DS:DX = pointer al pathname.
Output
Se (CF = 0) allora successo, altrimenti AX = codice di errore.
Codice di errore: 1 = codice di funzione non valido
2 = file non trovato
3 = percorso non trovato
4 = accesso negato.
FUNZIONE 5BH
Descrizione
Categoria
Input
Output
39h
3Ah
3Bh
41h
43h
45h
46h
47h
4Eh
4Fh
56h
57h
5Ah
CREATE NEW FILE
Crea un nuovo file, solo se non già esistente.
I/O su dischi.
AH = 5BH CX = attributi del file
DS:DX = pointer al pathname
Se (CF = 0) allora AX = file handle, altrimenti AX = codice di errore.
Codice di errore: 3 = percorso non trovato
4 = nessun file handle disponibile
5 = accesso negato
80 = file già esistente.
Create Directory.
Remove Directory.
Change Current Directory.
Delete Directory Entry.
Get/Set File Attributes.
Duplicate File Handle.
Force Duplicate File Handle.
Get Current Directory.
Find First File.
Find Next File.
Change Directory Entry.
Get/Set Date/Time of File.
Create Temporary File.
implementazione
S’inizierà a descrivere il file system di MS-DOS guardando prima lo schema di un disco.
Lo schema di un hard disk e gli schemi dei floppy sono diversi tra loro; si parlerà in
particolare dell’hard disk.
Tutti i dischi rigidi hanno lo stesso schema.
Il settore di boot contiene l’informazione critica sul file system, ovvero il codice per far
partire il sistema; seguono delle tabelle che tengono traccia di tutto lo spazio del disco, poi
c’è la root e quindi tutto il resto.
Il settore di boot inizia sempre con un’istruzione JUMP che tralascia l’informazione
descrittiva del settore e va all’inizio del codice.
In questo modo la ROM può iniziare il boot leggendo il settore di boot nella memoria,
avviandolo senza doversi preoccupare dello schema interno.
Segue una lista di parametri critici, ivi incluso il numero di byte per settore, il numero di
settori per blocco, il numero di tabelle di allocazione dei file, la dimensione della directory
root, la dimensione del dispositivo e altri dati del genere.
MS-DOS
um 96 di 138
Dopo questi parametri c’è il codice di bootstrap.
A differenza del bootstrap di ROM che legge semplicemente il settore 0 e gli trasferisce il
controllo, questo codice sa che sta facendo il boot di MS-DOS.
Infatti, il codice di ROM può fare indifferentemente il boot di Unix o di qualsiasi altro SO.
Il codice del settore di boot localizza la directory radice e cerca IO.SYS e MSDOS.SYS; a
questo punto usa BIOS per caricarli e posizionarsi all’inizio di IO.SYS.
Il settore di boot contiene, nella parte finale, la tabella delle partizioni i cui elementi
indicano l’inizio e la fine di ogni partizione, fino ad un massimo di 4; ogni partizione può
contenere un file system differente, per cui MS-DOS e Unix possono coesistere senza
problemi sullo stesso hard disk, ognuno nella sua partizione.
Una partizione può essere marcata come attiva, per permettere che solo quella inizi a
girare quando è fatto il boot del sistema dal disco rigido.
L’utility FDISK, serve per permettere agli utenti di creare, cancellare e modificare le
dimensioni delle partizioni.
Una volta che un disco è stato diviso in partizioni e i file system sono stati sistemati in
ognuna di esse, una nuova ripartizione del disco comporta quasi sempre lo
smantellamento di tutti i file system e il loro ripristino.
Per i floppy invece si parla di cluster, gruppo, blocco, grappolo; è un insieme di settori
consecutivi, record fisico, la cui dimensione, in numero pari a una potenza di due, è
stabilito al momento della formattazione.
Esempio.
Cluster = 1024 byte (1KB) = 2 settori
9 settori = 9 X 512 = 4608 byte
40 tracce = 40 X 4608 = 184320 byte
2 facce = 2 X 184320 = 368640 : 1024 = 360 KB
La capacità logica è solamente di 354 KB, ne mancano 6, 6144 byte, 12 settori, 1 traccia
più 1/3, MS-DOS occupa 6 cluster numerati da 1 a 6 per i descrittori e 354 numerati da 7 a
360 per i dati.
Per sicurezza e integrità, esistono due copie della FAT costantemente aggiornate.
Il primo byte della FAT usato dal device driver per identificare il disco.
La mappa dell’area dati del disco comincia al byte di offset quattro.
Dopo il settore di boot si trova la FAT che tiene traccia di tutto lo spazio del disco.
Questa tabella, in MS-DOS, ha le stesse prestazioni della lista libera e della tabella degli inode in Unix.
MS-DOS
um 97 di 138
Per fornire maggiore affidabilità, si duplica la FAT, così il sistema non sarà distrutto se la
FAT principale diventa illeggibile, la FAT contiene un elemento per ogni cluster sul disco.
La dimensione del cluster si trova nel settore di boot e può variare da 1 settore per il disco
RAM, fino a 8 settori per gli hard disk di grandi dimensioni.
Nella versione 1.0, la dimensione dell’elemento di FAT era di 12 bit, ma poiché questa
dimensione può gestire solo dischi fino a 4096 cluster, quando furono messi in
circolazione dischi rigidi più grandi, essa fu modificata a 16 bit, permettendo così
65536X512 = 33 MB.
Le partizioni più grandi di 33 MB sono gestite tramite l’utilizzo di dimensioni del cluster
maggiori dei 512 byte standard, blocchi di 2 KB per i dischi da 100 MB.
Lo schema della FAT è mostrato nella figura seguente, lo schema reale è diverso poiché i
campi sono codificati in uno strano modo, un ritorno alle radici CP/M di MS-DOS.
Vi è una corrispondenza biunivoca tra gli elementi della FAT e i cluster del disco, fatta
eccezione per i primi due elementi che codificano la classe del disco.
In questo esempio è mostrato un file che inizia al cluster 6 e l’elemento della FAT in
posizione 6 contiene 8, a significare che il secondo cluster del file è il cluster 8; l’elemento
della FAT in posizione 8 contiene 4, per cui il cluster successivo è il cluster 4; l’elemento
della FAT in posizione 4 è 2 e infine l’elemento in posizione 2 è un codice speciale che
indica la fine del file.
Così, dando il numero del primo cluster di un file è possibile localizzare tutti i cluster
seguendo la catena nella FAT.
L’elemento della cartella relativo ad un file contiene il cluster di partenza e la FAT fornisce
la parte rimanente della catena.
I cluster liberi sono marcati da un altro codice speciale nella FAT.
Quando un file aumenta la sua dimensione, MS-DOS cerca un elemento libero nella FAT
e assegna quel cluster al file; allo stesso modo è usato un codice diverso per marcare i
cluster non leggibili.
Significato dei valori assunti dalle entry nella FAT.
0000H
cluster non occupato e disponibile.
FFF7H
cluster danneggiato.
FFFFH
EOF (End Of File), ultimo cluster di un file.
Per vedere com’è integrata la FAT nel sistema, si descrive ora una chiamata di sistema
OPEN dall’inizio alla fine.
Essa parte quando MS-DOS esamina la tabella dei descrittori del file, tenuta nel PSP
come un array di 20 byte e cerca un descrittore di file libero.
Ognuno dei byte della tabella dei descrittori dei file contiene sia un indice alla tabella
principale del file system approssimativamente analoga alla tabella degli i-node di Unix,
MS-DOS
um 98 di 138
oppure un codice che informa che il descrittore del file non è in uso; se è trovato un
descrittore di file libero, si cerca uno spazio libero nella tabella del file system.
Se c’è, allora è esaminato il pathname del file da aprire per controllare se esso è un CON,
un LPT o il nome di uno degli altri file speciali; durante questo confronto sono ignorate sia
le cartelle sia l’estensione.
Se esso non è un file speciale, si fa un controllo sul primo carattere per vedere se è una
(\), in questo caso il path è assoluto e la ricerca inizia nella root; in caso contrario, il path è
relativo e la ricerca inizia nella cartella di lavoro.
Da questo punto di vista MS-DOS è sostanzialmente lo stesso di Unix.
Una cartella in MS-DOS ha un elemento di 32 byte per ogni file o directory.
I primi 11 caratteri contengono il nome del file e l’estensione.
A differenza di Unix, il punto che separa la parte principale del nome dall’estensione non è
memorizzato esplicitamente nella directory.
Esempio, entry per i floppy da 360 KB = 112; da 1.44 MB = 224.
FILENAME (0..7)
Nome del file, 8 caratteri allineati a sinistra e completati eventualmente da spazi.
Il primo byte indica lo stato del file.
1. 00H la entry non è mai stata usata, questa informazione è usata per limitare le ricerche
nella cartella.
2. 05H il vero primo carattere del nome E5H, indica che il file è stato cancellato. Infatti
MS-DOS non cancella fisicamente un file, ma si limita a sostituire il primo carattere del
nome con E5H e a liberare, nella FAT, i cluster occupati; di conseguenza, poiché,
all’interno della directory sono mantenute inalterate tutte le altre informazioni, sarà
possibile, a patto di non aver occupato lo spazio per un altro file, recuperare le
informazioni contenute nel file cancellato con il comando UNDELETE.
3. 2EH la entry corrisponde a una sotto cartella, se anche il secondo byte è 2EH, allora il
campo 26-27 contiene il numero di cluster della directory padre, o 0000H se la
directory padre è root, altrimenti, i byte da 01 a 10 contengono spazi e il campo 26-27
contiene il numero di cluster di questa stessa cartella.
4. E5H il file è stato cancellato, ogni altro carattere è il carattere del nome di un file.
5. . elemento autoreferente il cui numero di cluster iniziale punta alla cartella corrente.
6. .. elemento padre il numero di cluster iniziale si riferisce all’inizio della cartella padre.
ESTENSIONE (8-10)
Estensione del nome del file.
MS-DOS
um 99 di 138
ATTRIBUTI (11)
Contengono i seguenti codici.
1. 00H bit di normale, il file può essere letto e scritto senza limitazioni.
2. 01H bit di readonly, 1 per i file di sola lettura, non si può scrivere sul file.
3. 02H bit di hidden, 1 per i file nascosti, non elencati da DIR.
4. 04H bit di sistema, 1 per i file di sistema, non cancellabili.
5. 08H bit di volume, label associata al disco, 1 per indicare che l’elemento si riferisce
all’etichetta di volume, solo un file può avere questo attributo e deve essere nella
directory radice.
6. 10H bit di directory, 1 per indicare che l’elemento si riferisce ad una cartella.
7. 20H bit di archivio, 1 quando è modificato il file, 0 quando è salvato.
Il byte di attributo si può leggere o scrivere usando le chiamate di sistema.
RISERVATI (12-21)
Per uso futuro.
ORA (22-23)
Ora di creazione o di ultimo aggiornamento, secondo la seguente mappa di bit (B7 - B0).
Offset 17H: H H H H M M M.
Offset 18H: M S S S S S S.
H: il numero binario, 4 bit, che rappresenta le ore (0-23).
M: il numero binario, 4 bit, che rappresenta i minuti (0-59).
S: il numero binario, 6 bit, che rappresenta i secondi (solo pari).
DATA (24-25)
Data di creazione o aggiornamento, l’anno, il mese e il giorno sono mappati su due byte.
Offset 19H: Y Y Y Y Y Y Y M.
Offset 18H: M M M D D D D D.
Y: anno, 7 bit, compreso tra 0 e 119 (1980-2099).
M: mese, 4 bit, tra 1 e 12.
D: giorno, 5 bit, tra 1 e 31.
CLUSTER INIZIALE (26-27)
Cluster iniziale, è il numero del primo cluster nel file, per primo il byte meno significativo.
Permette di localizzare l’inizio della catena nella FAT, rendendo così possibile trovare tutti
i cluster successivi.
DIMENSIONE (28-31)
Dimensione del file in byte, con prima la word meno significativa.
È interessante confrontare l’implementazione del file system MS-DOS con quella di Unix;
in quest’ultimo un elemento di directory contiene il nome del file e il numero dell’i-node e
nient’altro; tutte le altre informazioni, come la dimensione del file, l’ora e il giorno di
creazione e i numeri di cluster sono negli i-node.
MS-DOS non ha gli i-node per cui tutte le informazioni sono contenute nell’elemento della
directory, questo rende impossibili i link poiché avere due elementi di directory che
contengono lo stesso numero di cluster iniziale non può funzionare; ognuno avrebbe il suo
giorno, ora e dimensione del file provocando inconsistenze.
Ciò significa anche che l’accesso diretto ad un cluster vicino alla fine di un grosso field
richiede uno o più accessi al disco.
Ritornando alla chiamata di sistema OPEN, se la ricerca ha successo, l’elemento di
directory è copiato nella tabella dei file del sistema, che ha un elemento per ogni file
aperto; il campo posizione del file è quindi messo a 0.
L’avere il campo posizione del file sistemato qui non provoca problemi come
MS-DOS
um 100 di 138
succederebbe in Unix poiché non c’è il pericolo che un utente indipendente possa aprire il
file; infatti il descrittore di file è restituito al chiamante e la OPEN termina.
Con questa impostazione di base, l’implementazione della READ e della WRITE è
semplice.
Il sistema usa il descrittore del file per accedere all’array di 20 byte contenuto nel PSP per
ottenere l’indirizzo della tabella di sistema dei file che contiene le informazioni riguardanti il
file, queste informazioni comprendono l’inizio della catena dei cluster del disco, la
posizione corrente del file, la dimensione corrente, che tutte insieme permettono
l’esecuzione delle operazioni.
La dimensione della tabella di sistema dei file è determinata da una riga in CONFIG.SYS,
ma è limitata a non più di 256 dall’uso di elementi di un byte nel PSP.
File FILETYPE.ASM
Riproduce le funzioni del comando TYPE.
Legge dalla linea di comando il nome del file da visualizzare, lo apre, ne legge blocchi di
carattere lunghi buf_len byte e li carica nel buffer out_buf che in seguito è passato al
modulo di scrittura su file logico di uscita, predefinito con handle uguale ad un’unità
schermo.
Non ha luogo alcun controllo del tipo di caratteri che sono direttamente copiati così come
provengono dal file d’input.
Un controllo sul numero dei byte letti indica quando il file è giunto al suo termine, nel qual
caso l’esecuzione salta al modulo di chiusura del file close_file_handle.
Quindi chiude il file e termina l’esecuzione; mostra anche come avviene la lettura dei
parametri passati insieme al comando, interessante pure la ridirezione d’I/O.
STACKSEG SEGMENT PARA STACK ‘STACK’
DB
200H DUP (?)
STACKSEG ENDS
CSEG SEGMENT WORD ‘CSEG’
ASSUME CS:CSEG,DS:CSEG,ES:CSEG
BUF_LEN EQU 80
;legge dal file d’ingresso blocchi lunghi BUF_LEN byte
OUT_HANDLE
EQU 1
;handle di output = display
OUTSTR
DB “PROGRAMMA PER TYPE DI FILE “,13,10,”$”
FILE_NAME DB 32 DUP(0)
FILE_HANDLE
DW 0
;handle di input
OUT_BUF DB BUF_LEN DUP (0) ;questi blocchi sono caricati in BUF_LEN per
andare al file logico d’uscita senza nessun controllo
LOCAL_PSP DW 0
;prima del run DS ed ES puntano al PSP FILETYPE
;salva questo valore
BEGIN: MOV CS:LOCAL_PSP,DS
;il PSP è contenuto in DS
MOV AX,CSEG
;DS = CSEG via AX
MOV DS,AX
MOV DX,OFFSET OUTSTR
;DS:DX punta ad OUTSTR
MOV AH,09H
INT 21H
GET_FILE_NAME:
;legge dalla linea di comando filename e copy in FILE_NAME eliminando i blank
CLD
;SI e DI vanno incrementati
MOV DI,OFFSET FILE_NAME ;indirizzo di destinazione
MOV AX,CSEG
;ES = CSEG via AX
MOV ES,AX
;ES:DI punta a FILE_NAME
MOV DS,LOCAL_PSP
;DS:DI punta alla stringa di comando
MOV SI,80H
LODSB
;lunghezza della stringa in AL
MS-DOS
um 101 di 138
XOR AH,AH
MOV CX,AX
LOOP_1:
LODSB
CMP AL,32
JA COPY_INP_STRING
DEC CX
JMP LOOP_1
COPY_INP_STRING:
STOSB
DEC CX
REP MOVSB
OPEN_FILE_HANDLE:
MOV AX,CSEG
MOV DS,AX
MOV DX,OFFSET FILE_NAME
MOV AH,3DH
MOV AL,0H
INT 21H
JC END_PROCESS
MOV FILE_HANDLE,AX
READ_BLOCK:
MOV DX,OFFSET OUT_BUF
MOV CX,BUF_LEN
MOV BX,FILE_HANDLE
MOV AH,3FH
INT 21H
JC END_PROCESS
DISPLAY_ON_OUTPUT:
CMP AX,0
JE CLOSE_FILE_HANDLE
MOV CX,AX
MOV BX,OUT_HANDLE
MOV DX,OFFSET OUT_BUF
MOV AH,40H
INT 21H
JMP READ_BLOCK
CLOSE_FILE_HANDLE:
MOV BX,FILE_HANDLE
MOV AH,3EH
INT 21H
END_PROCESS:
MOV AL,0
MOV AH,4CH
INT 21H
CSEG ENDS
END BEGIN
MS-DOS
;CX = numero di byte da leggere
;delete blank dalla stringa d’ingresso
;controllo ASCII = 32
;byte da leggere -1
;lettura stringa d’ingresso
;ES:DI punta già a FILE_NAME
;copiatura byte successivi, numero
;contenuto in CX
;apertura file in lettura
;DS:DX punta a FILE_NAME
;funzione DOS open_file
;accesso: read_only
;end per errore carry true
;risultato chiamato da AX,handle per il file
;lettura file
;DS:DX punta ad OUT_BUF dove metto i char
;CX = numero di byte da leggere
;BX = file handle
;funzione DOS read_file
;end per errore carry true
;su video il contenuto di OUT_BUF
;AX = numero di byte scritti
;AX = 0 a fine file
;CX = numero di byte in uscita
;BX = handle file logico output
;DS:DX punta ad OUT_BUF
;funzione DOS write_file
;lettura di un nuovo blocco
;BX = file handle
;funzione DOS close_file
um 102 di 138
I/O
Introduzione
MS-DOS supporta i file speciali di caratteri per fare l’I/O sui dispositivi seriali, per lo più
come fa Unix, tranne per il fatto che i nomi dei dispositivi non sono memorizzati in una
directory come /dev.
Per copiare un file su una console, video, si può usare il comando: COPY FILE CON.
Il file CON può essere aperto anche dalle applicazioni, per lo più come /dev/tty può essere
aperto dai programmi Unix, infatti, può essere aperto come \DEV\CON anche se non c’è la
cartella \DEV.
L’apertura di un file di caratteri speciali restituisce un descrittore di file, che può essere
usato per la lettura e la scrittura, altri file di caratteri speciali comprendono COM la prima
porta seriale, LPT1 la prima porta di stampante in linea parallela e NUL che ha una
funzione identica a quella di /dev/null in Unix.
Questi nomi non possono essere usati come la prima parte di qualsiasi nome di file,
indipendentemente da quale tipo di estensione essi abbiano.
I file di caratteri speciali supportano le modalità cooked e raw, come i file di Unix; in
modalità cooked, l’editing tra le linee, come la cancellazione di caratteri è fatta dal SO,
rendendo disponibile all’applicazione solo il risultato finale.
In modalità raw, i caratteri sono passati all’applicazione esattamente come sono ricevuti;
gli editor di video e altre applicazioni interattive operano spesso in questo modo.
A differenza di Unix, in cui un processo parte con tre file speciali già aperti, lo standard
input, lo standard output e lo standard error, tutti connessi al terminale, in MS-DOS
quando parte un processo, esso ha cinque file aperti automaticamente: lo standard input,
lo standard output, lo standard error, la linea seriale e la stampante, che usano i descrittori
di file rispettivamente da 0 a 4.
MS-DOS permette agli utenti d’installare i loro driver di dispositivo solo dopo che il sistema
è inizializzato.
Tutto ciò è in contrasto con l’approccio Unix, in cui i driver di dispositivo sono compilati
sempre nel kernel e non sono installabili in un secondo momento.
La differenza è dovuta al fatto che storicamente i sistemi Unix sono stati installati e gestiti
nei centri di calcolo, dove un amministratore di sistema è sempre disponibile per la
compilazione e la generazione del sistema.
Un driver di dispositivo è installato aggiungendo una semplice istruzione al file
CONFIG.SYS dando il path name del file che contiene il driver.
chiamate di sistema
La chiamata IOCTL (IO ConTroL) è formata da un numero considerevole di chiamate per
la gestione dei file speciali; alcune opzioni permettono alle applicazioni di verificare un
descrittore di file per vedere se è un file speciale di caratteri, per mandare i dati di
controllo, in pratica la velocità di linea del terminale, per controllare lo stato dell’input e
dell’output del dispositivo, per definire le modalità video o altre, per specificare le pagine di
codice dei vari linguaggi nazionali, per leggere o scrivere i parametri.
implementazione
L’I/O in MS-DOS è realizzato completamente attraverso i file speciali a caratteri e a
blocchi.
I file a caratteri si occupano dei dispositivi che trattano un carattere per volta, come
terminali e stampanti, mentre i file a blocchi servono per i dischi.
Associato con ogni file speciale c’è un driver di dispositivo, che contiene il codice che
MS-DOS
um 103 di 138
permette l’I/O.
Alcuni driver, come COM1, CON e LPT1, sono standard e sono contenuti in IO.SYS; gli
utenti possono caricare altri driver di dispositivo quando si fa il boot del sistema
aggiungendo una o più righe in CONFIG.SYS.
Avere i driver di dispositivo serve a dotare MS-DOS di un’interfaccia standard per tutti i
dispositivi H/W.
Quando un’applicazione scrive o legge un file speciale compresi tutti gli accessi al file
sytem, MS-DOS chiama il driver corrispondente in modo standardizzato, dicendogli quale
di essi vuole, allontanando il SO dai particolari dell’H/W.
L’idea di permettere i driver installabili dagli utenti è servita per permettere a chiunque di
comprare qualsiasi dispositivo d’I/O per i propri PC, tra cui nastri, sintetizzatori vocali,
plotter e strumenti musicali digitali.
Per usare uno di questi è necessario creare un nuovo file speciale e installare un nuovo
driver che se ne occupa.
In Unix, l’installazione di un nuovo driver di dispositivo richiede la ricompilazione del SO, il
che è accettabile per l’installazione tradizionale di un computer, ma assolutamente
impraticabile per un prodotto di massa come MS-DOS.
Un driver può andare bene per un file speciale a caratteri o un file speciale a blocchi, ma
non per entrambi, poiché le interfacce dei due tipi sono un po’ differenti e le funzioni che
devono adempiere non sono le stesse, l’accesso diretto è permesso sui dispositivi a
blocchi, ma non su quelli a carattere.
Ogni driver è un programma separato, scritto in linguaggio assembly, in C o un altro
linguaggio e compilato, iI driver hanno estensione SYS come MOUSE.SYS per distinguerli
dagli altri file.
Tutti i driver a caratteri hanno la seguente struttura, i driver a blocchi differiscono non
molto da quelli a caratteri.
Prima si trova un’intestazione, header, di 18 byte che identifica il driver e descrive alcune
delle sue proprietà; segue il codice, formato da due parti, una che accetta le richieste MSDOS e una per realizzare l’I/O.
Quando è installato un driver, esso è messo in cima ad una lista concatenata di driver; una
variabile interna di MS-DOS contiene il puntatore al primo elemento della lista ed è usata
per visitare la lista.
Poiché la visita della lista parte dalla testa, un driver appena installato ha la precedenza su
quelli installati precedentemente.
Per esempio, il driver standard CON non supporta alcuna sequenza di escape per l’output
su video, per cui se un utente ne vuole una di tipo ANSI deve inserire in CONFIG.SYS il
file ANSI.SYS, che carica un nuovo driver per CON sul disco rigido; da questo momento
tutto l’I/O su video sarà mandato ad ANSI.SYS.
La parola successiva nell’intestazione è una bit map, parola di attributi, usata per
MS-DOS
um 104 di 138
distinguere i dispositivi a caratteri da quelli a blocchi e per dire se sono supportate alcune
funzioni opzionali.
I 5 bit di ordine più basso sono usati per rendere possibile a MS-DOS una ricerca rapida
nella lista in modo da trovare il driver della console, del clock, lo standard input e lo
standard output senza dover cercare i loro nomi.
15
14
13
11
7
6
4
3
2
1
0
Blocco di carattere.
IOCTL è supportato?
L’output fino allo stato busy è supportato?
L’apertura e la chiusura sono supportate?
Le richieste di IOCTL sono supportate?
I set/get logical drive sono supportati?
1 se è un driver di console con output veloce.
1 per il driver del clock.
1 per il driver di NULL.
1 per lo standard output.
1 per lo standard input.
Le due parole successive danno rispettivamente gli offset del gestore di richieste e il
codice d’I/O, infine, si trova il nome del driver, che ha un massimo di 8 caratteri.
Quando un file è aperto, MS-DOS prima controlla se il nome appartiene ad un file
speciale, visitando la lista dei driver per vedere se il nome del file da aprire corrisponde al
nome di qualcuno dei driver nella catena; in questo caso, quel driver è usato per tutte le
scritture e le letture fatte sul file.
Immediatamente dopo il driver si trova il codice, che è richiamato secondo lo schema che
segue.
1. Un’applicazione utente fa una chiamata di sistema READ o WRITE; MS-DOS usa il
descrittore del file per localizzare l’elemento della tabella dei file di sistema, guardando
nella tabella del descrittore del file del PSP e deduce quale dispositivo deve essere
letto o scritto.
2. Forma, poi, un messaggio di richiesta costituito da un’intestazione di 13 byte e, in
alcuni casi, da parametri extra; il messaggio contiene il codice di funzione per
l’operazione desiderata, l’indirizzo di memoria da cui leggere o scrivere, l’indirizzo del
dispositivo per i dispositivi a blocchi e il contatore di byte.
3. MS-DOS, quindi, esamina l’offset della procedura di gestione delle richieste del
dispositivo e la chiama; questa procedura esamina il messaggio e salva i campi
significativi; poi restituisce il controllo prima che parta il lavoro.
4. Successivamente MS-DOS guarda l’offset del codice d’I/O nell’intestazione del driver
di dispositivo e lo chiama per l’elaborazione in corso; la ragione di questa suddivisione
in due chiamate non è chiara, ma probabilmente dovrebbe essere di aiuto nel caso in
futuro si aggiunga la multiprogrammazione in MS-DOS.
5. Quando il driver ha finito il lavoro, setta una parola di stato che ne indica il successo o
il fallimento e restituisce il controllo al chiamante.
I driver di dispositivo possono supportare un numero grande di funzioni, sebbene un
particolare driver possa indicare che esso non supporta alcune delle più strane; basta
mettere a 0 certi bit nella parola di attributi.
Se, per esempio, un’applicazione fa una chiamata di sistema IOCTL su un file speciale il
cui driver non supporta IOCTL gli è restituito uno stato di errore.
I driver non possono usare le chiamate di sistema di MS-DOS perché MS-DOS non è
rientrante, in pratica non può accettare una nuova chiamata di sistema mentre è occupato
con un’altra.
MS-DOS
um 105 di 138
COMANDI
ATTRIB
Visualizza o modifica gli attributi dei file.
Questo comando visualizza, imposta o rimuove gli attributi assegnati ai file e alle cartelle,
quali l’attributo di sola lettura, di archivio, di file di sistema e di file nascosto.
ATTRIB [+R|-R] [+A|-A] [+S|-S] [+H|-H][[unità:][percorso]nomefile] [/S]
Opzioni.
+R Imposta l’attributo di sola lettura.
-R Disattiva l’attributo di sola lettura.
+A Imposta l’attributo archivio. -A Disattiva l’attributo archivio.
+S Imposta il file come file di sistema.
-S Disattiva l’attributo di file di sistema.
+H Imposta il file come file nascosto.
-H Disattiva l’attributo di file nascosto.
/S Elabora i file presenti nella cartella corrente e in tutte le sotto cartelle.
Per visualizzare tutti gli attributi di tutti i file presenti nella cartella corrente, utilizzare la
seguente sintassi.
ATTRIB
DISKCOPY
Copia il contenuto di un disco floppy nell’unità di origine su un floppy formattato o non
formattato inserito nell’unità di destinazione.
Il comando DISKCOPY cancella il contenuto del disco di destinazione sovrascrivendovi i
nuovi dati; questo comando determina il numero di facce da copiare in base all’unità e al
disco di origine.
DISKCOPY [unità1: [unità2:]] [/1] [/V] [/M]
Opzioni.
/V Verifica che le informazioni siano copiate correttamente; l’utilizzo di questa opzione
rallenta l’operazione.
/M Indica a DISKCOPY di usare solo memoria convenzionale per memorizzazioni
provvisorie, DISKCOPY usa di solito il disco rigido per tale operazione, non si debbono
scambiare i floppy.
CHDIR (CD)
Visualizza il nome della cartella corrente oppure cambia la cartella corrente.
CHDIR [unità:][path]
CHDIR[..]
CD [unità:][percorso]
CD[..]
CHKDSK
Genera e visualizza una relazione sullo stato del disco e riporta gli errori individuati sul
disco.
Il rapporto sullo stato mostra gli errori rilevati nel sistema di archiviazione MS-DOS,
consistente nella tavola allocazione file e nelle cartelle.
Anche CHKDSK fornisce un riepilogo dell’uso del disco.
CHKDSK non verifica che le informazioni nei file possano essere lette senza errori.
MS-DOS
um 106 di 138
Se vi sono errori su disco, CHKDSK visualizza un messaggio.
L’utility SCANDISC è il metodo consigliato per correggere problemi su disco, da preferire
al comando CHKDSK /F.
CHKDSK [unità:][[percorso] nomefile] [/F] [/V]
Opzioni.
/F Corregge gli errori su disco, non utilizzare questa opzione se si sta eseguendo
CHKDSK da altre applicazioni.
/V Visualizza il nome di ciascun file contenuto in tutte le cartelle, durante il controllo del
disco.
Per visualizzare una relazione sullo stato del disco dell’unità corrente, utilizzare la
seguente sintassi.
CHKDSK
COPY
Copia uno o più file in un’altra posizione.
Il comando COPY può essere utilizzato anche per unire file.
Se sono copiati più file, MS-DOS visualizza il nome di ciascun file man mano che è
copiato.
COPY [Y|-Y][/A|/B] origine[/A|/B] [+ origine[/A|/B] [+ ...]][destinazione [/A|/B]] [/V]
Opzioni.
/A Indica un file di testo ASCII.
L’opzione /A ha effetto su tutti i file che essa precede nell’elenco dei nomi di file sulla riga
di comando, fino a quando COPY non incontra un’opzione /B.
In tal caso, l’opzione /B ha effetto su tutti i file che la precedono.
Quando l’opzione /A segue un nome di file, essa avrà effetto su quel file e su tutti i file ad
essa successivi, fino a quando COPY non incontra l’opzione /B.
In tal caso, l’opzione /B avrà effetto su tutti i file che la precedono.
Un file di testo ASCII può utilizzare il carattere di fine file CTRL+Z, per indicare la fine di un
file.
Durante l’unione di file, il comando COPY considera per definizione i file come file di testo
ASCII.
/B Indica un file binario.
L’opzione /B ha effetto su tutti i file che la precedono sulla riga di comando, fino a quando
il comando COPY non incontra un’opzione /A.
In tal caso, l’opzione /A avrà effetto su tutti i file che la precedono.
Se l’opzione /B segue un nome di file, essa avrà effetto su quel file e su tutti i file ad essa
successivi, fino a quando COPY non incontra un’opzione /A.
In tal caso, l’opzione /A avrà effetto su tutti i file che la precedono.
L’opzione /B specifica che l’interprete dei comandi deve leggere il numero di byte
specificati dalle dimensioni dei file nella cartella.
L’opzione /B è il valore predefinito di COPY, tranne quando esso sta unendo dei file.
DEFRAG
Riorganizza i file su un disco per ottimizzare le prestazioni del disco stesso.
Non utilizzare questo comando durante l’esecuzione di Windows.
DEFRAG [unità:] [/F] [/S[:]ordine] [/B] [/SKIPHIGH] [/LCD | /BW | /G0] [/H] DEFRAG [unità:]
[/U] [/B] [/SKIPHIGH] [/LCD | /BW | /G0] [/H]
MS-DOS
um 107 di 138
Opzioni.
/F Compatta i file e garantisce che nel disco non siano presenti spazi vuoti tra i file.
/U Compatta i file e lascia spazi vuoti, se presenti, tra i file.
/B Riavvia il PC dopo avere riorganizzato i file.
/H Sposta file nascosti.
DEL (Erase)
Elimina i file specificati.
DEL [unità:][percorso] nomefile [/P]
Opzione.
/P Chiede conferma prima di eliminare il file specificato.
DELTREE
Elimina una cartella con tutti i file e sotto cartelle relative.
DELTREE [/Y] [unità:]percorso [[drive:]percorso[...]]
DIR
Visualizza l’elenco dei file e delle sotto cartelle di una cartella.
Quando si utilizza il comando DIR senza parametri od opzioni, esso visualizza l’etichetta di
volume e il numero di serie del disco.
Visualizza inoltre una cartella o un file per riga, inclusa l’estensione del file, la relativa
dimensione in byte, la data e l’ora dell’ultima modifica.
Infine, il comando riporta il numero totale dei file elencati, la quantità totale di memoria
occupata e il numero di byte lasciati liberi sul disco.
DIR [unità:][percorso][nomefile] [/P] [/W] [/A[[:]attributi]][/O[[:]tipoordinamento]] [/S] [/B] [/L]
[C]
Opzioni.
/P Visualizza l’elenco una schermata per volta.
Per passare alla schermata successiva, è sufficiente premere un tasto.
/W Visualizza l’elenco in formato ampio, elencando fino a cinque file o cartella per riga.
/A[[:] attributi] Visualizza solo le cartelle e i file con gli attributi specificati.
Se questa opzione è omessa, il comando DIR visualizza tutti i file tranne quelli nascosti e
di sistema.
Se l’opzione è utilizzata senza specificare gli attributi, DIR visualizza tutti i file, compresi
quelli nascosti e di sistema.
L’elenco che segue descrive ciascuno dei valori che è possibile utilizzare per attributi.
I due punti (:) sono facoltativi.
È possibile utilizzare una qualsiasi combinazione di questi valori senza separarli con spazi.
H File nascosti, -H File non nascosti, S File di sistema, -S File non di sistema, D Directory
-D Solo file escluse le directory, A File pronti per essere archiviati backup, -A File che non
sono stati modificati dall’ultimo backup, R File di sola lettura, -R File non di sola lettura.
DOSKEY
Doskey è un’utility residente in memoria ed è utilizzata per personalizzare e automatizzare
la riga di comando MS-DOS.
Quando è installato, Doskey occupa circa 3 KB di memoria residente.
DOSKEY [/REINSTALL] [/BUFSIZE=dimensione] [/MACROS]
[/HISTORY][/INSERT|/OVERSTRIKE] [nomemacro=[testo]]
MS-DOS
um 108 di 138
EDIT
Avvia MS-DOS Editor che consente di creare e modificare file di testo ASCII; è un editor a
schermo intero che consente di creare, modificare, memorizzare e stampare file di testo
ASCII.
In MS-DOS Editor è possibile scegliere i comandi da menu e specificare le informazioni e
le preferenze nelle finestre di dialogo.
MS-DOS Editor comprende un’ampia Guida in linea per richiedere informazioni relative
alle sue procedure e ai suoi comandi.
EDIT [[unità:][percorso]nomefile ] [/B] [/G] [/H] [/NOHI]
Per poter utilizzare MS-DOS Editor è necessario che il file QBASIC.EXE si trovi nella
directory corrente, nel relativo percorso di ricerca o nella stessa cartella del file
EDIT.COM.
Se il file QBASIC.EXE è eliminato per liberare spazio sul disco, MS-DOS Editor non potrà
essere eseguito.
EMM386
Abilita o disabilita il supporto di memoria espansa EMM386 su un PC con CPU 80386 o
superiore.
Il comando EMM386 abilita o disabilita anche il supporto del coprocessore Weitek.
Non utilizzare questo comando durante l’esecuzione di Windows.
Esso, inoltre, provvede supporto di memoria espansa e accesso alla memoria superiore.
EMM386 [ON|OFF|AUTO]
Per visualizzare lo stato attuale del supporto di memoria espansa EMM386, utilizzare la
sintassi seguente.
EMM386
Parametri.
ON|OFF|AUTO Attiva il driver di periferica EMM386.EXE se impostato su ON, sospende il
driver di periferica EMM386.EXE se impostato su OFF oppure posiziona il driver di
periferica EMM386.EXE in modalità automatica se impostato su AUTO.
La modalità automatica abilita il supporto di memoria espansa solamente quando un
programma lo richiede.
Il valore predefinito ON.
EXPAND
Espande un file compresso.
È possibile utilizzare questo comando per recuperare uno o più file dai dischi
d’installazione o di aggiornamento inclusi nel pacchetto di MS-DOS.
I file non possono essere utilizzati finché non sono decompressi.
EXPAND [unità:][percorso]nomefile [[unità:][percorso]nomefile[...]] destinazione
Se è digitato quanto segue, EXPAND chiederà d’immettere la posizione e/o il nome che si
desidera assegnare al file espanso.
EXPAND [unità:][percorso]nomefile
EXPAND chiederà d’immettere la posizione e il nome del file compresso da espandere,
quindi la posizione e/o il nome da assegnare al file espanso, se si digita quanto segue.
EXPAND
MS-DOS
um 109 di 138
FDISK
Avvia l’utility FDISK, che configura il disco rigido per l’utilizzo di MS-DOS.
Visualizza una serie di menu per facilitare la suddivisione in partizioni del disco rigido per
MS-DOS.
FDISK
Opzioni.
/STATUS Visualizza una panoramica delle partizioni del disco rigido del PC, senza avviare
l’utility.
Per visualizzare le informazioni sulla partizione senza avviare l’utility, utilizzare la seguente
sintassi.
FDISK /STATUS
FORMAT
Formatta il disco nell’unità specificata per accettare i file di MS-DOS.
Il comando FORMAT crea una nuova cartella principale e una tabella di assegnazione dei
file per il disco.
È anche possibile controllare le aree danneggiate sul disco ed eliminare tutti i dati sul
disco.
Per consentire a MS-DOS di utilizzare un disco nuovo, utilizzare questo comando per
formattare il disco.
FORMAT unità: [/V[:etichetta]] [/Q] [/U] [/F:dimensione][/B|/S] [/C]
FORMAT unità: [/V[:etichetta]] [/Q] [/U] [/T:tracce /N:settori] [/B|/S] [/C]
FORMAT unità: [/V[:etichetta]] [/Q] [/U] [/1] [/4] [/B|/S] [/C]
FORMAT unità: [/Q] [/U] [/1] [/4] [/8] [/B|/S] [/C]
Non formattare un disco floppy in misura maggiore a quella attribuitagli.
Se il disco è stato formattato e non si sta utilizzando il parametro /U, la vecchia tabella di
assegnazione dei file e la cartella principale saranno salvate per poter annullare la
formattazione del disco.
Se è stato formattato il disco sbagliato utilizzare il comando il più presto possibile.
Opzioni.
/Q Specifica una formattazione veloce di un disco.
Tramite questa opzione, FORMAT elimina la FAT e la directory principale di un disco
formattato in precedenza, ma non esamina il disco per verificare la presenza di aree
danneggiate.
Si dovrebbe utilizzare l’opzione /Q per formattare solo dischi già formattati in precedenza
che non sono sicuramente danneggiati.
/U Specifica un’operazione di formattazione incondizionata per un disco floppy o un disco
rigido.
La formattazione incondizionata distrugge tutti i dati esistenti sul disco e impedisce di
annullare la formattazione in un secondo tempo.
È consigliabile utilizzare /U se sono stati visualizzati messaggi di errori di lettura e di
scrittura durante l’utilizzo del disco.
/F:size Specifica la dimensione del disco floppy da formattare.
Se possibile, utilizzare questa opzione, invece delle opzioni /T e /N.
Utilizzare uno dei seguenti valori per la dimensione: 720, 1440.
/B Riserva dello spazio per i file di sistema IO.SYS e MSDOS.SYS su un disco appena
formattato come file nascosti.
Nelle versioni precedenti di MS-DOS, era necessario riservare questo spazio prima di
utilizzare il comando SYS per copiare i file di sistema sul disco.
Questa opzione è mantenuta MS-DOS versione 6.0 solo per ragioni di compatibilità.
MS-DOS
um 110 di 138
/S Copia i file di sistema in uso IO.SYS, MSDOS.SYS e COMMAND.COM dall’unità disco
di avvio del sistema su un disco formattato che può essere utilizzato come disco di
sistema.
Se FORMAT non riesce a trovare i file di sistema in uso, richiede l’inserimento di un disco
di sistema.
/C Ricontrolla i cluster danneggiati.
Per impostazione predefinita, se un’unità contiene cluster segnati come “danneggiati”
FORMAT non ricontrolla i cluster; li lascia semplicemente segnati come “danneggiati”.
Utilizzare l’opzione /C se si desidera che FORMAT ricontrolli tutti i cluster danneggiati
sull’unità.
KEYB
Avvia l’utility KEYB che configura una tastiera in base ad una lingua specifica.
Utilizzare KEYB per configurare una tastiera per una lingua diversa dall’inglese
statunitense.
KEYB [xx[,[yyy][,[unità disco:][percorso]nomefile]]] [/E] [/ID:nnn]
Parametri.
xx Specifica il codice della tastiera.
yyy Specifica la tabella codici.
Se non è specificato un valore, KEYB utilizza la tabella codici corrente.
[unità:][percorso]nomefile Specifica la posizione e il nome del file di definizione della
tastiera.
Il nome del file predefinito è KEYBOARD.SYS.
Se KEYBOARD.SYS si trova in una cartella inclusa nel percorso, non sarà necessario
specificare questo parametro.
MS-DOS 6.22 include due file di definizione della tastiera: il file predefinito
KEYBOARD.SYS e KEYBRD2.SYS, che fornisce supporto per tastiere non incluse in
KEYBOARD.SYS.
[unità-dos:]percorso dos Specifica la posizione del file KEYB.COM.
Opzioni.
/E Indica che la tastiera installata è avanzata, tale opzione risulta utile se si utilizza una
tastiera avanzata su un PC 8086.
/ID:nnn Specifica il tipo di tastiera in uso.
Questa opzione è necessaria solo per i paesi che hanno più schemi di tastiera per la
stessa lingua Francia, Italia e Regno Unito.
Per esempio, la Tabella Identificazione codici della tastiera Paese o lingua (valore xx)
(valore yyy) (valore ID:nnn) Italia it 850 437 Stati Uniti us 850 437.
LABEL
Crea, modifica o elimina l’etichetta di volume, nome, di un disco.
MS-DOS visualizza l’etichetta di volume all’interno dell’elenco della cartella.
MS-DOS visualizza anche il numero di serie del volume, se è disponibile.
LABEL [unità:][etichetta]
Per indicare a MS-DOS di visualizzare l’etichetta di volume e il numero di serie correnti, se
esistono e di richiedere l’immissione di un’etichetta o l’eliminazione di quella esistente,
utilizzare la seguente sintassi.
LABEL
MEM
Visualizza la quantità di memoria utilizzata e la quantità di memoria libera nel sistema.
MS-DOS
um 111 di 138
È possibile utilizzare il comando MEM per visualizzare le informazioni relative alle aree di
memoria utilizzate, alle aree di memoria libere e alle applicazioni caricate in memoria.
MEM [/CLASSIFY|/DEBUG|/FREE|/MODULE nomemodulo] [/PAGE]
Opzioni.
/CLASSIFY Elenca le applicazioni che sono state caricate effettivamente nella memoria e
visualizza la quantità di memoria convenzionale e di memoria superiore utilizzata da ogni
applicazione.
MEM /CLASSIFY Fornisce anche un sommario dell’utilizzo di memoria ed elenca i blocchi
di memoria più grandi a disposizione.
È possibile utilizzare l’opzione seguente.
/CLASSIFY con /PAGE, ma non con altre opzioni di MEM.
L’opzione /CLASSIFY può essere abbreviata in /C.
/FREE Elenca le aree di memoria convenzionale e superiore libere.
MEM/FREE Visualizza l’indirizzo del segmento, la dimensione di ogni area di memoria
convenzionale libera e il blocco più grande libero in ogni area di memoria superiore.
È possibile utilizzare l’opzione /FREE con /PAGE, ma non con altre opzioni di MEM.
Si può abbreviare /FREE in /F.
/PAGE Fa una pausa dopo ogni schermata di output.
Questa opzione può essere utilizzata con altre opzioni di MEM.
Per visualizzare lo stato della memoria utilizzata e della memoria libera del sistema,
utilizzare la seguente sintassi.
MEM
MKDIR (MD)
Crea una cartella.
È possibile utilizzare il comando MKDIR per creare una struttura di directory su più livelli.
MKDIR [unità:]percorso
MD [unità:]percorso
MSCDEX
Fornisce accesso alle unità CD-ROM.
MSCDEX può essere caricato dal file AUTOEXEC.BAT o dal prompt dei comandi.
Il driver di periferica che fa parte dell’unità CD-ROM deve essere caricato dal file
CONFIG.SYS.
Il comando MSCDEX non dovrebbe essere utilizzato dopo che Windows è stato avviato.
MSCDEX /D:periferica [/D:periferica2... ] [/E] [/K] [/S] [/V] [/L:lettera] [/M:numero]
Parametri.
/D:periferica1 [/D:periferica2... ] Specifica la signature del driver del primo driver di
periferica CD-ROM.
Il parametro periferica1 deve coincidere con il parametro specificato dall’opzione /D sul
comando CONFIG.SYS che avvia il driver di periferica corrispondente CD-ROM.
Il comando MSCDEX deve includere almeno un’opzione /D.
Per installare dei driver di periferica CD-ROM addizionali, specificare un’opzione
addizionale /D per ciascun driver.
/E Specifica che il driver CD-ROM deve essere predisposto in modo da espandere
memoria, se ne esiste disponibile, per archiviare dei buffer di settore.
/V Indica a MSCDEX di visualizzare delle statistiche di visualizzazione della memoria
quando è avviato.
/L:lettera Specifica le lettere dell’unità da assegnare alla prima unità CD-ROM.
MS-DOS
um 112 di 138
Se si ha più di un’unità CD-ROM, MS-DOS assegna delle unità addizionali conseguenti
alle lettere dell’unità disponibili.
/M:numero Specifica il numero di buffer di settore.
PATH
Imposta un percorso di ricerca per file eseguibili.
MS-DOS utilizza il comando PATH per cercare i file eseguibili nelle cartelle specificate.
Il percorso di ricerca predefinito è solo la cartella corrente.
PATH [[unità:]percorso[;...]]
Per visualizzare il percorso di ricerca corrente, utilizzare la sintassi seguente.
PATH
Per eliminare tutte le impostazioni dei percorsi di ricerca e lasciare soltanto quella
predefinita, la directory corrente, utilizzare la seguente sintassi.
PATH;
Quando è specificato da solo, elimina tutte le impostazioni dei percorsi e indica a MS-DOS
di ricercare soltanto nella cartella corrente.
PRINT
Stampa un file di testo durante l’elaborazione di altri comandi MS-DOS.
Se si dispone di una periferica di output, collegata ad una delle porte seriali o parallele del
sistema, con il comando PRINT sarà possibile stampare in background.
PRINT [/D:periferica] [/B:dimensioni] [/U:tic1] [/M:tic2] [/S:tic3] [/Q:dimensionicoda] [/T]
[[unità:][percorso] nomefile[ ...]] [/C] [/P] P
Opzioni.
/D:periferica Specifica il nome della periferica di stampa.
I valori validi delle porte parallele sono LPT1, LPT2 e LPT3.
I valori validi delle porte seriali sono COM1, COM2, COM3 e COM4.
Il valore predefinito è PRN.
I valori PRN e LPT1 si riferiscono alla stessa porta parallela.
L’opzione /D deve precedere il nome di qualsiasi file sulla riga di comando.
/T Elimina tutti i file dalla coda di stampa.
Per installare il comando PRINT utilizzando i parametri predefiniti o per visualizzare il
contenuto della coda di stampa senza modificarla, la sintassi sarà la seguente.
PRINT
PROMPT
Modifica l’aspetto del prompt dei comandi di MS-DOS.
È possibile personalizzare l’aspetto del prompt dei comandi in maniera tale da visualizzare
una qualsiasi stringa di testo, con informazioni quali il nome della directory corrente, l’ora e
la data e il numero della versione di MS-DOS.
PROMPT [testo]
Testo.
$Q = (segno di uguale).
$$ $ (simbolo del dollaro).
$T Ora corrente.
$D Data corrente.
$P Unità e percorso corrente.
$V Numero della versione di MS-DOS.
MS-DOS
um 113 di 138
$N Unità corrente.
$G > (segno di maggiore).
$L < (segno di minore).
$B | (pipe).
$_ INVIO-NUOVA RIGA.
$E Il codice escape ASCII (codice 27).
$H BACKSPACE (elimina un carattere che è stato scritto sulla riga di prompt).
RENAME (REN)
Cambia il nome di uno o più file.
È possibile assegnare un nuovo nome a tutti i file che corrispondono al nome specificato.
Non è possibile utilizzare questo comando per assegnare un nuovo nome a file di unità
diverse o per spostarli in nuove cartelle.
Per rinominare le sotto cartella o spostare i file, utilizzare il comando.
RENAME [unità:][percorso]nomefile1 nomefile2
REN [unità:][percorso]nomefile1 nomefile2
RMDIR (RD)
Elimina (rimuove) una cartella.
Prima di eliminare una cartella, è necessario eliminare prima tutti i file e le sotto cartelle
contenuti in essa.
La cartella deve essere vuota, fatta eccezione per i simboli (.) e (..).
RMDIR [unità:]percorso
RD [unità:]percorso
SCANDISK
Avvia Microsoft SCANDISK, un’utilità di scansione e ripristino che controlla una data unità
per rilevare degli errori e correggere eventuali problemi.
SCANDISK [unità: [unità: ...]|/ALL] [/CHECKONLY | /AUTOFIX [/NOSAVE] | CUSTOM]
[/SURFACE] [/MONO] [/NOSUMMARY]
Opzioni.
/ALL Controlla e ripristina tutte le unità locali.
/AUTOFIX Corregge gli errori senza chiedere prima conferma.
Per impostazione predefinita, avviando SCANDISK con l’opzione /AUTOFIX tutti i cluster
persi rilevati sull’unità, saranno salvati come file nella cartella principale dell’unità.
Per fare in modo che SCANDISK elimini i cluster persi invece di salvarli, includere
l’opzione /NOSAVE.
Utilizzando l’opzione /AUTOFIX, se sono rilevati errori sarà richiesto un disco Undo.
Per evitarlo, includere l’opzione /NOSUMMARY.
Non è possibile utilizzare l’opzione /AUTOFIX unitamente alle opzioni /CHECKONLY o
/CUSTOM.
/CHECKONLY Controlla una data unità per rilevarvi degli errori, ma non li corregge.
Non si può usare questa opzione unitamente alle opzioni /AUTOFIX or /CUSTOM.
/NOSAVE Fa in modo che SCANDISK elimini tutti i cluster persi rilevati.
Può essere utilizzato solo unitamente all’opzione /AUTOFIX.
Se si avvia SCANDISK con l’opzione /AUTOFIX omettendo l’opzione /NOSAVE, ScanDisk
salverà il contenuto dei cluster persi come file nella cartella principale dell’unità.
/SURFACE Esegue automaticamente una scansione della superficie dell’unità dopo aver
controllato altre aree.
Con una scansione della superficie di un’unità non compressa, SCANDISK conferma che i
MS-DOS
um 114 di 138
dati possono essere scritti e letti con sicurezza.
Con la scansione di un’unità compressa SCANDISK conferma che i dati possono essere
decompressi.
È consigliabile esaminare periodicamente la superficie di tutte le unità.
In base all’impostazione predefinita, una volta terminato l’esame del file system di una
data unità, SCANDISK chiede se si desidera effettuare una scansione della superficie.
Con l’opzione /SURFACE tale scansione è effettuata senza chiedere conferma.
Se si usa /SURFACE unitamente all’opzione /CUSTOM esso ha la precedenza sulle
impostazioni di superficie nella sezione [Custom] del file SCANDISK.INI.
SMARTDRV
Avvia o configura l’utility SMARTDRIVE la quale crea una cache del disco nella memoria
estesa.
Una cache del disco può velocizzare in modo significativo le operazioni di MS-DOS.
Quando è utilizzato per l’operazione di caching del disco, SMARTDRIVE è caricato
utilizzando il comando SMARTDRV nel file AUTOEXEC.BAT o al prompt dei comandi.
SMARTDRIVE può anche eseguire un doppio buffering, il quale è compatibile per i
controller del disco rigido che non possono funzionare con la memoria fornita da EMM386
o Windows eseguito in modalità 386 avanzata.
Per utilizzare il doppio buffering, caricare il driver di periferica utilizzando un comando
DEVICE nel file CONFIG.SYS.
Il comando SMARTDRV non sarà caricato dopo che Windows è stato avviato.
Sintassi.
Quando si avvia SMARTDRIVE dal file AUTOEXEC.BAT o dal prompt dei comandi,
utilizzare la seguente sintassi.
[unità:][percorso]SMARTDRV [/X] [[unità[+|-]]...] [/U] [/C|/R] [/F|/N] [/L] [/V|/Q|/S]
[DimCacheIniz][DimCacheWin]] [/E:DimElemen] [/B: ]
Quando inizia l’esecuzione di SMARTDRIVE, utilizzare la seguente sintassi.
SMARTDRV [/X] [[unità[+|-]]...]] [/C|/R] [/F|/N] [/Q|/S]
Per visualizzare lo stato corrente dopo che è stato caricato SMARTDRIVE, usare la
sintassi seguente.
SMARTDRV
Se si specifica una lettera dell’unità senza un segno di addizione o sottrazione, l’opzione di
caching di lettura è attivata e quella di scrittura è disattivata.
Se si specifica una lettera dell’unità seguita da un segno di addizione, le due opzioni sono
attivate.
Se si specifica una lettera dell’unità seguita da un segno di sottrazione, le opzioni sono
disattivate.
Se non si specifica una lettera dell’unità, le unità dischi floppy, CD-ROM e le unità create
utilizzando INTERLNK sono attivate con l’opzione di lettura ma non di scrittura, i dischi
fissi con entrambe le opzioni attivate e le unità di rete e le schede di memoria flash sono
ignorate.
Dimcacheiniz Specifica la dimensione in KB della cache quando SMARTDRIVE è avviato,
quando Windows non è eseguito.
DimCacheWin Specifica, in KB, in che misura SMARTDrive ridurrà la dimensione della
cache per Windows.
Quando è avviato Windows, SMARTDRIVE riduce la dimensione della cache per
recuperare memoria per l’utilizzo di Windows.
Opzioni.
/X Disattiva il caching write-behind per tutte le unità.
MS-DOS
um 115 di 138
È possibile quindi attivare il caching per le singole unità usando il parametro unità+|-.
/U Non carica il modulo caching CD-ROM di SMARTDRIVE anche se si possiede un’unità
CD-ROM.
Se è caricato SMARTDRIVE con l’opzione /U, non è possibile attivare il caching dell’unità
CD-ROM.
Se è caricato SMARTDRIVE senza l’opzione /U, è possibile disattivare o attivare il caching
di singole unità CD-ROM usando il parametro dell’unità+|-.
/C Scrive tutte le informazioni di cui è stato eseguito il caching dalla memoria sui dischi.
SMARTDRIVE scrive informazioni dalla memoria sul disco a volte quando altra attività del
disco è rallentata.
Si potrebbe utilizzare questa opzione se si sta spegnendo il PC e si vuole assicurare che
le informazioni cache sono state scritte sul disco.
SMARTDRIVE scrive tutte le informazioni cache sul disco se si riavvia il PC premendo
CTRL+ALT+CANC, ma non se si spegne o si preme il pulsante di riavvio.
/S Visualizza informazioni addizionali circa lo stato di SMARTDRIVE.
Controllare che SMARTDRIVE abbia completato l’opzione di cache di scrittura prima di
riavviare o spegnere il PC.
Questo non è necessario se si riavvia il PC premendo CTRL+ALT+CANC.
Per fare in modo che SMARTDRIVE scriva tutte le informazioni di cui è stato eseguito il
caching sui dischi, digitare SMARTDRV /C al prompt dei comandi.
Dopo che l’attività del disco è stata interrotta, è possibile riavviare il PC per sicurezza o
spegnere il PC.
SUBST
Associa un percorso ad una lettera di unità.
La lettera di unità assegnata rappresenta un’unità virtuale dato il suo possibile uso come
unità fisica all’interno dei comandi.
Non usare il comando SUBST quando Windows è in esecuzione.
SUBST [unità1: [unità2:]percorso]
SUBST unità1: /D
Opzione.
/D Elimina un’unità virtuale.
Per visualizzare i nomi delle unità virtuali attive, utilizzare la seguente sintassi.
SUBST
SYS
Crea un disco di avvio, copiando sul disco i file di sistema di MS-DOS, IO.SYS e
MSDOS.SYS, l’interprete dei comandi MS-DOS COMMAND.COM e la parte di MS-DOS
che fornisce accesso alle unità compresse DRVSPACE.BIN.
Il comando SYS copierà il file DRVSPACE.BIN solo se tale file si trova nella cartella
principale dell’unità o della directory di origine, IO.SYS, MSDOS.SYS e DRVSPACE.BIN
sono file nascosti e pertanto non compaiono negli elenchi delle cartelle visualizzate dal
comando DIR.
Per visualizzare questi file, digitare DIR /A.
SYS [unità1:][percorso] unità2:
TYPE
Visualizza il contenuto di un file di testo.
Utilizzare il comando TYPE per visualizzare un file di testo senza modificarlo.
TYPE [unità:][percorso]nomefile
MS-DOS
um 116 di 138
UNDELETE
Ripristina i file eliminati in precedenza con il comando, UNDELETE fornisce tre livelli di
protezione dei file da eliminazioni accidentali: metodo Sentry di eliminazione, metodo
Registro di eliminazione e metodo Standard.
UNDELETE [[unità:][percorso]nomefile] [/DT|/DS|/DOS]
UNDELETE [/LIST|/ALL|/PURGE[unità]|/STATUS|/LOAD|/UNLOAD|/S[unità ]|/Tunità [voci]]
Opzioni.
/LIST Elenca i file eliminati che sono disponibili per il recupero, ma non recupera alcun file.
Il parametro [unità:][percorso]nomefile e le opzioni /DT, /DS e /DOS controllano l’elenco
fornito dall’opzione.
/DOS Recupera soltanto i file elencati come file eliminati da MS-DOS, chiedendo conferma
per ciascuno di essi.
Se esiste un file di registrazione dell’eliminazione, l’opzione indica a UNDELETE di
ignorarlo.
/LOAD Carica nella memoria UNDELETE, un’applicazione residente in memoria,
utilizzando le informazioni definite nel file UNDELETE.INI.
Se il file UNDELETE.INI non esiste, UNDELETE utilizzerà i valori predefiniti.
/UNLOAD Rimuove la porzione di UNDELETE che risiede in memoria, impedendo in tal
modo il ripristino dei file eliminati.
UNFORMAT
Ripristina un disco cancellato dal comando FORMAT.
UNFORMAT ripristina solo unità disco rigido o floppy locali, mentre non può essere
utilizzato per ripristinare unità di rete.
Il comando UNFORMAT può inoltre ricostruire una tabella delle partizioni del disco
danneggiate su un’unità disco rigido.
UNFORMAT unità: [/L] [/TEST] [/P]
Opzioni.
/L Elenca tutti i file e le sotto cartelle trovate da UNFORMAT.
Se questa opzione non è specificata, UNFORMAT elenca solo le sotto cartelle e i file
frammentati.
Per sospendere lo scorrimento dell’elenco visualizzato, premere la combinazione di tasti
CTRL+S.
Per riprendere lo scorrimento, premere un tasto qualsiasi.
VER
Visualizza il numero della versione di MS-DOS.
VER
VOL
Visualizza l’etichetta di volume e il numero di serie del disco, se esistenti.
VOL [unità:]
XCOPY
Copia file ad eccezione dei file di sistema, nascosti e cartelle, incluse le sotto cartelle.
Con questo comando è possibile copiare tutti i file di una cartella, compresi i file nelle
MS-DOS
um 117 di 138
relative sotto cartelle.
XCOPY origine [destinazione] /Y|/-Y] [/A|/M] [/D:data] [/P] [/S] [/E] [/V] [/W]
Opzioni.
/Y Indica che XCOPY sostituisce i file esistenti senza chiedere conferma.
Per impostazione predefinita, se si specifica un file come file di destinazione, XCOPY
chiederà se si desidera sovrascrivere il file esistente.
Le versioni precedenti di MS-DOS sostituiscono semplicemente il file esistente.
Se il comando XCOPY è parte di un file batch, XCOPY si comporterà come nelle
precedenti versioni.
Specificando questa opzione si ha la precedenza su tutte le impostazioni predefinite e
correnti della variabile d’ambiente COPYCMD.
/-Y Indica che XCOPY chiede la conferma quando sostituisce un file esistente.
Specificando questa opzione si ha la precedenza su tutte le impostazioni predefinite e
correnti della variabile d’ambiente COPYCMD.
/P Chiede conferma alla creazione di ciascun file di destinazione con un messaggio.
/S Copia le cartelle e le sotto cartelle, purché non siano vuote.
Se è omessa questa opzione, XCOPY ha effetto solo all’interno di una singola cartella.
/E Copia qualsiasi sotto cartella, anche se vuota.
Con questa opzione è necessario utilizzare l’opzione /S.
ANSI.SYS
Definisce le funzioni che modificano gli elementi grafici dello schermo, controllano i
movimenti del cursore e riassegnano i tasti.
Il driver della periferica ANSI.SYS supporta l’emulazione terminale ANSI della sequenza di
escape per controllare lo schermo e la tastiera del sistema.
Una sequenza di escape ANSI è una sequenza di caratteri ASCII, i primi due dei quali
sono il carattere escape (1BH) e il carattere parentesi sinistra (5BH).
I caratteri che seguono questi due specificano un codice alfanumerico che controlla una
funzione della tastiera o dello schermo.
Le sequenze di escape ANSI rilevano la differenza tra lettere maiuscole e minuscole.
Le lettere “A” e “a”, ad esempio, hanno due significati completamente diversi.
Questo driver della periferica deve essere caricato da un comando.
DEVICE o DEVICEHIGH nel file CONFIG.SYS.
DEVICE=[unità:][percorso]ANSI.SYS [/X] [/K] [/R]
Opzioni.
[unità:][percorso] Specifica la posizione del file ANSI.SYS.
/X Riassegna i tasti estesi indipendentemente sulle tastiere a 101 tasti.
/K Fa sì che ANSI.SYS gestisca una tastiera a 101 tasti come una da 84 tasti.
È l’equivalente del comando SWITCHES=/K.
Se in genere si utilizza il comando SWITCHES=/K, sarà necessario utilizzare l’opzione /K
con il file ANSI.SYS.
/R Regola lo scorrimento delle righe per migliorare la leggibilità quando ANSI.SYS è
utilizzato con le applicazioni che facilitano l’utilizzo dei PC agli utenti con particolari
esigenze.
Parametri utilizzati nelle sequenze di escape ANSI.
Pn Parametro numerico, specifica un numero decimale.
Ps Parametro di selezione, specifica un numero decimale che è utilizzato per selezionare
una funzione.
È possibile specificare più funzioni separando i parametri con (;).
Pl Parametro di riga, specifica un numero decimale che rappresenta una delle righe sullo
MS-DOS
um 118 di 138
schermo o su un’altra periferica.
Pc Parametro di colonna, specifica un numero decimale che rappresenta una delle
colonne sullo schermo o su un’altra periferica.
Sequenze di escape ANSI per i movimenti del cursore, la grafica e le impostazioni della
tastiera: nel seguente elenco di sequenze di escape ANSI, l’abbreviazione ESC
rappresenta il carattere di escape ASCII 27 (1BH), che appare all’inizio di ciascuna
sequenza di escape.
ESC[PL;PcH Posizione del cursore: sposta il cursore in corrispondenza delle coordinate
specificate.
Se non è specificata alcuna posizione, il cursore sarà spostato nell’angolo superiore
sinistro dello schermo (riga 0, colonna 0), vale a dire nella stessa posizione di quando si
preme il tasto HOME.
Questa sequenza di escape funziona nello stesso modo della sequenza che segue.
ESC[PL;Pcf Posizione del cursore: questa sequenza di escape funziona nello stesso
modo della sequenza precedente.
ESC[PnA Cursore verso l’alto: sposta il cursore verso l’alto per il numero di righe
specificato senza cambiare colonna.
Se il cursore è già posto sulla prima riga, ANSI.SYS ignorerà la sequenza.
ESC[PnB Cursore verso il basso: sposta il cursore verso il basso per il numero di righe
specificato senza cambiare colonna.
Se il cursore è già posto sull’ultima riga, ANSI.SYS ignorerà la sequenza.
ESC[PnC Cursore in avanti: sposta il cursore verso la fine della riga per il numero di
colonne specificato senza cambiare riga.
Se il cursore è già posto nella colonna più a destra, ANSI.SYS ignorerà la sequenza.
ESC[PnD Cursore all’indietro: sposta il cursore verso l’inizio della riga per il numero di
colonne specificato senza cambiare riga.
Se il cursore è già posto nella colonna più a sinistra, ANSI.SYS ignorerà la sequenza.
ESC[s Salvataggio della posizione del cursore: salva la posizione corrente del cursore.
È possibile spostare il cursore alla posizione salvata utilizzando la sequenza per il
ripristino della posizione del cursore.
ESC[u Ripristino della posizione del cursore: sposta il cursore alla posizione memorizzata
dalla sequenza per il salvataggio della posizione del cursore.
ESC[2J Cancellazione di schermo: cancella il contenuto dello schermo e sposta il cursore
nell’angolo superiore sinistro (riga 0, colonna 0).
ESC[K Cancellazione di riga: cancella tutti i caratteri dalla posizione del cursore fino alla
fine della riga incluso il carattere in corrispondenza del cursore.
ESC[Ps;...;Psm Impostazione della modalità grafica: chiama le funzioni grafiche
specificate dai seguenti valori.
Queste funzioni specifiche rimangono attive fino alla successiva occorrenza di questa
sequenza di escape.
La modalità grafica modifica i colori e gli attributi di testo quali il grassetto e la
sottolineatura visualizzati.
Attributi di testo.
0 Tutti gli attributi disattivati.
1 Grassetto attivato.
4 Sottolineato (solo su schede video monocromatiche).
5 Lampeggiamento attivato.
7 Video inverso attivato.
8 Nascosto attivato.
Colori di primo piano.
30 Nero.
31 Rosso.
32 Verde.
33 Giallo.
MS-DOS
um 119 di 138
34 Blu.
35 Fucsia.
36 Azzurro.
37 Bianco.
Colori di sfondo.
40 Nero.
41 Rosso.
42 Verde.
43 Giallo.
44 Blu.
45 Fucsia.
46 Azzurro
47 Bianco.
I parametri compresi tra 30 e 47 sono conformi allo standard ISO (International Standard
Organization) 6429.
ESC[=psh Impostazione di modalità: modifica la larghezza dello schermo o il tipo di
modalità specificato da uno dei seguenti valori.
0 40 X 148 X 25 monocromatico (testo).
1 40 X 148 X 25 a colori (testo).
2 80 X 148 X 25 monocromatico (testo).
3 80 X 148 X 25 a colori (testo).
4 320 X 148 X 200 a 4 colori (grafica).
5 320 X 148 X 200 monocromatico (grafica).
6 640 X 148 X 200 monocromatico (grafica).
7 Attiva il ritorno a capo automatico delle righe.
13 320 X 148 X 200 a colori (grafica).
14 640 X 148 X 200 a colori (grafica a 16 colori).
15 640 X 148 X 350 monocromatico (grafica a 2 colori).
16 640 X 148 X 350 a colori (grafica a 16 colori).
17 640 X 148 X 480 monocromatico (grafica a 2 colori).
18 640 X 148 X 480 a colori (grafica a 16 colori).
19 320 X 148 X 200 a colori (grafica a 256 colori).
ESC[=Psl Ripristino di modalità: ripristina la modalità utilizzando gli stessi valori utilizzati
dall’Impostazione di modalità, eccetto il valore 7, che consente il ritorno a capo automatico
delle righe.
L’ultimo carattere in questa sequenza di escape è una lettera L minuscola.
ESC[codice;stringa;...p Impostazione delle stringhe da tastiera: imposta di nuovo un tasto
ad una stringa specificata.
I parametri sono definiti nel seguente modo.
o “Codice” corrisponde a uno o più valori elencati nella tabella che segue.
Questi valori rappresentano tasti e combinazioni di tasti.
Quando si utilizzano questi valori nel comando, è necessario digitare il punto e virgola (;)
indicato nella tabella oltre a quelli richiesti dalla sequenza di escape.
I codici racchiusi fra parentesi non sono disponibili su alcune tastiere.
ANSI.SYS non interpreterà tali codici per queste tastiere a meno che non sia specificata
l’opzione /X nel comando DEVICE in ANSI.SYS.
o “Stringa” è il codice ASCII per un singolo carattere o una stringa racchiusa tra virgolette
(“ ”).
Ad esempio, sia 65 sia “A” possono essere utilizzate per rappresentare una A maiuscola.
Alcuni valori nella seguente tabella non sono validi per tutti i PC.
Verificare nella documentazione del PC i valori che sono diversi.
Tasto Codice MAIUSC+codice CTRL+codice ALT+codice.
F1 0;59 0;84 0;94 0;104
F2 0;60 0;85 0;95 0;105
MS-DOS
um 120 di 138
F3 0;61 0;86 0;96 0;106
F4 0;62 0;87 0;97 0;107
F5 0;63 0;88 0;98 0;108
F6 0;64 0;89 0;99 0;109
F7 0;65 0;90 0;100 0;110
F8 0;66 0;91 0;101 0;111
F9 0;67 0;92 0;102 0;112
F10 0;68 0;93 0;103 0;113
F11 0;133 0;135 0;137 0;139
F12 0;134 0;136 0;138 0;140
HOME (Tn) 0;71 55 0;119 -Freccia SU (Tn) 0;72 56 (0;141) -PGSU (Tn) 0;73 57 0;132 -Freccia SINISTRA (Tn) 0;75 52 0;115 -Freccia DESTRA (Tn) 0;77 54 0;116 -FINE (Tn) 0;79 49 0;117 -Freccia GIÙ (Tn) 0;80 50 (0;145) -PGGIÙ (Tn) 0;81 51 0;118 -INS (Tn) 0;82 48 (0;146) -CANC (Tn) 0;83 46 (0;147) -HOME (224;71) (224;71) (224;119) (224;151)
Freccia SU (224;72) (224;72) (224;141) (224;152)
PGSU (224;73) (224;73) (224;132) (224;153)
Freccia SINISTRA (224;75) (224;75) (224;115) (224;155)
Freccia DESTRA (224;77) (224;77) (224;116) (224;157)
FINE (224;79) (224;79) (224;117) (224;159)
Freccia GIÙ (224;80) (224;80) (224;145) (224;154)
PGGIÙ (224;81) (224;81) (224;118) (224;161)
INS (224;82) (224;82) (224;146) (224;162)
CANC (224;83) (224;83) (224;147) (224;163)
STAMP -- -- 0;114 -PAUSA/INTERR -- -- 0;0 - BACKSPACE 8 8 127 (0)
INVIO 13 -- 10 (0
TAB 9 0;15 (0;148) (0;165)
NULL 0;3 - - - - -A 97 65 1 0;30
B 98 66 2 0;48
C 99 66 3 0;46
D 100 68 4 0;32
E 101 69 5 0;18
F 102 70 6 0;33
G 103 71 7 0;34
H 104 72 8 0;35
I 105 73 9 0;23
J 106 74 10 0;36
K 107 75 11 0;37
L 108 76 12 0;38
M 109 77 13 0;50
N 110 78 14 0;49
O 111 79 15 0;24
P 112 80 16 0;25
Q 113 81 17 0;16
R 114 82 18 0;19
MS-DOS
um 121 di 138
S 115 83 19 0;31
T 116 84 20 0;20
U 117 85 21 0;22
V 118 86 22 0;47
W 119 87 23 0;17
X 120 88 24 0;45
Y 121 89 25 0;21
Z 122 90 26 0;44
1 49 33 -- 0;120
2 50 64 0 0;121
3 51 35 -- 0;122
4 52 36 -- 0;123
5 53 37 -- 0;124
6 54 94 30 0;125
7 55 38 -- 0;126
8 56 42 -- 0;126
9 57 40 -- 0;127
0 48 41 -- 0;129
- 45 5 31 0;130
= 61 43 --- 0;131
[ 91 123 27 0;26
] 93 125 29 0;27
92 124 28 0;43
; 59 58 -- 0;39
‘ 39 34 -- 0;40
, 44 60 -- 0;51
. 46 62 -- 0;52
/ 47 63 -- 0;53
` 96 126 -- (0;41)
INVIO (Tn) 13 -- 10 (0;166)
/ (Tn) 47 47 (0;142) (0;74)
* (Tn) 42 (0;144) (0;78) -- (Tn) 45 45 (0;149) (0;164)
+ (Tn) 43 43 (0;150) (0;55)
5 (Tn) (0;76) 53 (0;143) –
DBLBUFF.SYS
Carica il driver della periferica DBLBUFF.SYS per eseguire la doppia bufferizzazione.
La doppia bufferizzazione crea compatibilità per certi controller di disco rigido che non
possono funzionare con la memoria fornita da EMM386 o Windows eseguito in modalità
386 avanzata.
Se durante l’installazione di Windows è determinato che il sistema necessita della doppia
bufferizzazione, sarà aggiunta la voce DoubleBuffer = 1 alla sezione [Options] di
MSDOS.SYS, che consentirà il caricamento automatico di DBLBUFF.SYS.
Per attivare manualmente la doppia bufferizzazione, è possibile aggiungere la voce
appena indicata nel file MSDOS.SYS oppure aggiungere un comando DEVICE nel file
CONFIG.SYS.
DEVICE=[unità:][percorso]DBLBUFF.SYS [/D+]
Opzioni.
[unità:][percorso] Specifica la posizione del file DBLBUFF.SYS.
/D+ Indica che DBLBUFF.SYS deve sempre eseguire la doppia bufferizzazione di tutto
l’I/O su disco.
MS-DOS
um 122 di 138
In base all’impostazione predefinita, la doppia bufferizzazione sarà eseguita solo per l’I/O
verso i blocchi di memoria superiore e sarà interrotta automaticamente se non risulterà
necessaria.
DISPLAY.SYS
Consente di visualizzare i set di caratteri internazionali sui monitor EGA (Enhanced
Graphics Adapter), VGA e LCD (Liquid Crystal Display).
Questo driver della periferica deve essere caricato da un comando DEVICE o
DEVICEHIGH nel file CONFIG.SYS.
DEVICE=[unità:][percorso]DISPLAY.SYS CON[:]=(tipo[,[tchw][,n]])
DEVICE=[unità:][percorso]DISPLAY.SYS CON[:]=(tipo[,[tchw][,(n,m)]])
Opzioni.
[unità:][percorso] Specifica la posizione del file DISPLAY.SYS.
tipo Specifica la scheda video in uso.
I valori validi includono EGA e LCD.
Il valore EGA supporta sia le schede EGA sia VGA.
Se è omesso il parametro “tipo”, DISPLAY.SYS eseguirà una verifica dell’H/W per
determinare il tipo di scheda video in uso.
Per “tipo” è inoltre possibile specificare i valori CGA (Color Graphics Adapter) e MONO,
ma non avranno alcun effetto in quanto la caratteristica di cambiamento del set di caratteri
non è attivata per queste periferiche.
tchw Specifica il numero del set di caratteri supportato dall’H/W in uso.
Nel seguente elenco sono indicati i set di caratteri che sono supportati da MS-DOS e il
paese e la lingua per ciascun set.
437 Statunitense.
850 Multilingue (Latina I).
852 Slava (Latina II).
860 Portoghese.
863 Franco-Canadese.
865 Nordica.
I set di caratteri aggiuntivi sono supportati dai file EGA2.CPI e EGA3.CPI.
n Specifica il numero di set di caratteri che può essere supportato dall’H/W in aggiunta al
set principale specificato nel parametro tchw.
I valori validi per n sono compresi tra 0 e 6.
Questo valore dipende dall’H/W.
Per le schede video EGA, il valore massimo per n è 6 per le schede video LCD, il valore
massimo per n è 1.
m Specifica il numero di caratteri secondari che può essere supportato dall’H/W per
ciascuna tabella codici.
Il valore predefinito è 2 se tipo è impostato a EGA, 1 se tipo è impostato a LCD.
DRVSPACE.SYS, DBLSPACE.SYS
Determina la posizione definitiva in memoria di DRVSPACE.BIN o DBLSPACE.BIN, la
parte di MS-DOS che fornisce l’accesso alle unità compresse.
DxxSPACE.SYS carica il driver in modalità reale nei blocchi di memoria superiore.
In questo modo è possibile risparmiare 60 K di memoria convenzionale quando si esegue
Windows 95 in modalità reale e almeno 100 K se si utilizza Microsoft Plus! Per Windows.
Quando si avvia il sistema, DRVSPACE.BIN o DBLSPACE.BIN è caricato insieme alle
altre funzioni del SO, prima che siano eseguiti i comandi nei file CONFIG.SYS e
AUTOEXEC.BAT.
Il file DXXSPACE.BIN è inizialmente caricato nella memoria convenzionale prima dei
driver della periferica che forniscono l’accesso alla memoria superiore.
MS-DOS
um 123 di 138
Quando si utilizza DRIVESPACE o DOUBLESPACE per creare un’unità compressa sul
PC, è aggiunto un comando per DxxSPACE.SYS al file CONFIG.SYS.
Nella sintassi che segue, al posto di DxxSPACE digitare il nome di file per l’applicazione
che si sta utilizzando.
DEVICE=[unità:][percorso]DxxSPACE.SYS /MOVE [/NOHMA] [/LOW]
DEVICEHIGH=[unità:][percorso]DxxSPACE.SYS /MOVE [/NOHMA] [/LOW]
Opzioni.
/MOVE Sposta DXXSPACE.BIN nella posizione definitiva in memoria.
Inizialmente DXXSPACE.BIN è caricato nella parte alta della memoria convenzionale.
Dopo che Windows ha terminato di eseguire i comandi nel file CONFIG.SYS,
DXXSPACE.BIN è spostato nella parte bassa della memoria convenzionale.
Quando DXXSPACE.SYS è caricato utilizzando il comando DEVICE, sposta
DXXSPACE.BIN dalla parte alta della memoria convenzionale a quella bassa.
In questo modo, possono essere evitati i conflitti con le applicazioni che sono caricate dal
file CONFIG.SYS e che richiedono l’accesso alla parte alta della memoria convenzionale.
Quando DXXSPACE.SYS è caricato utilizzando il comando DEVICEHIGH,
DXXSPACE.BIN è spostato nella memoria superiore, se disponibile.
Lo spostamento di DXXSPACE.BIN nella memoria superiore rende disponibile ulteriore
memoria convenzionale.
/NOHMA Fa in modo che DXXSPACE.SYS non sposti parte di DXXSPACE.BIN nell’area
di memoria alta HMA.
Se MS-DOS è caricato nell’HMA, DXXSPACE.SYS sposterà parte di DXXSPACE.BIN
nell’HMA se lo spazio disponibile è sufficiente.
Utilizzare quest’opzione se non si desidera che DXXSPACE.BIN utilizzi aree di memoria
alta.
/LOW Fa in modo che DXXSPACE.SYS non sia caricato nella parte alta della memoria
convenzionale.
Utilizzare quest’opzione se si dispone di un’applicazione per MS-DOS che non supporta
DRIVESPACE o DOUBLESPACE nella parte alta della memoria convenzionale.
L’utilizzo di quest’opzione farà sì che Windows non riutilizzi la memoria occupata da
DXXSPACE.SYS.
[unità:][percorso] Specifica la posizione del file Dxxspace.sys.
EGA.SYS
Salva e ripristina la visualizzazione quando il Task Swapper della Shell di MS-DOS è
utilizzato con i monitor EGA.
Se si dispone di un monitor EGA, sarà necessario installare il driver della periferica
EGA.SYS prima di utilizzare il Task Swapper.
Questo driver deve essere caricato da un comando DEVICE o DEVICEHIGH nel file
CONFIG.SYS.
DEVICE=[unità:][percorso]EGA.SYS
Opzioni.
[unità:][percorso] Specifica la posizione del file Ega.sys.
EMM386.EXE
Fornisce l’accesso all’area di memoria alta e utilizza la memoria estesa per simulare la
memoria espansa.
Questo driver della periferica deve essere caricato da un comando DEVICE nel file
CONFIG.SYS e può essere utilizzato solo su PC con CPU 80386 o superiore.
EMM386 utilizza la memoria estesa per simulare la memoria espansa per le applicazioni
MS-DOS
um 124 di 138
che utilizzano quest’ultimo tipo di memoria.
EMM386 rende inoltre possibile caricare le applicazioni e i driver della periferica nei
blocchi di memoria superiore UMB.
DEVICE=[unità:][percorso]EMM386.EXE [ON|OFF|AUTO] [memoria] [MIN=dim]
[W=ON|W=OFF] [Mx|FRAME=indirizzo|/Pmmmm] [Pn=indirizzo] [X=mmmm-nnnn]
[I=mmmm-nnnn] [B=indirizzo] [L=minXMS] [A=regalt] [H=handle] [D=nnn]
[RAM=mmmm-nnnn] [NOEMS] [NOVCPI] [HIGHSCAN] [VERBOSE] [WIN=mmmm-nnnn]
[NOHI] [ROM=mmmm-nnnn] [NOMOVEXBDA] [ALTBOOT] [NOBACKFILL]
Opzioni.
[unità:][percorso] Specifica la posizione del file Emm386.exe.
[ON|OFF|AUTO] Attiva il driver della periferica EMM386 se impostato a ON o sospende il
driver EMM386 se impostato a OFF oppure imposta il driver EMM386 alla modalità
automatica se impostato ad AUTO.
La modalità automatica attiva il supporto della memoria espansa e il supporto dei blocchi
della memoria superiore solo su richiesta di un’applicazione.
Il valore predefinito è ON.
Utilizzare il comando EMM386 per modificare questo valore una volta che EMM386 è
stato avviato.
memoria Specifica la quantità massima di memoria estesa in KB che EMM386 deve
fornire come memoria EMS/VCPI.
Questa quantità è aggiunta alla memoria utilizzata per i blocchi di memoria superiore e per
lo stesso EMM386.
Il valori per “memoria” sono compresi tra 64 e il valore minore tra 32768 e la quantità di
memoria estesa disponibile quando EMM386 è caricato.
Il valore predefinito è la quantità di memoria estesa disponibile.
Se si specifica NOEMS, il valore predefinito sarà 0.
EMM386 arrotonda il valore per difetto al precedente multiplo di 16.
MIN=dim Specifica la quantità minima di memoria EMS/VCPI in KB che sarà fornita da
EMM386, se quella quantità è disponibile.
EMM386 riserva questa quantità di memoria estesa da utilizzare come memoria
EMS/VCPI quando è caricato tramite il comando DEVICE=EMM386.EXE nel file
CONFIG.SYS.
È possibile che EMM386 fornisca ulteriore memoria EMS/VCPI fino alla quantità
specificata dal parametro “memoria” se è disponibile sufficiente memoria XMS quando
un’applicazione richiede della memoria EMS/VCPI.
I valori sono compresi tra zero e il valore specificato dal parametro “memoria”.
Il valore predefinito è 256.
Se si specifica NOEMS, il valore predefinito sarà 0.
Se il valore di MIN è maggiore del valore di “memoria”, EMM386 utilizzerà il valore
specificato da MIN.
W=ON|W=OFF Attiva o disattiva il supporto per il coprocessore Weitek.
L’impostazione predefinita è W=OFF.
Mx Specifica l’indirizzo del frame di pagina.
I valori validi per “x” sono compresi tra 1 e 14.
Nel seguente elenco è indicato ciascun valore e l’indirizzo di base associato in formato
esadecimale.
1 => C000H 8 => DC00H
2 => C400H 9 => E000H
3 => C800H 10 => 8000H
4 => CC00H 11 => 8400H
5 => D000H 12 => 8800H
6 => D400H 13 => 8C00H
MS-DOS
um 125 di 138
7 => D800H 14 => 9000H
I valori compresi tra 10 e 14 devono essere utilizzati solo su PC che dispongono di 512 KB
di memoria.
FRAME=indirizzo Specifica direttamente la base di un segmento di frame di pagina.
Per impostare uno specifico indirizzo di base di segmento, utilizzare l’opzione FRAME,
quindi specificare l’indirizzo desiderato.
I valori validi per l’indirizzo sono compresi tra 8000H e 9000H e tra C000H e E000H, con
incrementi di 400H.
Per fornire memoria espansa e disattivare il frame di pagina, è possibile specificare
FRAME=NONE.
Quest’impostazione può tuttavia impedire il corretto funzionamento di alcune applicazioni
che richiedono l’utilizzo della memoria espansa.
/Pmmmm Specifica l’indirizzo del frame di pagina.
I valori validi per mmmm sono compresi tra 8000H e 9000H e tra C000H e E000H, con
incrementi di 400H.
Pn=indirizzo Specifica l’indirizzo di un segmento di una pagina specifica, dove n è il
numero della pagina specificata e indirizzo è l’indirizzo del segmento desiderato.
I valori validi per n sono compresi tra 0 e 255.
Quelli per indirizzo sono compresi tra 8000H e 9C00H e tra C000H e EC00H, con
incrementi di 400H.
Gli indirizzi per le pagine da 0 a 3 devono essere contigui al fine di mantenere la
compatibilità con la versione 3.2 delle specifiche per la memoria espansa LIM EMS.
Se si utilizza l’opzione “Mx”, FRAME o “/Pmmmm”, non sarà possibile specificare gli
indirizzi per le pagine da 0 a 3 per l’opzione “/Pmmmm”.
X=mmmm-nnnn Impedisce a EMM386 di utilizzare un particolare intervallo d’indirizzi di
segmenti per una pagina EMS o per i blocchi di memoria superiore.
I valori validi per mmmm e nnnn sono compresi tra A000H e FFFFH e sono arrotondati per
difetto al precedente limite di 4 KB.
L’opzione X ha la precedenza sull’opzione I se i due intervalli si sovrappongono.
I=mmmm-nnnn Specifica un intervallo d’indirizzi di segmenti da utilizzare per una pagina
EMS o per i blocchi di memoria superiore.
I valori validi per mmmm e nnnn sono compresi tra A000H e FFFFH e sono arrotondati per
difetto al precedente limite di 4 KB.
L’opzione X ha la precedenza sull’opzione I se i due intervalli si sovrappongono.
B=indirizzo Specifica l’indirizzo di segmento più basso disponibile per il banking della
memoria espansa swapping di 16 KB di pagine.
I valori validi sono compresi tra 1000H e 4000H, il valore predefinito è 4000H.
l=minXMS fa sì che la quantità di memoria espansa specificata in KB sia ancora
disponibile dopo il caricamento di EMM386.
Il valore predefinito è 0.
A=regalt Specifica la quantità di set di registri a rapido avvicendamento utilizzati per la
funzionalità multitasking che è possibile allocare a EMM386.
I valori validi sono compresi tra 0 e 254.
Il valore predefinito è 7.
Ciascun set di registri aggiunge circa 200 byte alle dimensioni di EMM386 in memoria.
H=handle Specifica la quantità di handle che possono essere utilizzati da EMM386.
I valori validi sono compresi tra 2 e 255.
Il valore predefinito è 64.
D=nnn Specifica la quantità di KB di memoria che deve essere riservata per l’accesso
diretto alla memoria DMA bufferizzato.
A parte il DMA del disco floppy, questo valore deve riflettere il maggiore trasferimento
DMA che sarà eseguito mentre EMM386 è attivo.
I valori validi per nnn sono compresi tra 16 e 256.
Il valore predefinito è 32.
MS-DOS
um 126 di 138
RAM=mmmm-nnnn Specifica un intervallo d’indirizzi di segmenti da utilizza re per i blocchi
di memoria superiore.
Inoltre, attiva il supporto EMS.
Se non è specificato alcun intervallo, EMM386 utilizzerà tutto lo spazio disponibile della
scheda per creare i blocchi di memoria superiore e un frame di pagina per l’EMS.
NOEMS Fornisce l’accesso all’area della memoria superiore ma impedisce di accedere
alla memoria espansa.
NOVCPI Disattiva il supporto per le applicazioni VCPI.
Quest’opzione deve essere utilizzata insieme all’opzione NOEMS.
Se NOVCPI è specificata senza l’opzione NOEMS, EMM386 non disattiverà il supporto
per la VCPI.
Se sono specificate entrambe le opzioni, EMM386 ignorerà il parametro memoria e
l’opzione MIN.
La disattivazione del supporto per le applicazioni VCPI riduce la quantità di memoria
estesa allocata.
HIGHSCAN Specifica che EMM386 effettua un ulteriore controllo per determinare la
disponibilità di memoria superiore da utilizzare come blocchi di memoria superiore o
finestre EMS.
Su alcuni PC, l’utilizzo di quest’opzione può non avere alcun effetto o far sì che EMM386
consideri disponibili delle aree di memoria superiore che in realtà non lo sono.
In questo caso, è possibile che il sistema si arresti.
VERBOSE fa sì che EMM386 visualizzi dei messaggi di errore o di stato durante il
caricamento.
In base all’impostazione predefinita, EMM386 visualizza dei messaggi solo nel caso in cui
si verifichi una condizione di errore.
È possibile abbreviare VERBOSE a V.
Per visualizzare i messaggi di stato senza aggiungere l’opzione VERBOSE, premere e
tenere premuto ALT mentre EMM386 è avviato.
WIN=mmmm-nnnn Riserva l’intervallo d’indirizzi di segmenti specificato per Windows
anziché per EMM386.
I valori validi per mmmm e nnnn sono compresi tra A000H e FFFFH e sono arrotondati per
difetto al precedente limite di 4 KB.
L’opzione X ha la precedenza sull’opzione WIN se i due intervalli si sovrappongono.
L’opzione WIN ha la precedenza sulle opzioni RAM, ROM e I se i rispettivi intervalli si
sovrappongono.
[NOHI] non consente il caricamento di EMM386 nell’area di memoria superiore.
In genere, parte di EMM386 è caricata nella memoria superiore.
L’utilizzo di quest’opzione riduce la memoria convenzionale disponibile e aumenta l’area di
memoria superiore disponibile per gli UMB.
[ROM=mmmm-nnnn] Specifica un intervallo di indirizzi di segmenti che EMM386 utilizza
per la RAM shadow, memoria ad accesso casuale utilizzata per la ROM.
I valori validi per mmmm e nnnn sono compresi tra A000H e FFFFH e sono arrotondati per
difetto al precedente limite di 4 KB.
L’utilizzo di quest’opzione può rendere il sistema più veloce se questo non dispone già di
RAM shadow.
[NOMOVEXBDA] Impedisce a EMM386 di spostare i dati del BIOS esteso dalla memoria
convenzionale a quella superiore.
[ALTBOOT] Specifica che EMM386 utilizza un handler alternativo per riavviare il sistema
quando è premuto CTRL+ALT+CANC.
Utilizzare quest’opzione solo se il sistema si arresta o funziona in modo non corretto dopo
che è stato caricato EMM386 e si è premuto CTRL+ALT+CANC.
[NOBACKFILL] se EMM386 è configurato per fornire i blocchi di memoria superiore
utilizzando l’opzione NOEMS o RAM, EMM386 riempirà automaticamente di nuovo la
memoria convenzionale fino a 640 KB.
MS-DOS
um 127 di 138
Tuttavia, poiché Windows non supporta questo tipo di operazione, sarà necessario
utilizzare l’opzione NOBACKFILL se il PC in uso dispone di meno di 640 KB di memoria
convenzionale.
HIMEM.SYS
HIMEM è un gestore della memoria estesa, un’utility che coordina l’utilizzo della memoria
estesa del PC, inclusa HMA, in modo che due applicazioni o due driver di periferica non
utilizzino contemporaneamente la stessa memoria.
HIMEM è installato aggiungendo il comando DEVICE per il file HIMEM.SYS nel file
CONFIG.SYS.
La riga di comando per HIMEM.SYS deve precedere qualsiasi comando che avvia
applicazioni o driver di periferica che utilizzano la memoria estesa.
Ad esempio, la riga di comando per HIMEM.SYS deve precedere quella per
EMM386.EXE.
DEVICE=[unità:][percorso]HIMEM.SYS [/A20CONTROL:ON|OFF] [/CPUCLOCK:ON|OFF]
[/EISA] [/HMAMIN=m] [/INT15=xxxx] [/MACHINE:xxxx] [/NOABOVE16] [/NOEISA]
[/NUMHANDLES=n] [/SHADOWRAM:ON|OFF] [/TESTMEM:ON|OFF] [/VERBOSE] [/X]
Nella maggior parte dei casi, non sarà necessario specificare delle opzioni della riga di
comando.
I valori predefiniti per HIMEM.SYS sono studiati per funzionare con la maggior parte
dell’H/W.
[unità:][percorso] Specifica la posizione del file HIMEM.SYS che deve sempre trovarsi
sulla stessa unità che contiene i file di MS-DOS.
Se il file si trova nella cartella principale dell’unità di avvio, non sarà necessario includere
alcun percorso.
Sarà comunque necessario includere il nome di file completo.
/A20CONTROL:ON|OFF Specifica se HIMEM deve controllare la riga A20 anche se tale
riga era attiva nel momento in cui HIMEM è stato caricato.
L’handler A20 forisce l’accesso all’HMA.
Se è specificato /A20CONTROL:OFF, HIMEM controllerà la riga A20 solo se A20 era
disattivata quando HIMEM è stato caricato, il valore predefinito è il seguente.
/A20CONTROL:ON.
/CPUCLOCK:ON|OFF Specifica se HIMEM deve influire sulla velocità dell’orologio del PC.
Se la velocità dell’orologio cambia quando s’installa HIMEM, sarà possibile correggere il
problema specificando /CPUCLOCK:ON.
Se è attivata quest’opzione, sarà tuttavia rallentato HIMEM.
Il valore predefinito è /CPUCLOCK:OFF.
/EISA Specifica che HIMEM deve allocare tutta la memoria estesa disponibile.
Quest’opzione è necessaria solo sui PC EISA (Extended Industry Standard Architecture)
con più di 16 MB di memoria.
Sugli altri PC, HIMEM alloca automaticamente tutta la memoria estesa disponibile.
/HMAMIN=m Specifica la quantità di memoria richiesta da un’applicazione perché HIMEM
gli consenta l’uso dell’HMA.
L’HMA può essere utilizzata da una sola applicazione alla volta.
HIMEM alloca l’HMA alla prima applicazione che dispone dei requisiti di utilizzo della
memoria impostati per quest’opzione.
È possibile specificare un valore compreso tra 0 e 63.
Impostare /HMAMIN alla quantità di memoria richiesta dall’applicazione che utilizza la
quantità maggiore di memoria HMA.
L’opzione /HMAMIN non è necessaria, il valore predefinito è infatti 0.
Se si omette quest’opzione o la s’imposta a 0, HIMEM allocherà l’HMA alla prima
applicazione che la richiede, indipendentemente dalla quantità che sarà effettivamente
MS-DOS
um 128 di 138
utilizzata.
L’opzione /HMAMIN non ha alcun effetto quando Windows è eseguito in modalità 386
avanzata.
/INT15=xxxx alloca la quantità di memoria estesa in KB che deve essere riservata
all’interfaccia dell’Interrupt 15H.
Alcune precedenti applicazioni allocano la memoria estesa utilizzando questa interfaccia al
posto del metodo XMS fornito da HIMEM.
Se si utilizzano queste applicazioni, è possibile garantirsi una quantità sufficiente di
memoria disponibile impostando “xxxx” a 64 KB in più rispetto alla quantità richiesta dalle
applicazioni.
È possibile specificare un valore compreso tra 64 e 65535.
Tuttavia, non è possibile specificare più memoria di quanta il sistema ne abbia a
disposizione.
Se è specificato un valore minore di 64, il valore diventerà pari a 0.
Il valore predefinito è 0.
/MACHINE:xxxx Specifica il tipo di PC in uso.
In genere, HIMEM è in grado di rilevare il tipo di PC, tuttavia esistono alcuni PC che non è
possibile rilevare.
Su questi sistemi, HIMEM utilizza il tipo predefinito, IBM AT o compatibile.
È possibile che sia necessario includere l’opzione /MACHINE se il PC in uso è di un tipo
che HIMEM non è in grado di rilevare e se HIMEM non funziona correttamente con
impostato il tipo di sistema predefinito.
/NOABOVE16 Specifica di non utilizzare il supporto INT 15H AX==E801H Compaq
Bigmem per l’analisi della memoria estesa.
/NOEISA Specifica che HIMEM non deve eseguire l’analisi EISA per la memoria estesa.
/NUMHANDLES=n specifica il numero massimo di handle ai blocchi di memoria estesa
EMB che possono essere utilizzati contemporaneamente.
È possibile specificare un valore compreso tra 1 e 128.
Il valore predefinito è 32.
Ciascun handle aggiuntivo richiede altri 6 byte di memoria.
L’opzione /NUMHANDLES non ha alcun effetto quando Windows è eseguito in modalità
386 avanzata.
/SHADOWRAM:ON|OFF Specifica se disattivare la RAM shadow SHADOWRAM:OFF o
se lasciarla attivata SHADOWRAM:ON.
Alcuni PC rendono l’esecuzione del codice ROM più veloce tramite il shadowing nella
RAM, vale a dire copiando all’avvio il codice ROM nella più veloce memoria RAM, che
utilizza la memoria estesa.
Sui PC che utilizzano la RAM shadow e dispongono di meno di 2 MB di RAM, HIMEM in
genere tenta di disattivare la RAM shadow per recuperare della memoria estesa
aggiuntiva per Windows.
HIMEM è in grado di disattivare la RAM shadow solo su certi tipi di sistemi.
Quando HIMEM disattiva la RAM shadow, il codice ROM è eseguito nella memoria ROM
anziché nella RAM, che è più veloce.
Per questo motivo, il PC sarà leggermente più lento di prima.
/TESTMEM:ON|OFF Determina se HIMEM esegue una verifica della memoria quando è
avviato il PC.
In base all’impostazione predefinita, HIMEM verifica l’affidabilità della memoria estesa del
PC ad ogni avvio del PC.
Questa verifica consente d’identificare la memoria che non è più affidabile e che può
determinare l’instabilità del sistema o la perdita di dati.
La verifica eseguita da HIMEM è più completa di quella standard che è eseguita
all’accensione nella maggior parte dei PC.
Per evitare la verifica di HIMEM, specificare /TESTMEM:OFF.
La disattivazione della verifica della memoria abbrevia il processo di avvio del sistema.
MS-DOS
um 129 di 138
L’impostazione predefinita è /TESTMEM:ON.
/VERBOSE Fa sì che HIMEM visualizzi dei messaggi di errore o di stato durante il
caricamento.
In base all’impostazione predefinita, HIMEM visualizza dei messaggi solo nel caso in cui si
verifichi una condizione di errore.
È possibile abbreviare VERBOSE a V.
Per visualizzare i messaggi di stato senza aggiungere l’opzione VERBOSE, premere e
tenere premuto ALT mentre HIMEM è avviato.
/X Specifica di non utilizzare INT 15H AX==E820H, l’API di supporto alla memoria estesa.
RAMDRIVE.SYS
Utilizza parte della RAM del PC per simulare un’unità disco rigido.
Questo driver della periferica deve essere caricato tramite un comando DEVICE o
DEVICEHIGH nel file CONFIG.SYS.
Le unità RAM sono molto più veloci delle unità disco rigido in quanto il PC può leggere le
informazioni più velocemente dalla memoria che dal disco rigido.
Un’unità RAM si presenta come una normale unità disco rigido e può essere utilizzata
come una qualsiasi unità disco rigido.
La differenza più importante fra questi due tipi di unità consiste nel fatto che l’unità RAM
esiste solo nella memoria.
Le informazioni contenute in un’unità RAM sono perse ogni volta che si spegne o si riavvia
il PC.
È possibile creare quante unità RAM si desidera, fino ad utilizzare tutta la memoria
disponibile sul PC.
A tal fine, aggiungere una riga RAMDRIVE.SYS nel file CONFIG.SYS per ciascuna unità
RAM aggiuntiva desiderata.
DEVICE=[unità:][percorso]RAMDRIVE.SYS [DimDisco DimSettore [Numvoci]]][/E | /A]
Opzioni.
[unità:][percorso] Specifica la posizione del file RAMDRIVE.SYS.
DimDisco specifica la quantità di KB di memoria che si desidera utilizzare per l’unità RAM.
Ad esempio, per creare un’unità RAM da 640 KB, occorrerà specificare 640.
Se non è specificato alcun valore, RAMDRIVE creerà un’unità RAM da 64 KB.
È possibile specificare un valore compreso tra 4 e 32767.
Non è in ogni caso possibile specificare una quantità di memoria superiore a quella
disponibile nel sistema.
DimSettore specifica la dimensione in byte dei settori del disco.
La dimensione può essere uguale a 128, 256 o 512 byte.
Se è specificato un valore per DimSettore, sarà necessario specificarlo anche per
DimDisco.
In genere, è utilizzata la dimensione predefinita di 512 byte.
NumVoci limita il numero di file e di cartelle che è possibile creare nella cartella principale
dell’unità RAM.
Il limite varia da 2 a 1024 voci.
Il limite che è specificato è arrotondato per eccesso al successivo limite di dimensione dei
settori.
Se non è specificato alcun limite, sarà possibile creare fino a 64 voci nella cartella
principale dell’unità RAM.
Se è specificato un valore per NumVoci, sarà necessario specificarlo anche per DimDisco
e DimSettore.
Se non si dispone di memoria sufficiente per creare l’unità RAM come specificato,
RAMDRIVE tenterà di crearla con il limite di 16 voci di directory.
L’unità RAM sarà creata, ma probabilmente avrà un limite diverso da quello desiderato.
MS-DOS
um 130 di 138
/E Crea l’unità RAM nella memoria estesa.
Affinché RAMDRIVE utilizzi la memoria estesa, è necessario che il PC sia configurato
adeguatamente e che nel file CONFIG.SYS il comando DEVICE per il gestore della
memoria estesa quale HIMEM.SYS preceda il comando DEVICE relativo a
RAMDRIVE.SYS.
In genere, è meglio creare un’unità RAM nella memoria estesa se questa è disponibile su
PC in uso.
/A Crea l’unità RAM nella memoria espansa.
Affinché RAMDRIVE utilizzi la memoria espansa, è necessario che il PC sia configurato
adeguatamente e che nel file CONFIG.SYS il comando DEVICE per il gestore della
memoria espansa quale EMM386, 386MAX, CEMM o QEMM preceda il comando
DEVICE relativo a RAMDRIVE.SYS.
SETVER.EXE
Carica in memoria la tabella della versione di MS-DOS.
Questo driver deve essere caricato utilizzando un comando DEVICE o DEVICEHIGH nel
file CONFIG.SYS.
SETVER.EXE carica in memoria la tabella della versione di MS-DOS, nella quale sono
elencati i nomi delle applicazioni e il numero di versione di MS-DOS con cui ciascuna
applicazione deve essere eseguita.
DEVICE=[unità:][percorso]SETVER.EXE
Opzioni.
[unità:][percorso] Specifica la posizione del file SETVER.EXE.
ACCDATE
Per ciascun disco rigido, specificare se deve essere registrata la data in cui è stato
eseguito l’ultimo accesso ai file.
Le date di accesso sono disattivate per tutte le unità quando il PC è avviato in modalità
provvisoria.
In base all’impostazione predefinita, le date non sono registrate per i dischi floppy.
ACCDATE=unità1+|- [unità2+|-]
Opzioni.
Il segno più (+) indica che la data dell’ultimo accesso ai file sull’unità deve essere
memorizzata.
Il segno meno (-) indica che la data dell’ultimo accesso ai file non deve essere
memorizzata.
BREAK
Imposta o disattiva la funzionalità estesa di CTRL+C.
Questo comando può essere digitato al prompt dei comandi o utilizzato nel file
CONFIG.SYS.
È possibile premere CTRL+C per arrestare un’applicazione o un’operazione ad esempio,
l’ordinamento di file.
In genere, MS-DOS verifica CTRL+C solo quando legge dalla tastiera o scrive sullo
schermo o su una stampante.
Se s’imposta BREAK a ON, la funzionalità CTRL+C sarà estesa anche ad altre funzioni,
quali le operazioni di lettura e scrittura di un disco.
BREAK [ON|OFF]
MS-DOS
um 131 di 138
Per visualizzare l’impostazione corrente di BREAK al prompt dei comandi, utilizzare la
seguente sintassi: BREAK.
Nel file CONFIG.SYS, utilizzare invece la seguente sintassi: BREAK=ON|OFF.
ON| OFF Attiva o disattiva la funzionalità estesa CTRL+C.
BUFFERS/BUFFERSHIGH
Alloca memoria per un numero specificato di buffer su disco all’avvio del sistema.
Utilizzare il comando BUFFERSHIGH per caricare i buffer nella memoria superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
BUFFERS=n[,m]
BUFFERSHIGH=n[,m]
Opzioni.
n Specifica il numero di buffer su disco.
Il valore di n deve essere compreso tra 1 e 99.
Il valore predefinito è 30.
m specifica il numero di buffer presenti nella cache secondaria.
Il valore di m deve essere compreso tra 0 e 8.
Il valore predefinito è 0 vale a dire, nessun buffer nella cache secondaria.
Se è specificato un valore non valido per n o m, sarà utilizzata automaticamente
l’impostazione predefinita.
COUNTRY
Consente a MS-DOS di utilizzare le convenzioni specifiche di un paese per la
visualizzazione della data, dell’ora e della valuta; per determinare l’ordine con cui i
caratteri sono ordinati e per determinare quali caratteri possono essere utilizzati nei nomi
di file.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
Il comando COUNTRY configura MS-DOS in modo che riconosca il set di caratteri e le
convenzioni di punteggiatura specifici della lingua selezionata.
COUNTRY=xxx[,[yyy][,[unità:][percorso]nomefile]]
Opzioni.
xxx Specifica il codice del paese.
yyy Specifica il set di caratteri per il paese.
[unità:][percorso]nomefile Specifica la posizione e il nome del file che contiene le
informazioni sul paese.
DEVICE
Carica in memoria il driver della periferica specificato.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
DEVICE=[unità:][percorso]nomefile [parametri-dp]
Opzioni.
[unità:][percorso]nomefile Specifica la posizione e il nome del driver della periferica da
caricare.
[parametri-dp] Specifica qualsiasi informazione sulla riga di comando richiesta dal driver
della periferica.
DEVICEHIGH
Carica nella memoria superiore il driver della periferica specificato.
MS-DOS
um 132 di 138
Questa operazione consente di rendere disponibili ulteriori byte nella memoria
convenzionale, che possono essere utilizzati per altre applicazioni.
Se non è disponibile spazio nella memoria superiore, il comando DEVICEHIGH avrà la
stessa funzione del comando DEVICE.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
DEVICEHIGH [unità:][percorso]nomefile [parametri-dp]
Per specificare l’area o le aree di memoria in cui caricare il driver della periferica, utilizzare
la seguente sintassi.
DEVICEHIGH [[/L:area1[,dimmin1][;area2[,dimmin2] [/S]]=
[unità:][percorso]nomefile [parametri-dp]
Opzioni.
[unità:][percorso]nomefile Specifica la posizione e il nome del driver della periferica da
caricare nella memoria superiore.
parametri-dp Specifica qualsiasi informazione sulla riga di comando richiesta dal driver
della periferica.
/L:area1[,dimmin1][;area2[,dimmin2] Specifica una o più aree di memoria nelle quali
caricare il driver della periferica.
In base all’impostazione predefinita, MS-DOS carica il driver nel blocco di memoria
superiore più grande disponibile UMB e rende tutti gli altri blocchi di memoria superiore
disponibili per l’utilizzo del driver.
È possibile utilizzare l’opzione /L per caricare il driver della periferica in una specifica area
di memoria oppure indicare le aree che il driver può utilizzare.
Per caricare il driver nel blocco più grande di un’area specifica della memoria superiore,
specificare il numero dell’area dopo l’opzione /L.
Ad esempio, per caricare il driver nel blocco dell’area 4, sarà necessario digitare /L:4.
Per visualizzare l’elenco delle aree di memoria disponibili, digitare MEM /F al prompt dei
comandi.
Quando è caricato utilizzando l’opzione /L, il driver della periferica può utilizzare solo l’area
di memoria specificata.
Alcuni driver utilizzano più aree di memoria, quindi è necessario specificare le aree.
Per sapere come la memoria è utilizzata da un driver, digitare il comando MEM /M e
specificare il nome del driver come argomento.
Per specificare due o più aree, separare i numeri dei blocchi con un punto e virgola (;).
Ad esempio, per utilizzare i blocchi 2 e 3, sarà necessario digitare /L:2;3.
In genere, MS-DOS carica un driver in un blocco di memoria superiore nell’area
specificata solo se l’area contiene un blocco più grande delle dimensioni di caricamento
del driver, che in genere corrispondono alle dimensioni del file eseguibile.
Se il driver in esecuzione richiede più memoria di quando è caricato, sarà possibile
utilizzare il parametro dimmin per assicurarsi che il driver non sia caricato in un blocco di
memoria superiore troppo piccolo.
Se si specifica un valore per il parametro dimmin, MS-DOS caricherà il driver in quell’area
solo se questa contiene un blocco di memoria superiore più grande delle dimensioni di
caricamento del driver e del valore di dimmin.
/S Riduce alle dimensioni minime il blocco di memoria superiore durante il caricamento del
driver.
Questa opzione consente un utilizzo più efficiente della memoria.
È in genere utilizzata solo dall’utility MEMMAKER, che analizza l’utilizzo della memoria per
un driver di periferica per determinare se l’opzione /S può essere utilizzata per il
caricamento del driver.
Questa opzione può essere utilizzata solo insieme all’opzione /L e interessa solo i blocchi
MS-DOS
um 133 di 138
di memoria superiore per i quali è stata specificata una dimensione minima.
DOS
Specifica che MS-DOS deve mantenere un collegamento all’area di memoria superiore,
deve essere in parte caricato nell’area di memoria alta HMA o in entrambe.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
DOS=HIGH|LOW[,UMB|,NOUMB][,AUTO|,NOAUTO]
DOS=[HIGH,|LOW,]UMB|NOUMB[,AUTO|,NOAUTO]
DOS=[HIGH,|LOW,][UMB,|NOUMB,]AUTO|NOAUTO
Opzioni.
UMB|NOUMB Specifica se MS-DOS deve gestire i blocchi di memoria superiore creati da
un provider di questi tipi di blocchi, quale EMM386.EXE.
Il parametro UMB specifica che gli eventuali blocchi devono essere gestiti da MS-DOS.
Il parametro NOUMB specifica che MS-DOS non deve gestire i blocchi di memoria
superiore.
L’impostazione predefinita è NOUMB.
HIGH|LOW Specifica se una parte di MS-DOS deve essere caricata nell’area di memoria
alta (HIGH) o se MS-DOS deve rimanere interamente nella memoria convenzionale
(LOW).
L’impostazione predefinita è LOW.
AUTO|NOAUTO Specifica se i driver di periferica HIMEM.SYS, IFSHLP.SYS,
DBLBUFF.SYS e SETVER.EXE devono essere automaticamente caricati da MS-DOS, se
non sono esplicitamente caricati nel file CONFIG.SYS.
L’impostazione predefinita AUTO carica automaticamente i driver.
L’impostazione AUTO utilizza inoltre automaticamente i comandi BUFFERSHIGH,
FILESHIGH, FCBSHIGH, LASTDRIVEHIGH e STACKSHIGH, indipendentemente
dall’utilizzo della forma -HIGH del comando.
Se si specifica il parametro NOAUTO, sarà necessario caricare esplicitamente i driver di
periferica e utilizzare la forma -HIGH dei comandi appena indicati per ottenere le migliori
prestazioni.
DRIVPARM
Definisce i parametri per le periferiche, quali le unità disco o le unità nastro quando è
avviato MS-DOS.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
Il comando DRIVPARM modifica i parametri dell’unità fisica esistente.
Non crea una nuova unità logica.
Le impostazioni specificate nel comando DRIVPARM ignorano le definizioni del driver per
qualsiasi periferica a blocchi precedente.
DRIVPARM=/D:numero [/C] [/F:fattore] [/H:intestazioni] [/I] [/N] [/S:settori] [/T:tracce]
Opzioni.
/D:numero Specifica il numero dell’unità fisica.
I valori per numero devono essere compresi tra 0 e 255 ad esempio, il numero 0 = unità A,
1 = unità B, 2 = unità C.
/C Specifica che l’unità è in grado di rilevare se la porta dell’unità è chiusa.
/F:fattore Specifica il tipo di unità.
Nella tabella che segue sono elencati i valori validi per fattore e delle brevi descrizioni per
ciascuno di essi.
Il valore predefinito è 2.
0 160 KB/180 KB o 320 KB/360 KB.
MS-DOS
um 134 di 138
1 1.2 MB.
2 720 KB.
5 Disco rigido
6 Nastro.
7 1.44 MB.
8 Disco ottico di lettura e scrittura.
9 2.88 MB.
/H:intestazioni Specifica il numero massimo d’intestazioni.
I valori per intestazioni devono essere compresi tra 1 e 99.
Il valore predefinito dipende dal valore specificato per /F:fattore.
/I Specifica un’unità disco da 3”½ elettronicamente compatibile.
Le unità elettronicamente compatibili sono installate sul PC e utilizzano il controller
esistente dell’unità disco floppy.
Utilizzare l’opzione /I se il BIOS ROM non supporta le unità disco floppy da 3”½.
/N Specifica una periferica a blocchi non removibile.
/S:settori Specifica il numero di settori per traccia supportato dalla periferica a blocchi.
I valori per settori devono essere compresi tra 1 e 99.
Il valore predefinito dipende dal valore specificato per /F:fattore.
/T:tracce Specifica il numero di tracce per lato supportato dalla periferica a blocchi.
Il valore predefinito dipende dal valore specificato per /F:fattore.
FCBS, FCBSHIGH
Specifica il numero di blocchi di controllo file FCB che possono essere aperti da MS-DOS
contemporaneamente.
Utilizzare il comando FCBSHIGH per caricare i blocchi di controllo file nella memoria
superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
Un blocco di controllo file è una struttura di dati in cui sono memorizzate le informazioni
per un file.
FCBS=x
FCBSHIGH=x
Opzioni.
x Specifica il numero di blocchi di controllo file che possono essere aperti in MS-DOS
contemporaneamente.
I valori validi per x sono compresi tra 1 e 255.
Il valore predefinito è quattro.
FILES/FILESHIGH
Specifica il numero di file a cui MS-DOS può accedere contemporaneamente.
Utilizzare il comando FILESHIGH per caricare il comando nell’area di memoria superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
FILES=x
FILESHIGH=x
Opzioni.
x Specifica il numero di file a cui MS-DOS può accedere contemporaneamente.
I valori validi per x sono compresi tra 8 e 255.
Il valore predefinito è 8.
INSTALL/INSTALLHIGH
Carica in memoria un’applicazione residente in memoria quando è avviato MS-DOS.
MS-DOS
um 135 di 138
Utilizzare il comando INSTALLHIGH per caricare l’applicazione residente in memoria nella
memoria superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
Le applicazioni residenti in memoria rimangono in memoria fintanto che il PC è acceso.
Possono essere utilizzate anche quando sono in esecuzione altre applicazioni.
È possibile utilizzare il comando INSTALL o INSTALLHIGH per caricare applicazioni MSDOS residenti in memoria, quali FASTOPEN, KEYB, NLSFUNC E SHARE.
INSTALL=[unità:][percorso]nomefile [parametri-comando]
INSTALLHIGH=[unità:][percorso]nomefile [parametri-comando]
Opzioni.
[unità:][percorso]nomefile Specifica la posizione e il nome dell’applicazione residente in
memoria che si desidera eseguire.
parametri-comando Specifica i parametri per l’applicazione specificata per nomefile.
LASTDRIVE/LASTDRIVEHIGH
Specifica il numero massimo di unità a cui è possibile accedere.
Utilizzare il comando LASTDRIVEHIGH per caricare la struttura dei dati LASTDRIVE nella
memoria superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
Il valore che è specificato rappresenta l’ultima unità valida che MS-DOS deve riconoscere.
LASTDRIVE=x
LASTDRIVEHIGH=x
Opzioni.
x Specifica una lettera di unità compresa tra A e Z.
NUMLOCK
Specifica se il tasto BLOC NUM è attivato o meno all’avvio del PC.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
NUMLOCK=[ON|OFF]
Opzioni.
ON|OFF Se è impostato a ON, attiva il tasto BLOC NUM quando in MS-DOS è
visualizzato il menu di avvio, se è impostato a OFF, disattiva BLOC NUM.
REM
Consente d’includere dei commenti in un file batch o nel file CONFIG.SYS.
Il comando REM è inoltre utile per disattivare dei comandi.
Nel file CONFIG.SYS è possibile utilizzare un punto e virgola (;) al posto del comando
REM.
Questa operazione non può invece essere applicata ai file batch.
REM [stringa]
Opzioni.
stringa Specifica una stringa di caratteri: il comando che si desidera disattivare o il
commento che si desidera includere.
SET
Visualizza, imposta o rimuove le variabili di ambiente MS-DOS.
MS-DOS
um 136 di 138
Le variabili di ambiente servono a controllare il comportamento di alcuni file batch e
applicazioni e a controllare la visualizzazione e il funzionamento di MS-DOS.
Il comando SET è spesso utilizzato nel file AUTOEXEC.BAT o CONFIG.SYS per
impostare le variabili di ambiente ogni volta che è avviato MS-DOS.
SET variabile=[stringa]
Per visualizzare le impostazioni correnti di ambiente al prompt dei comandi, utilizzare la
seguente sintassi: SET.
variabile specifica la variabile che si desidera impostare o modificare.
stringa specifica la stringa che si desidera associare alla variabile specificata.
SHELL
Specifica il nome e la posizione dell’interprete dei comandi che deve essere utilizzato da
MS-DOS.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
Se si desidera utilizzare un proprio interprete dei comandi al posto di COMMAND.COM,
sarà possibile specificarne il nome aggiungendo un comando SHELL nel file
CONFIG.SYS.
SHELL=[[unità:]percorso]nomefile [parametri]
Opzioni.
[[unità:]percorso]nomefile Specifica la posizione e il nome dell’interprete dei comandi che
deve essere utilizzato da MS-DOS.
parametri Specifica i parametri o le opzioni della riga di comando che possono essere
utilizzate con l’interprete specificato.
STACKS/STACKSHIGH
Supporta l’utilizzo dinamico degli stack di dati per la gestione degli interrupt H/W.
Utilizzare il comando STACKSHIGH per caricare gli stack nella memoria superiore.
Questi comandi possono essere utilizzati solo nel file CONFIG.SYS.
STACKS=n,s
STACKSHIGH=n,s
Opzioni.
n Specifica il numero degli stack.
I valori validi per n sono 0 e i numeri compresi tra 8 a 64.
s Specifica le dimensioni in byte di ciascuno stack.
I valori validi per s sono 0 e i numeri compresi tra 32 e 512.
SWITCHES
Specifica opzioni speciali in MS-DOS.
Questo comando può essere utilizzato solo nel file CONFIG.SYS.
SWITCHES= /F /K /N /E[:n]
Opzioni.
/F Evita la pausa di due secondi successiva alla visualizzazione del messaggio che
informa dell’avvio di MS-DOS.
/K Fa sì che una tastiera avanzata si comporti come una convenzionale.
/N Impedisce l’utilizzo di F5 o di F8 per ignorare i comandi di avvio.
Se si utilizza il comando SWITCHES /N, sarà ancora possibile premere CTRL+F5 o
MS-DOS
um 137 di 138
CTRL+F8 per ignorare DRVSPACE.BIN oppure DBLSPACE.BIN.
Per evitare ciò, utilizzare il comando D**SPACE /SWITCHES per aggiungere
l’impostazione SWITCHES /N nel file D**SPACE.INI.
/E[:n] Utilizzata senza il parametro :n, questa opzione indica che IO.SYS deve disattivare il
riposizionamento automatico di EBIOS.
Il riposizionamento automatico di EBIOS aumenta la memoria convenzionale disponibile
per le applicazioni per MS-DOS.
La disattivazione di questa funzionalità determina una riduzione della memoria
convenzionale disponibile per le applicazioni per MS-DOS.
Utilizzare l’opzione /E con i parametro n per riposizionare N byte di EBIOS nella memoria
bassa, dove n è il numero di byte da riposizionare.
Il valore minimo per n è 48 e il massimo è 1024.
Il numero specificato è sempre arrotondato per eccesso al successivo multiplo di 16.
Prompt dei comandi
Visualizzazione delle cartelle dal prompt dei comandi.
Per visualizzare il contenuto di una cartella in formato finestra dal prompt dei comandi,
digitare.
Start. oppure Start...
Avvio di applicazioni per Windows dal prompt dei comandi.
Per avviare un’applicazione per Windows dal prompt dei comandi, digitare il nome
dell’applicazione specificando i parametri necessari.
Ad esempio, per avviare il Blocco note, digitare NOTEPAD al prompt dei comandi, quindi
premere INVIO.
Per avviare un’applicazione o aprire un documento, è possibile utilizzare il comando Start.
Esempio.
C:>start Nomedoc.est.
MS-DOS
um 138 di 138
UBERTINI MASSIMO
http://www.ubertini.it
[email protected]
Dip. Informatica Industriale
I.T.I.S. "Giacomo Fauser"
Via Ricci, 14
28100 Novara Italy
tel. +39 0321482411
fax +39 0321482444
http://www.fauser.edu
[email protected]