Capitolo – 10
RECUPERO DATI DA UN DISCO DANNEGGIATO
Recupero dati da un floppy disk danneggiato
Un floppy disk è una delle fonti di archiviazione dati meno affidabili. Se vai in un'organizzazione che utilizza sistemi informatici e chiedi ai suoi dipendenti dei problemi causati dai floppy disk, molto spesso sentirai dire che il problema è che un dipendente dell'organizzazione aveva alcuni dati importanti sul suo floppy disk e ora il floppy disk non è leggibile dal computer e sullo schermo appare un messaggio simile a:
"Impossibile leggere il disco"
"Traccia 0 non valida"
"Disco o capacità non valida"
"Disco non formattato. Vuoi formattarlo adesso?
Si tratta di un problema quotidiano per le organizzazioni che utilizzano sistemi informatici e floppy disk. Il problema diventa critico quando si scopre che non è stato effettuato alcun backup o che non è disponibile alcun backup per i dati che sembrano persi sul floppy disk danneggiato.
Il problema più grande si verifica quando si esegue il backup di informazioni critiche su un floppy disk, si ripristinano dischi di programmi antivirus per contrastare un attacco di virus oppure si salvano record di avvio o altri backup (potrebbero esserci diverse opzioni) su un floppy disk e, quando si desidera riutilizzare il backup dal floppy disk, si verifica un errore di lettura.
In tal caso, si rischia di perdere informazioni e dati importanti e, in alcuni casi, quando si avverte la mancanza di programmi di backup e di ripristino per le informazioni di avvio del computer, programmi di ripristino in caso di attacchi di virus , ecc., si può subire una grave perdita di dati sotto forma di guasto del sistema operativo dovuto alla mancanza di informazioni memorizzate sul floppy disk, che al momento non può essere letto dal computer.
In questi casi, la cosa più importante diventa recuperare i dati da un floppy disk che il sistema del computer ha riconosciuto come difettoso.
Perché il floppy disk non è leggibile?
Il problema più comune che causa la visualizzazione di messaggi di errore come questi su un floppy disk è il danneggiamento del DOS Boot Record (DBR) del floppy disk, che consente al computer di conoscere l'identità logica del floppy disk.
Il DBR è un piccolo programma memorizzato nella traccia 0, nella testina 0 e nel settore 1 che contiene informazioni importanti sul floppy disk, come:
- Numero di byte per settore
- Settore per cluster
- Numero di FAT
- Numero massimo di directory radice, ecc.
Poiché il floppy disk non ha un sistema di partizione logica, non è presente alcun MBR. Il primo settore del floppy disk contiene il DBR. Questa è anche la differenza principale quando si confronta la struttura logica di un disco rigido con quella di un floppy disk.
Quando leggiamo le informazioni del settore di avvio del floppy disk utilizzando un qualsiasi programma di modifica dei dischi, verranno visualizzate informazioni come quelle mostrate nell'immagine sottostante.
La figura seguente mostra 512 byte di informazioni DBR su un floppy disk da 3½ pollici e 1,44 MB.

Se queste informazioni vengono in qualche modo danneggiate o diventano illeggibili, il floppy disk produrrà i seguenti messaggi di errore di lettura. Ciò potrebbe essere dovuto a danni fisici o logici al primo settore del disco.
La corruzione logica comprende i casi in cui le informazioni nel primo settore del dischetto vengono modificate, c'è un settore logicamente danneggiato o il DBR del dischetto viene danneggiato per qualche altro motivo.
Si presume che si verifichi un danno fisico se il primo settore del floppy disk presenta settori fisicamente danneggiati (ad esempio, il settore 1 è fisicamente danneggiato). Il problema diventa più serio quando si scopre che il floppy disk ha più di un settore danneggiato sulla traccia 0.
Come recuperare
Ora che abbiamo scoperto entrambe le cause del danno, spero che tu possa capire il problema. Recuperare i dati da un danneggiamento logico non è così difficile , ma il recupero da un danneggiamento fisico richiede un po' più di impegno.
Metodo – 1
Salvare un'immagine avviabile di un nuovo floppy disk.
Se il problema è logico, ora capiamo come possiamo recuperare i dati . Ciò che dobbiamo fare è semplicemente ottenere il record di avvio appropriato da un altro floppy della stessa dimensione e capacità e incollarlo nel primo settore del floppy illeggibile. Sebbene il problema sia stato creato a causa del record di avvio errato , ora dovrebbe funzionare.
Questa procedura prevede due passaggi, seguendo i quali recupereremo i nostri dati da un floppy illeggibile:
- Creazione dell'immagine del DOS Boot Record di un buon floppy
- Incollare l'immagine di avvio nel primo settore del floppy illeggibile
Creazione dell'immagine del DOS Boot Record di un buon floppy
Per memorizzare l'immagine del record di avvio del floppy disk nuovo, il programma deve eseguire le tre attività seguenti:
- Leggi esattamente i primi 512 byte del floppy disk funzionante
- Controllare che l'operazione di lettura sia riuscita (più importante)
- Memorizza questi 512 byte nel nome file e nel percorso di destinazione specificati
Il settore del floppy è di 512 byte ed è necessario copiare l'immagine esatta del settore. È il passaggio più importante e necessario in caso di qualsiasi tipo di operazione applicata sul floppy per verificare se l'operazione è riuscita o meno.
Potrebbe esserci un problema di inizializzazione anche con un floppy disk nuovo e integro. Ecco perché nella maggior parte dei casi in cui l'operazione viene eseguita su floppy disk, prima di tutto l'inizializzazione dei floppy disk viene eseguita nella programmazione con l' operazione di reset disk (funzione 00 H di INT 13H).
Se anche dopo l'inizializzazione il floppy disk inserito di recente o quello modificato causano errori di lettura, si consiglia di eseguire nuovamente il programma: molto probabilmente questa volta funzionerà.
Il programma seguente deve eseguire queste attività specificate. Vediamo come procede:
/* Memorizza l'immagine di avvio in un file da un nuovo floppy disk */
#include <bios.h>
#include <stdio.h>
int principale(vuoto)
{
struct diskinfo_t dinfo;
sindacato REGS regolamenti;
int risultato;
int conteggio=0, i;
carattere nome[80];
carattere statico dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = 0; /* numero della testina del disco */
dinfo.track = 0; /* numero traccia */
dinfo.sector = 1; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
clrscr();
gotoxy(10,3);cprintf("Inserisci il nome del file e il percorso
Memorizza immagine di avvio");
gotossi(5,5);
ottiene(nome_f);
fp=fopen(fname,"wb");
se((fp=fopen(fname,"wb"))==NULL)
{
videoalto();
gotoxy(10,10);cprintf("Impossibile creare il file");
ottenere();
uscita(0);
}
gotossile(10,9);
cprintf("Tentativo di lettura dall'unità floppy disk:\n");
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
risultato = _bios_disk(_DISK_READ, &dinfo);
se ((risultato & 0xff00) == 0)
{
mentre(conteggio<512)
{
fprintf(fp,"%c",dbuf[conteggio] & 0xff );
conta++;
}
fclose(fp);
gotoxy(10,14);cprintf("Disco letto dall'unità floppy disk
: riuscito.\n");
}
altro
{
gotossi(10,14);
cprintf("Impossibile leggere l'unità A, stato = 0x%02x\n", risultato);
switch(risultato)
{
caso 0x00:
cprintf("\n\n STATO: Nessun errore!! ");
rottura;
caso 0x01:
cprintf("\n\n STATO: Comando non valido ");
rottura;
caso 0x02:
cprintf("\n\n STATO: Contrassegno indirizzo non trovato ");
rottura;
caso 0x03:
cprintf("\n\n STATO: Tentativo di scrittura su disco protetto da scrittura ");
rottura;
caso 0x04:
cprintf("\n\n STATO: Settore non trovato ");
rottura;
caso 0x06:
cprintf("\n\n STATO: Disco modificato dall'ultima operazione ");
rottura;
caso 0x08:
cprintf("\n\n STATO: Accesso diretto alla memoria (DMA) superato ");
rottura;
caso 0x09:
cprintf("\n\n STATO: Tentativo di eseguire DMA oltre il limite di 64K ");
rottura;
caso 0x0C:
cprintf("\n\n STATO: Tipo di supporto non trovato ");
rottura;
caso 0x10:
cprintf("\n\n STATO: CRC/ECC non valido durante la lettura del disco ");
rottura;
caso 0x20:
cprintf("\n\n STATO: Il controller è fallito ");
rottura;
caso 0x31:
cprintf("\n\n STATO: Nessun supporto nell'unità (estensioni IBM/MS INT 13H) ");
rottura;
caso 0x32:
cprintf("\n\n STATO: Tipo di unità non corretto memorizzato nella CMOS (Compaq) ");
rottura;
caso 0x40:
cprintf("\n\n STATO: operazione di ricerca non riuscita ");
rottura;
caso 0x80:
cprintf("\n\n STATO: L'allegato non è riuscito a rispondere (timeout del disco) ");
rottura;
caso 0xB0:
cprintf("\n\n STATO: Volume non bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB1:
cprintf("\n\n STATO: Volume bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB2:
cprintf("\n\n STATO: Volume non rimovibile (estensioni INT 13H) ");
rottura;
caso 0xB3:
cprintf("\n\n STATO: Volume in uso (estensioni INT 13H) ");
rottura;
caso 0xB4:
cprintf("\n\n STATO: Conteggio blocchi superato (estensioni INT 13H) ");
rottura;
caso 0xB5:
cprintf("\n\n STATO: Richiesta di espulsione valida fallita (estensioni INT 13H) ");
rottura;
default: cprintf("\n\n STATO: CODICE di stato SCONOSCIUTO per errori floppy ");
}
}
restituisci 0;
}
Commenti sulla codifica del programma:
Nella codifica del programma fornita in precedenza, sostanzialmente procediamo a svolgere le seguenti attività passo dopo passo:
- dinfo punta alla struttura diskinfo_t che contiene le informazioni dei parametri richiesti dall'operazione eseguita dalla funzione _bios_disk.
- Poiché vogliamo leggere il primo settore del disco, la posizione del settore sarà la seguente:
Parametro |
Cosa significa |
dinfo.unità = 0x00 |
Indica l'unità 0 che è l'unità floppy disk ( a :) |
dinfo.testa = 0 |
Indica la testa numero 0 |
dinfo.traccia = 0 |
Indica la traccia 0 |
dinfo.settore = 1 |
Primo settore del floppy che è il settore 1 |
dinfo.settore = 1 |
Numero di settori da considerare per l'operazione di lettura = 1 |
dinfo.buffer = dbuf |
Buffer dati per l'operazione |
- Apre un flusso di file con nome file e percorso forniti dall'utente per memorizzare le informazioni dell'immagine di avvio di 512 byte esatti. Il nome file e il percorso sono memorizzati nell'array di caratteri fname.
- Inizializza il sistema del disco usando l'interrupt 13H (funzione 00h) dove regs.h.ah = 0x00 punta alla funzione 00 H e regs.h.dl = 0x00 è usato per a: floppy. E int86(0x13, ®s, ®s) richiama il servizio di interrupt MS-DOS INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) legge il settore specificato del floppy disk.
- Lo stato restituito viene memorizzato nel risultato, che viene utilizzato per visualizzare il messaggio di operazione riuscita o per visualizzare un messaggio di errore sullo schermo se si verifica un errore.

Incollare l'immagine di avvio nel primo settore del floppy illeggibile
Per incollare l'immagine di avvio dal file al primo settore del floppy illeggibile dobbiamo eseguire le seguenti tre attività principali nel nostro programma:
- Legge le informazioni esatte di 512 byte del record di avvio del nuovo floppy dal file salvato in precedenza.
- Scrivere queste informazioni nel primo settore del floppy attualmente illeggibile.
- Verificare il completamento corretto dell'operazione di scrittura (molto importante).
Poiché il settore del floppy è di 512 byte ed è necessario incollare l'immagine di avvio esatta nel settore, è il passaggio più importante e necessario in caso di qualsiasi tipo di operazione applicata sul floppy per verificare se l'operazione è riuscita o meno.
Potrebbe verificarsi un problema di inizializzazione del floppy disk durante l'operazione, pertanto è necessario inizializzare il disco reimpostando il sistema del disco (utilizzando la funzione 00H di INT 13H).
Se anche dopo l'inizializzazione il floppy disk inserito di recente o quello modificato causano errori di lettura, si consiglia di eseguire nuovamente il programma: molto probabilmente questa volta funzionerà.
Il programma seguente deve eseguire queste attività specificate. Vediamo come procede:
/* Carica l'immagine di avvio sul floppy illeggibile */
#include <bios.h>
#include <stdio.h>
int principale(vuoto)
{
struct diskinfo_t dinfo;
sindacato REGS regolamenti;
int risultato;
int conteggio=0, i;
carattere nome[80];
carattere dbuf[512];
FILE *fp;
clrscr();
gotoxy(5,3);cprintf("Inserisci il nome del file e il percorso in cui è archiviata l'immagine di avvio del floppy");
gotossi(5,5);
ottiene(nome_f);
fp=fopen(fname,"rb");
se((fp=fopen(fname,"rb"))==NULL)
{
videoalto();
gotoxy(10,10);cprintf("Impossibile aprire il file");
ottenere();
uscita(0);
}
gotossi(10,9);
cprintf("Tentativo di recupero dell'unità floppy disk:\n");
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
mentre(conteggio<512)
{
fscanf(fp,"%c",&dbuf[conteggio]);
conta++;
}
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = 0; /* numero della testina del disco */
dinfo.track = 0; /* numero traccia */
dinfo.sector = 1; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
risultato = _bios_disk(_DISK_WRITE, &dinfo);
se ((risultato & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Riuscito!!! Spero che Floppy possa
Lavora adesso.\n");
}
altro
{
gotossi(10,14);
cprintf("Impossibile leggere l'unità A, stato = 0x%02x\n", risultato);
gotossi(10,16);
switch(risultato)
{
caso 0x00:
cprintf("\n\n STATO: Nessun errore!! ");
rottura;
caso 0x01:
cprintf("\n\n STATO: Comando non valido ");
rottura;
caso 0x02:
cprintf("\n\n STATO: Contrassegno indirizzo non trovato ");
rottura;
caso 0x03:
cprintf("\n\n STATO: Tentativo di scrittura su disco protetto da scrittura ");
rottura;
caso 0x04:
cprintf("\n\n STATO: Settore non trovato ");
rottura;
caso 0x06:
cprintf("\n\n STATO: Disco modificato dall'ultima operazione ");
rottura;
caso 0x08:
cprintf("\n\n STATO: Accesso diretto alla memoria (DMA) superato ");
rottura;
caso 0x09:
cprintf("\n\n STATO: Tentativo di eseguire DMA oltre il limite di 64K ");
rottura;
caso 0x0C:
cprintf("\n\n STATO: Tipo di supporto non trovato ");
rottura;
caso 0x10:
cprintf("\n\n STATO: CRC/ECC non valido durante la lettura del disco ");
rottura;
caso 0x20:
cprintf("\n\n STATO: Il controller è fallito ");
rottura;
caso 0x31:
cprintf("\n\n STATO: Nessun supporto nell'unità (estensioni IBM/MS INT 13H) ");
rottura;
caso 0x32:
cprintf("\n\n STATO: Tipo di unità non corretto memorizzato nella CMOS (Compaq) ");
rottura;
caso 0x40:
cprintf("\n\n STATO: operazione di ricerca non riuscita ");
rottura;
caso 0x80:
cprintf("\n\n STATO: L'allegato non è riuscito a rispondere (timeout del disco) ");
rottura;
caso 0xB0:
cprintf("\n\n STATO: Volume non bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB1:
cprintf("\n\n STATO: Volume bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB2:
cprintf("\n\n STATO: Volume non rimovibile (estensioni INT 13H) ");
rottura;
caso 0xB3:
cprintf("\n\n STATO: Volume in uso (estensioni INT 13H) ");
rottura;
caso 0xB4:
cprintf("\n\n STATO: Conteggio blocchi superato (estensioni INT 13H) ");
rottura;
caso 0xB5:
cprintf("\n\n STATO: Richiesta di espulsione valida fallita (estensioni INT 13H) ");
rottura;
default: cprintf("\n\n STATO: CODICE di stato SCONOSCIUTO per errori floppy ");
}
}
restituisci 0;
}
Commenti sulla codifica del programma:
Nella codifica del programma fornita in precedenza, sostanzialmente procediamo a svolgere le seguenti attività passo dopo passo:
- dinfo punta alla struttura diskinfo_t che contiene le informazioni dei parametri richiesti dall'operazione eseguita dalla funzione _bios_disk.
- Poiché scriveremo le informazioni sul primo settore del disco, la posizione del settore sarà la seguente:
- Aprire il file in cui le informazioni dell'immagine di avvio di 512 byte di un nuovo floppy sono state memorizzate dal programma precedente. Il nome del file e il percorso sono memorizzati nell'array di caratteri fname.
- Inizializza il sistema del disco usando l'interrupt 13H (funzione 00h) dove regs.h.ah = 0x00 punta alla funzione 00 H e regs.h.dl = 0x00 è usato per a: floppy. E int86(0x13, ®s, ®s) richiama il servizio di interrupt MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) scrive le informazioni di avvio dal file specificato nel primo settore (specificato) del floppy disk.
- Lo stato restituito viene memorizzato nel risultato, che viene utilizzato per visualizzare il messaggio di operazione riuscita o per visualizzare un messaggio di errore sullo schermo se si verifica un errore.
Parametro |
Cosa significa |
dinfo.unità = 0x00 |
Indica l'unità 0 che è l'unità floppy disk ( a :) |
dinfo.testa = 0 |
Indica la testa numero 0 |
dinfo.traccia = 0 |
Indica la traccia 0 |
dinfo.settore = 1 |
Primo settore del floppy che è il settore 1 |
dinfo.settore = 1 |
Numero di settori da considerare per l'operazione di scrittura = 1 |
dinfo.buffer = dbuf |
Buffer dati per l'operazione |
Facciamolo con un singolo programma
Spero che ora abbiate capito il concetto alla base di questo tipo di recupero dati dal floppy disk . Dopo questo immaginiamo un singolo programma che dia gli stessi risultati che abbiamo ottenuto con l'aiuto dei due programmi discussi in precedenza.
Con i programmi discussi di recente stavamo svolgendo le seguenti attività:
- Memorizza le informazioni di avvio da un buon floppy disk in un file
- Incolla queste informazioni nel primo settore del floppy attualmente illeggibile Il file che stavamo usando per memorizzare l'immagine di avvio funzionava come ponte intermedio per collegare le operazioni di entrambi i programmi. Ma se definiamo queste informazioni di avvio nella codifica del nostro programma stesso, non abbiamo bisogno di creare un file e non abbiamo bisogno di leggere le informazioni di avvio del floppy dal file.
Nel nostro prossimo programma indicheremo al nostro programma cosa deve scrivere nel primo settore del floppy disk illeggibile, in questo modo eviteremo che due programmi diversi svolgano lo stesso compito e potremo recuperare i nostri dati nello stesso modo di prima dal nuovo singolo programma.
Il programma diventa quindi semplice con meno codice e siamo in grado di ridurre la probabilità di occorrenza di errori di lettura, scrittura o creazione di file . Stiamo eseguendo i seguenti quattro compiti importanti in questo programma:
Non pensare che il programma sia difficile da scrivere e comprendere guardando le informazioni esadecimali di 512 byte di dbuf[512]. Più avanti, discuteremo il modo più semplice per scrivere queste informazioni per la codifica del tuo programma.
- Definisce le informazioni del record di avvio DOS nel sistema esadecimale da scrivere nel primo settore del floppy attualmente illeggibile.
- Reimpostare il sistema del disco per inizializzare il floppy disk (INT 13H, funzione 00H).
- Scrivere il record di avvio DOS sul primo settore del floppy
- Verificare il completamento corretto dell'operazione e, se si è verificato un errore.
Esaminiamo il programma:
/* Singolo programma per caricare l'immagine di avvio predefinita su un floppy disk illeggibile */
#include <bios.h>
#include <stdio.h>
int principale(vuoto)
{
struct diskinfo_t dinfo;
sindacato REGS reg:
int risultato, i;
/* Immagine di avvio da caricare nell'unità floppy disk */
carattere statico dbuf[512]=
{
0xEB,0x3E,0x90,0x2B,0x29,0x6E, 0x70,0x32,0x49,0x48,0x43,0x0,0x2 ,0x1 ,0x1 ,0x0,
0x2,0xE0,0x0,0x40,0xB,0xF0,0x9,0x0,0x12, 0x0 ,0x2 ,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x29, 0x24,0x3B,0xDB, 0x16,0x4E, 0x4F, 0x20, 0x4E,0x41,0x4D,0x45,
0x20, 0x20, 0x20,0x20,0x46,0x41, 0x54,0x31, 0x32,0x20,0x20, 0x20,0xF1,0x7D, 0xFA,
0x33, 0xC9, 0x8E, 0xD1, 0xBC, 0xFC, 0x7B, 0x16, 0x7, 0xBD, 0x78, 0x0, 0xC5, 0x76, 0x0,
0x1E,0x56,0x16,0x55, 0xBF,0x22,0x5,0x89,0x7E,0x0,0x89,0x4E,0x2,0xB1,0xB,0xFC,
0xF3,0xA4,0x6,0x1F,0xBD,0x0,0x7C,0xC6,0x45,0xFE,0xF,0x8B, 0x46,0x18,0x88,0x45,
0xF9,0xFB,0x38,0x66, 0x24,0x7C,0x4,0xCD,0x13, 0x72,0x3C,0x8A,
0x46,0x10,0x98,0xF7,
0x66,0x16,0x3, 0x46,0x1C,0x13,0x56, 0x1E,0x3,0x46,0xE,0x13,
0xD1,0x50,0x52,0x89,
0x46,0xFC,0x89, 0x56,0xFE,0xB8,0x20,0x0, 0x8B,0x76,0x11,0xF7,
0xE6,0x8B,0x5E,0xB ,
0x3, 0xC3, 0x48, 0xF7, 0xF3, 0x1, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x5A,
0x58,0xBB,0x0 ,0x7 ,
0x8B,0xFB,0xB1,0x1, 0xE8,0x94,0x0 ,0x72,0x47,0x38,0x2D,0x74, 0x19,0xB1,0xB,0x56,
0x8B,0x76,0x3E, 0xF3,0xA6,0x5E,0x74,0x4A,0x4E, 0x74,0xB,0x3 , 0xF9,0x83, 0xC7, 0x15,
0x3B, 0xFB, 0x72, 0xE5, 0xEB, 0xD7, 0x2B, 0xC9, 0xB8, 0xD8, 0x7D, 0x87, 0x46, 0x3E, 0x3C,
0xD8,0x75,0x99, 0xBE,0x80,0x7D,0xAC, 0x98,0x3,0xF0,0xAC,0x84,0xC0,0x74,0x17,0x3C,
0xFF,0x74,0x9,0xB4,0xE,0xBB,0x7,0x0,0xCD,0x10,0xEB,0xEE,0xBE,0x83,0x7D,0xEB,
0xE5, 0xBE, 0x81, 0x7D, 0xEB, 0xE0, 0x33, 0xC0, 0xCD, 0x16, 0x5E, 0x1F, 0x8F, 0x4, 0x8F, 0x44,
0x2,0xCD, 0x19,0xBE,0x82,0x7D,0x8B,0x7D,0xF, 0x83,0xFF,0x2,0 x72,0xC8, 0x8B,0xC7,0x48,
0x48,0x8A,0x4E,0xD,0xF7,0xE1,0x3,0x46,0xFC, 0x13,0x56,0xFE,0xBB,0x0,0x7,0x53,0xB1,0x4,
0xE8,0x16,0x0, 0x5B,0x72,0xC8, 0x81,0x3F,0x4D,0x5A, 0x75,0xA7,0x81,0xBF, 0x0,0x2,0x42,0x4A,
0x75,0x9F,0xEA,0x0 ,0x2 ,0x70,0x0,0x50,0x52, 0x51, 0x91, 0x92, 0x33, 0xD2,0xF7,0x76,0x18,0x91,
0xF7,0x76, 0x18,0x42, 0x87, 0xCA, 0xF7, 0x76,0x1A,0x8A,0xF2,0x8A,0x56, 0x24,0x8A,0xE8,
0xD0, 0xCC, 0xD0, 0xCC, 0xA, 0xCC, 0xB8, 0x1, 0x2, 0xCD, 0x13, 0x59, 0x5A, 0x58, 0x72, 0x9, 0x40,
0x75,0x1,0x42,0x3, 0x5E,0xB,0xE2,0xCC,0xC3,0x3,0x18,0x1,0x27,0xD,0xA,0x49, 0x6E,
0x76,0x61,0x6C,0x69,0x64,0x20, 0x73, 0x79, 0x73, 0x74, 0x65,0x6D,0x20,0x64,0x69,0x73,
0x6B,0xFF,0xD,0xA,0x44,0x69, 0x73,0x6B,0x20, 0x49,0x2F, 0x4F,0x20, 0x65,0x72, 0x72,0x6F,
0x72,0xFF,0xD,0xA,0x52, 0x65,0x70,0x6C,0x61,0x63, 0x65,0x20,
0x74,0x68, 0x65, 0x20,
0x64, 0x69,0x73, 0x6B,0x2C,0x20,0x61, 0x6E,0x64,0x20,0x74, 0x68, 0x65, 0x6E, 0x20,0x70,
0x72,0x65, 0x73,0x73, 0x20,0x61, 0x6E,0x79,0x20,0x6B,0x65,0x79,0xD,0xA, 0x0,0x49,0x4F,
0x20,0x20,0x20,0x20, 0x20,0x20,0x53,0x59,0x53,0x4D, 0x53, 0x44, 0x4F, 0x53,0x20,0x20,
0x20,0x53, 0x59,0x53, 0x80,0x1,0x0,0x57,0x49, 0x4E,0x42, 0x4F,0x4F,0x54,0x20,0x53, 0x59
,0x53,0x0,0x0,0x55,0xAA};
clrscr();
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = 0; /* numero della testina del disco */
dinfo.track = 0; /* numero traccia */
dinfo.sector = 1; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
gotossi(10,9);
cprintf("Tentativo di lettura dall'unità floppy disk:\n");
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
risultato = _bios_disk(_DISK_WRITE, &dinfo);
se ((risultato & 0xff00) == 0)
{
gotossi(10,14);
cprintf("Stato scrittura disco: riuscito.\n");
}
altro
{
gotossi(10,14);
cprintf("Impossibile leggere l'unità A, stato = 0x%02x\n",
risultato);
gotossi(10,16);
switch(risultato)
{
caso 0x00:
cprintf("\n\n STATO: Nessun errore!! ");
rottura;
caso 0x01:
cprintf("\n\n STATO: Comando non valido ");
rottura;
caso 0x02:
cprintf("\n\n STATO: Contrassegno indirizzo non trovato ");
rottura;
caso 0x03:
cprintf("\n\n STATO: Tentativo di scrittura su write-
disco protetto ");
rottura;
caso 0x04:
cprintf("\n\n STATO: Settore non trovato ");
rottura;
caso 0x06:
cprintf("\n\n STATO: Disco modificato dall'ultima operazione ");
rottura;
caso 0x08:
cprintf("\n\n STATO: Accesso diretto alla memoria (DMA) superato ");
rottura;
caso 0x09:
cprintf("\n\n STATO: Tentativo di eseguire DMA oltre il limite di 64K ");
rottura;
caso 0x0C:
cprintf("\n\n STATO: Tipo di supporto non trovato ");
rottura;
caso 0x10:
cprintf("\n\n STATO: CRC/ECC non valido durante la lettura del disco ");
rottura;
caso 0x20:
cprintf("\n\n STATO: Il controller è fallito ");
rottura;
caso 0x31:
cprintf("\n\n STATO: Nessun supporto nell'unità (estensioni IBM/MS INT 13H) ");
rottura;
caso 0x32:
cprintf("\n\n STATO: Tipo di unità non corretto memorizzato nella CMOS (Compaq) ");
rottura;
caso 0x40:
cprintf("\n\n STATO: operazione di ricerca non riuscita ");
rottura;
caso 0x80:
cprintf("\n\n STATO: L'allegato non è riuscito a rispondere (timeout del disco) ");
rottura;
caso 0xB0:
cprintf("\n\n STATO: Volume non bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB1:
cprintf("\n\n STATO: Volume bloccato nell'unità (estensioni INT 13H) ");
rottura;
caso 0xB2:
cprintf("\n\n STATO: Volume non rimovibile (estensioni INT 13H) ");
rottura;
caso 0xB3:
cprintf("\n\n STATO: Volume in uso (estensioni INT 13) ");
rottura;
caso 0xB4:
cprintf("\n\n STATO: Conteggio blocchi superato (estensioni INT 13H) ");
rottura;
caso 0xB5:
cprintf("\n\n STATO: Richiesta di espulsione valida fallita (estensioni INT 13H) ");
rottura;
default: cprintf("\n\n STATO: CODICE di stato SCONOSCIUTO per errori floppy ");
}
}
restituisci 0;
}
In questa codifica del programma, sostanzialmente procediamo a svolgere le seguenti attività passo dopo passo:
- Il buffer di dati di caratteri statici dbuf[512] fornisce le informazioni di 512 byte nel sistema esadecimale, che devono essere scritte nel primo settore del floppy illeggibile. dbuf[512] dice al computer durante l'operazione quali informazioni devono essere scritte nel primo settore del floppy. (Vedi il programma successivo)
- dinfo punta alla struttura diskinfo_t che contiene le informazioni dei parametri richiesti dall'operazione eseguita dalla funzione _bios_disk.
- Poiché scriveremo le informazioni sul primo settore del disco, la posizione del settore sarà la seguente:
Parametro |
Cosa significa |
dinfo.unità = 0x00 |
Indica l'unità 0 che è l'unità floppy disk ( a :) |
dinfo.testa = 0 |
Indica la testa numero 0 |
dinfo.traccia = 0 |
Indica la traccia 0 |
dinfo.settore = 1 |
Primo settore del floppy che è il settore 1 |
dinfo.settore = 1 |
Numero di settori da considerare per l'operazione di scrittura = 1 |
dinfo.buffer = dbuf |
Buffer dati per l'operazione |
- Inizializza il sistema del disco usando l'interrupt 13H (funzione 00h) dove regs.h.ah = 0x00 punta alla funzione 00 H e regs.h.dl = 0x00 è usato per a: floppy. E int86(0x13, ®s, ®s) richiama il servizio di interrupt MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) scrive le informazioni di avvio dal file specificato nel primo settore (specificato) del floppy disk.
Lo stato restituito viene memorizzato nel risultato, che viene utilizzato per visualizzare il messaggio di operazione riuscita o per visualizzare un messaggio di errore sullo schermo se si verifica un errore.
Memorizzazione dell'immagine di avvio in caratteri ESADECIMALI da utilizzare nel nostro programma precedente
Sarà un lavoro molto difficile scrivere manualmente tutti i 512 caratteri del DOS Boot Record del floppy nel sistema esadecimale senza alcun errore nel programma di cui abbiamo discusso di recente. Se riusciamo a scriverlo in modo accurato, allora sarà un compito difficile e che richiederà molto tempo. Usiamo un po' di mente astuta per memorizzare i dati per il buffer dati dbuf[512] in un file.
Sappiamo che nella programmazione C i caratteri esadecimali sono rappresentati con 0x in modo tale che se il carattere esadecimale è A9 H, lo scriveremo nel nostro programma C come 0xA9. Il nostro prossimo programma fa lo stesso. Memorizzerà i dati che dobbiamo scrivere nel nostro programma precedente, come dati del buffer dati dbuf[512].
Ciò che devi fare è semplicemente prendere un floppy disk nuovo e fresco per creare l'immagine del suo DBR e copiare l'output di questo programma dal file di destinazione specificato e incollare questi dati nel tuo programma. Fai un po' di formattazione se necessario. Vediamo come funziona:
/* Programma per creare l'immagine di avvio del floppy disk in caratteri HEX */
#include <bios.h>
#include <stdio.h>
int principale(vuoto)
{
struct diskinfo_t dinfo;
sindacato REGS regolamenti;
int risultato,i;
int conteggio=0;
carattere nome[80];
carattere statico dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = 0; /* numero della testina del disco */
dinfo.track = 0; /* numero traccia */
dinfo.sector = 1; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
clrscr();
gotoxy(10,3);cprintf("Inserisci il nome del file e il percorso
Memorizza l'immagine di avvio nel sistema HEX");
gotossi(5,5);
ottiene(nome_f);
fp=fopen(fname,"wb");
se((fp=fopen(fname,"wb"))==NULL)
{
videoalto();
gotoxy(10,10);cprintf("Impossibile creare il file");
ottenere();
uscita(0);
}
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("Tentativo di lettura dal floppy
unità disco :\n");
risultato = _bios_disk(_DISK_READ, &dinfo);
se ((risultato & 0xff00) == 0)
{
gotossi(10,14);
cprintf("Disco letto dall'unità floppy disk:
riuscito.\n");
mentre(conteggio<512)
{
fprintf(fp,"0x%X, ",dbuf[conteggio] & 0xff );
conta++;
}
fclose(fp);
}
altro
{
gotossi(10,14);
cprintf("Impossibile leggere l'unità A, stato = 0x%02x\n",
risultato);
}
restituisci 0;
}
Commenti sulla codifica del programma:
Quindi i dati vengono memorizzati nel file specificato. Basta copiare i dati nel programma e fare la formattazione richiesta. Non dovresti mai dimenticare i seguenti suggerimenti durante la procedura:
- Assicurarsi che il funzionamento del programma sia andato a buon fine e che i dati memorizzati nel file di destinazione siano appropriati.
- Dovresti controllare l'intera operazione per verificare che non si verifichino errori previsti.
- Devi inizializzare il Floppy disk con il programma prima di leggere il suo settore di avvio. Puoi usare la funzione 00H di INT 13H a questo scopo.
Metodo – 2
Cosa fare se il Metodo 1 non funziona?
Se il Metodo – 1 non funziona e il disco illeggibile non consente al programma di riscrivere le informazioni di avvio sul suo primo settore, dovresti provare questo secondo metodo. Il motivo dietro il fallimento del Primo Metodo potrebbe essere la corruzione fisica del primo settore del floppy disk.
In questo secondo metodo copieremo temporaneamente tutti i dati dalla superficie del floppy illeggibile in un singolo file e poi incolleremo questa immagine direttamente sulla superficie di un altro disco funzionante.
La procedura prevede i seguenti due importanti passaggi:
- Settore per settore Copia temporaneamente tutti i dati della superficie del supporto floppy in un singolo file.
- Incollare i dati precedentemente memorizzati nel file su un nuovo floppy disk, così com'è, negli stessi settori.
Copia tutti i dati della superficie del supporto in un singolo file
Per memorizzare tutti i dati sulla superficie del supporto del floppy, il programma deve eseguire le seguenti tre attività:
- Inizializzare correttamente il disco con l'aiuto della funzione 00H di INT 13H.
- Leggere le informazioni settore per settore della superficie e memorizzarle in un unico file.
- Controllare che l'operazione di lettura sia riuscita (più importante)
È molto comune avere qualsiasi problema di inizializzazione con un floppy disk che porta a molti messaggi di lettura non riusciti. Ecco perché il disco deve essere inizializzato prima dell'operazione di lettura/scrittura con l'aiuto della programmazione.
Nel caso di qualsiasi tipo di operazione eseguita sul floppy, è il passaggio più importante e necessario per verificare se l'operazione è riuscita o meno.
Se anche dopo l'inizializzazione il floppy disk inserito di recente o quello modificato causano errori di lettura, si consiglia di eseguire nuovamente il programma: molto probabilmente questa volta funzionerà.
Il programma seguente deve eseguire queste attività specificate. Vediamo come procede:
/* Programma per memorizzare i dati della superficie fisica del floppy disk in un file */
#include <bios.h>
#include <stdio.h>
vuoto principale(vuoto)
{
int testa,traccia;
sindacato REGS regolamenti;
int risultato,i,settore;
char nomefile[80];
struct diskinfo_t dinfo;
carattere statico dbuf[512];
FILE *tt;
clrscr();
printf("\n Inserisci il nome del file con il percorso in cui memorizzarlo
Dati Temporaneamente\n");
ottiene(nomefile);
if((tt=fopen(nomefile,"wb"))==NULL)
{
printf("Impossibile creare il file,
Premere un tasto qualsiasi per USCIRE");
ottenere();
uscita(0);
}
printf("\n Inizializzazione del sistema floppy disk...\n");
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
per(traccia=0;traccia<=79;traccia++)
{
per(testa=0;testa<=1;testa++)
{
per(settore=1;settore<=18;settore++)
{
dinfo.drive = 0; /* numero unità per A: */
dinfo.head = testa; /* numero della testina del disco */
dinfo.track = traccia; /* numero traccia */
dinfo.sector = settore; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
risultato = _bios_disk(_DISK_READ, &dinfo);
se ((risultato & 0xff00) == 0)
{
per(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
altro
{
printf("Impossibile leggere l'unità A, stato =
0x%02x\t%d\t%d\t%d\n", risultato,testa,traccia,settore);
}
printf("Traccia di lettura = %d Testa = %d Settore = %d\n",
traccia,testa,settore);
}
}
}
}
Commenti sulla codifica del programma:
Nella codifica del programma fornita in precedenza, sostanzialmente procediamo a svolgere le seguenti attività passo dopo passo:
- L'array di caratteri filename[80] memorizza il percorso definito dall'utente e il nome del file in cui memorizzeremo temporaneamente i dati.
- dinfo punta alla struttura diskinfo_t che contiene le informazioni dei parametri richiesti dall'operazione eseguita dalla funzione _bios_disk.
- Inizializza il sistema del disco usando l'interrupt 13H (funzione 00h) dove regs.h.ah = 0x00 punta alla funzione 00 H e regs.h.dl = 0x00 è usato per a: floppy. E int86(0x13, ®s, ®s) richiama il servizio di interrupt MS-DOS INT 13 H.
- Poiché leggeremo tutte le informazioni della superficie del disco, i parametri di _bios_disk saranno i seguenti:
Parametro |
Cosa significa |
dinfo.unità = 0x00 |
Indica l'unità 0 che è l'unità floppy disk ( a :) |
dinfo.head = testa |
Indica la testa numero 0 e 1 poiché il floppy ha due lati (due teste) |
dinfo.track = traccia |
Indica la traccia da 0 a 79 poiché ci sono 80 tracce su ogni lato del floppy. |
dinfo.sector = settore |
Indica i settori da 1 a 18 poiché ogni traccia contiene 18 settori . |
dinfo.settore = 1 |
Numero di settori da considerare per l'operazione di lettura = 1 |
dinfo.buffer = dbuf |
Buffer dati per l'operazione |
- _bios_disk(_DISK_READ, &dinfo) legge i dati dalla superficie fisica del floppy disk dal settore specificato da dinfo.
- Lo stato restituito viene memorizzato nel risultato, che viene utilizzato per visualizzare il messaggio di operazione riuscita o per visualizzare un messaggio di errore sullo schermo se si verifica un errore.
Ricorda sempre che la dimensione del file che contiene l'immagine dei dati del floppy disk deve essere esattamente 1.474.560 byte perché il floppy ha 80 tracce (da 0 a 79), 2 lati o testine (testina 0 e testina 1), ogni traccia ha 18 settori e ogni settore contiene 512 byte di dati, quindi
Totale byte = (Numero di tracce) * (Numero di testine) *
(Numero di settori per traccia) * 512
= 80*2*18*512
= 1.474.560 byte
Pertanto, se si verifica un errore nella lettura di un qualsiasi settore del floppy disk, la dimensione del file cambierà da 1.474.560 byte, il che renderà tutte le informazioni, del tutto o in parte, inutili per il disco di destinazione su cui scriveremo l'immagine del disco, settore per settore, da questo file.
Questo perché il Computer legge le informazioni di qualsiasi file sulla superficie del supporto del floppy disk all'interno dell'intervallo di settori così come è stato allocato nella sua unità di allocazione. Ora, se i settori dei dati dei file vengono modificati, vengono modificate le informazioni complete del file.
Riflessioni sulla soluzione dell'errore di lettura del settore/i
È possibile che un floppy disk difettoso o illeggibile abbia un'area della superficie così danneggiata da rendere impossibile la lettura delle informazioni dalla superficie del disco.
In questa condizione le informazioni di questo/i settore/i verranno saltate e l'immagine del floppy sarà distorta anche per gli altri settori, poiché la dimensione del file immagine in questo caso è diversa da 1.474.560 byte.
Per mantenere le dimensioni del file immagine e incollare il resto delle informazioni nelle posizioni esatte dei settori sul disco di destinazione, scriviamo altre informazioni per conto dei dati originali di 512 byte e in questo modo saremo in grado di salvare il resto delle informazioni, tuttavia il recupero in tal caso potrebbe essere parziale.
Se il sistema non riesce a leggere neanche il primo settore del floppy di origine, dopo aver incollato l'immagine sul floppy di destinazione dovresti eseguire il programma descritto in precedenza per riscrivere il record di avvio DOS del floppy.
Vediamo come possiamo farlo programmando:
#include <bios.h>
#include <stdio.h>
vuoto principale(vuoto)
{
int testa,traccia;
sindacato REGS regolamenti;
int risultato,i,settore;
char nomefile[80];
struct diskinfo_t dinfo;
carattere statico dbuf[512];
/* Informazioni di 512 byte per riempire lo spazio del settore danneggiato */
/// Ho usato 512 zeri per riempire lo spazio di 512 byte \\\
carattere statico dbuf2[512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "0000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "0000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "0000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "0000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Inserisci il nome del file con il percorso in cui memorizzarlo
Dati Temporaneamente\n");
ottiene(nomefile);
if((tt=fopen(nomefile,"wb"))==NULL)
{
printf("Impossibile creare il file, premere un tasto qualsiasi per
USCITA");
ottenere();
uscita(0);
}
printf("\n Inizializzazione del sistema floppy disk...\n");
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
per(traccia=0;traccia<=79;traccia++)
{
per(testa=0;testa<=1;testa++)
{
per(settore=1;settore<=18;settore++)
{
dinfo.drive = 0; /* numero unità per A: */
dinfo.head = testa; /* numero della testina del disco */
dinfo.track = traccia; /* numero traccia */
dinfo.sector = settore; /* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
risultato = _bios_disk(_DISK_READ, &dinfo);
se ((risultato & 0xff00) == 0)
{
per(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
altro
{
printf("Impossibile leggere l'unità A, stato =
0x%02x\t%d\t%d\t%d\n", risultato, testina, traccia, settore);
/* Se il settore non è leggibile, occupa 512 byte da dbuf2 */
{NS} = ...
}
printf("Traccia di lettura = %d Testa = %d Settore = %d\n",
traccia, testa, settore);
}
}
}
}
Commenti sulla codifica del programma:
Nella codifica del programma, ogni passaggio è uguale al programma precedente, eccetto il buffer dati dbuf2[512], che stiamo utilizzando per gestire l'errore generato dal settore danneggiato durante l' operazione di lettura del disco e per mantenere la dimensione del file immagine.
In questo modo riempiamo lo spazio delle informazioni che non siamo riusciti a leggere dal settore danneggiato e ora scriviamo le pseudo-informazioni di 512 byte in modo da mantenere l'accuratezza dell'immagine del disco.
Incolla i dati dal file sulla superficie fisica del nuovo floppy disk:
In questo passaggio incolliamo i dati memorizzati nel file dal programma precedente sulla superficie fisica del nuovo floppy, settore per settore, nello stesso modo in cui li abbiamo copiati nel file.
Il programma procede con i seguenti passaggi principali:
- Aprire il file in cui abbiamo memorizzato temporaneamente i dati di superficie del floppy illeggibile.
- Inizializzare correttamente il sistema del disco tramite la funzione di reimpostazione 00H di INT 13H.
- Scrivere le informazioni sui settori del nuovo floppy disk dal file.
- Visualizzare simultaneamente lo stato di scrittura per individuare o evitare il verificarsi di errori.
Di seguito è riportato il codice sorgente del programma. Esaminiamo come funziona:
/* Programma per scrivere i dati sui settori della superficie del floppy disk nuovo dal file, creato dal programma precedente */
#include <bios.h>
#include <stdio.h>
vuoto principale(vuoto)
{
int testa,traccia;
sindacato REGS regolamenti;
int risultato,i,settore;
int conteggio =0;
char nomefile[80];
struct diskinfo_t dinfo;
carattere statico dbuf[512];
FILE *fp;
clrscr();
printf("\n Inserisci il nome del file con il percorso in cui memorizzarlo
Dati Temporaneamente\n");
ottiene(nomefile);
if((fp=fopen(nomefile,"rb"))==NULL)
{
printf("Impossibile creare il file, premere un tasto qualsiasi per
USCITA");
ottenere();
uscita(1);
}
/// Inizializza il sistema del disco \\\
per(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reimposta il sistema del disco */
regs.h.dl = 0x00; /* Disco floppy a: */
int86(0x13, ®s, ®s);
}
per(traccia=0;traccia<=79;traccia++)
{
per(testa=0;testa<=1;testa++)
{
per(settore=1;settore<=18;settore++)
{
conta =0;
mentre(conteggio<512 )
{
fscanf(fp,"%c",&dbuf[conteggio]);
conta++;
}
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = testa; /* numero della testina del disco */
dinfo.track = traccia; /* numero traccia */
dinfo.sector = settore;/* numero settore */
dinfo.nsectors = 1; /* conteggio settori */
dinfo.buffer = dbuf; /* buffer dati */
risultato= _bios_disk(_DISK_WRITE, &dinfo);
se ((risultato & 0xff00) == 0)
printf("Scrittura riuscita su Traccia = %d, Testa = %d,
Settore = %d.\n", traccia, testina, settore);
altro
printf("Impossibile leggere l'unità A, stato = 0x%02x\n",
risultato);
}
}
}
}
Commenti sulla codifica del programma:
Nella codifica del programma fornita in precedenza, sostanzialmente procediamo a svolgere le seguenti attività passo dopo passo:
- L'array di caratteri filename[80] contiene il percorso e il nome del file in cui abbiamo memorizzato temporaneamente i dati della superficie del floppy illeggibile.
- dinfo punta alla struttura diskinfo_t che contiene le informazioni dei parametri richiesti dall'operazione eseguita dalla funzione _bios_disk.
- Inizializza il sistema del disco usando l'interrupt 13H (funzione 00h) dove regs.h.ah = 0x00 punta alla funzione 00 H e regs.h.dl = 0x00 è usato per a: floppy. E int86(0x13, ®s, ®s) richiama il servizio di interrupt MS-DOS INT 13 H.
- Poiché scriveremo le informazioni direttamente sui settori della superficie del disco , i parametri di _bios_disk saranno i seguenti:
Parametro |
Cosa significa |
dinfo.unità = 0x00 |
Indica l'unità 0 che è l'unità floppy disk ( a :) |
dinfo.head = testa |
Indica la testa numero 0 e 1 poiché il floppy ha due lati (due teste) |
dinfo.track = traccia |
Indica la traccia da 0 a 79 poiché ci sono 80 tracce su ogni lato del floppy. |
dinfo.sector = settore |
Indica i settori da 1 a 18 poiché ogni traccia contiene 18 settori . |
dinfo.settore = 1 |
Numero di settori da considerare per l'operazione di scrittura = 1 |
dinfo.buffer = dbuf |
Buffer dati per l'operazione |
- _bios_disk(_DISK_WRITE, &dinfo) scrive i dati sui settori della superficie fisica del floppy disk, specificati da dinfo.
- Lo stato restituito viene memorizzato nel risultato, che viene utilizzato per visualizzare il messaggio di operazione riuscita o per visualizzare un messaggio di errore sullo schermo se si verifica un errore.
Se dopo aver applicato il Metodo 2 il nuovo floppy non funziona, puoi applicare il Metodo 1 sul nuovo floppy che hai utilizzato come disco di destinazione durante il Metodo 2.
Non solo questo, ma anche il numero di hit e tentativi può variare a seconda della corruzione del disco. Ma non devi preoccuparti se anche dopo non stai ottenendo risultati soddisfacenti.
Puoi provare il recupero file per file o puoi provare molti altri suggerimenti che imparerai in seguito. Qui implementeremo l'idea di raccogliere le informazioni sui file dalle directory radice, nella nostra programmazione per recuperare i dati.
Pensare al recupero logico dei dati cancellati o persi:
Tutti i casi precedenti di recupero trattati in questo capitolo servivano a recuperare i dati in situazioni in cui ci aspettavamo che solo il DBR fosse danneggiato e che i settori nella traccia 0, con directory FAT1, FAT2 e Root, fossero leggibili .
Ma se il problema è dovuto alla corruzione del FAT o i dati sono stati eliminati dal disco o si desidera recuperare i dati direttamente leggendo le informazioni dalla directory radice , è necessario leggere informazioni quali nome file , cluster di partenza , dimensione del file , attributo ecc. dalla voce della directory radice .
Come abbiamo già discusso in merito alla Root Directory nei capitoli precedenti, ci sono informazioni di 32 byte per ogni file o directory. Questi 32 byte sono divisi come segue:
Numero di byte |
Descrizione delle informazioni |
8 byte |
Nome file |
3 byte |
Estensione |
1 byte |
Attributo |
10 byte |
Prenotato |
2 byte |
Ora, creazione o ultimo aggiornamento |
2 byte |
Data, creazione o ultimo aggiornamento |
2 byte |
Cluster di partenza |
4 byte |
Dimensione del file |
Recuperiamo i dati leggendo le informazioni del/i file dalla directory radice e quindi integriamo il file nel percorso di destinazione e recuperiamo il file. Il nostro programma successivo esegue i seguenti passaggi per recuperare i dati:
- Leggere le voci della directory radice e visualizzarle sullo schermo con tutte le informazioni quali nome del file/directory, estensione del file, dimensione del cluster iniziale dei file in byte.
- Leggere le informazioni sui file e sulle directory nelle sottodirectory e visualizzarle se necessario.
- Conferma il nome del file da recuperare e continua il recupero.
- Calcola le informazioni CHS (cilindro, testata e settore) per il file specificato da recuperare.
- Integra i dati del file dall'area dati del disco e salva il file recuperato nel nome file di destinazione specificato nel percorso specificato.
Questo programma non si preoccupa se le informazioni di avvio del floppy sono leggibili o meno. Pertanto puoi recuperare anche i dati cancellati dal floppy disk corrotto . Vediamo la codifica del programma:
/* Programma per recuperare i dati dal floppy disk leggendo le informazioni del file dalla directory principale */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
vuoto principale()
{
void Display_Information(int senza segno,int senza segno,
intero senza segno);
unsigned int traccia=0,testa=1,settore=2;
Display_Information(traccia,testa,settore);
} /*Fine del principale */
void Display_Information(unsigned int traccia,
testa int senza segno,
settore int senza segno)
{
void retrieve(unsigned int *,unsigned int);
char buf[512]; // Buffer di 512 byte
carattere ch;
struct diskinfo_t finfo; //Struttura, utilizzata da _bios_disk
unsigned int risultato,i,j, conteggio=0; /* Interi senza segno
Definito */
unsigned int file_no; /* Intero senza segno
per numero di file */
struttura
{
unsigned int name[8],ext[3]; /* Nome file per DOS in 8.3
(Otto Punto Tre) Formato */
attributo int senza segno; // Attributo file/directory
unsigned int start; // Avvio del cluster del file
long unsigned int size; // Dimensione del file in byte
}root[32]; /* 32 byte di informazioni su
File/Directory nella radice
Elenco */
clrscr();
Fare
{
numero_file=0;
finfo.drive = 0x00; /* numero unità per A: */
finfo.head = testa; /* numero della testina del disco */
finfo.track = traccia; /* numero traccia */
finfo.sector= settore; /* numero settore */
finfo.nsectors=1; /* conteggio settori */
finfo.buffer = buf; /* buffer dati */
risultato = _bios_disk(_DISK_READ, &finfo); /* Leggi il
Settore */
if( (result & 0xff00) != 0) /* Se errore di lettura, visualizza
Messaggio di errore e uscita*/
{
printf("Errore di lettura");
ottenere();
exit(0); // Torna al DOS
}
/// Formato dello schermo di visualizzazione delle informazioni \\\
clrscr();
gotossi(9,1);
cprintf("CILINDRO DISPLAY: %u, TESTA: %u, SETTORE: %u",
traccia, testa, settore);
gotossi(9,2);
cprintf("FNO NOME EXT ATTRIBUTO INIZIO DIMENSIONE");
gotossi(7,3);
{NS} ...
/* Un settore alla volta. Ogni voce File/DIR occupa 32 byte */
per(i=0;i<512;i+=32)
{
per(j=0;j<8;j++)
{
/// Trova il nome del file/directory \\\
radice[numero_file].nome[j]=buf[j+i];
}
per(j=8;j<11;j++)
{
/// Trova l'estensione \\\
radice[numero_file].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attributo=buf[i+j]; /// Attributo
/// Avvio del cluster \\\
radice[numero_file].inizio=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Calcola la dimensione \\\
root[file_no].size =(intero lungo senza segno)(0xff &
(buf[31+i])*16*16*16*16*16*16*16*16;
root[file_no].size+=(intero lungo senza segno)(0xff &
(buf[30+i])*16*16*16*16;
root[file_no].size+=(intero lungo senza segno)(0xff &
(buf[29+i])*16*16;
root[file_no].size+=(intero lungo senza segno)(0xff &
buf[28+i]);
se((root[file_no].start == 0) ||
(root[file_no].attributo == 15))
continuare;
altro
{
gotossico(8,i/32+4);
cprintf("%2u",file_no); /* Visualizza file
Numero */
per(j=0;j<8;j++)
{
gotossico(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Visualizza file
Nome */
}
per(j=0;j<3;j++)
{
gotossico(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Visualizzazione
Estensione */
}
gotossico(30,i/32+4);
cprintf("%u",root[file_no].attributo); /* Visualizzazione
Attributo */
se(root[file_no].attributo==16)
{
gotossico(33,i/32+4);
cprintf("<DIR>"); /* Visualizza se Attributo Directory */
}
altro
{
gotossico(33,i/32+4);
cprintf("<FILE>"); /* La voce è di un file */
}
gotossico(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Visualizzazione
Cluster di avvio */
gotossico(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* dimensione del
File */
}
numero_file++;
}
gotossico(10,
cprintf("Premi 'M': per vedere l'elenco di altri file &quo
gotossico(10,
cprintf("Premi 'R': per recuperare un file da quanto sopra
elenco&quo
ch=getc
Ricorda che il nome del file che inizia con s (E5H) indica che il file è stato eliminato e pertanto il primo carattere del nome del file è stato sostituito con s (vedi la descrizione della directory radice nei capitoli precedenti).
E l'output del programma viene visualizzato in questo modo:
DISPLAY CILINDRO: 0, TESTA: 1, SETTORE: 2 NOME
FNO ATTRIBUTO EST DIMENSIONE INIZIO
--------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Premere 'M': per visualizzare l'elenco di altri file
Premere 'R': per recuperare un file dall'elenco soprastante R
|
DISPLAY CILINDRO: 0, TESTA: 1, SETTORE: 2 NOME
FNO ATTRIBUTO EST DIMENSIONE INIZIO
----------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Inserisci FNO. del file che vuoi recuperare 1
Vuoi recuperare _2_INFO .C
Cilindro = 1, Testina = 0, Settore = 1 Integrazione in corso........
Inserisci Percorso e Nome file per recuperare il file: c:\windows\desktop\H2_INFO.C
Recupero completato!!!
|
Commenti sulla codifica:
La funzione Display_Information serve per leggere le informazioni di file e directory e dalla directory radice. Nella struttura stiamo leggendo le informazioni di 32 byte per ogni file o directory con root[32].
Gli array di interi senza segno name[8] ed ext[3] sono per il nome del file o della directory per DOS nel formato 8.3 (otto punto tre). Allo stesso modo, un byte è per l'attributo e due byte per l'avvio del cluster. long unsigned int size; serve per memorizzare la dimensione del file di quattro byte.
La funzione _bios_disk legge il settore specificato dalla struttura finfo e lo stato dell'operazione viene memorizzato nel risultato.
Da ogni informazione di 512 byte letta dalla funzione _bios_disk , fino alla fine dell'area della directory radice , raccogliamo le informazioni dei file e delle directory memorizzati sul disco e le visualizziamo sullo schermo.
L'intero file_no memorizza il numero del file o della directory nell'elenco, a partire da 0. In genere la dimensione della directory radice è di 14 settori e la directory radice inizia generalmente da Cilindro =0, Testa =0 e Settore =2 nel caso di 1,44 MB e 3½ floppy disk.
Se l'utente immette il carattere 'M' o 'm' come input, vengono visualizzate le informazioni del settore successivo; se la scelta dell'utente è 'R' o 'r', vengono chiamate le funzioni di ripristino. La codifica della funzione retrieve() è riportata di seguito:
/* Funzione per avviare il ripristino del file specificato */
void recovery(int senza segno *root,int senza segno len)
{
void clear_the_line(unsigned int r); /* Funzione per cancellare una riga sullo schermo */
/* Funzione per integrare il file specificato */
void integrate(long int senza segno,int senza segno,
intero senza segno,intero senza segno);
int senza segno file_no,i;
carattere ch;
intero senza segno *loc;
unsigned int cilindro,testata,settore;
int senza segno inizio;
intero lungo senza segno dimensione;
clear_the_line(21); /* Cancella il numero di riga 21 */
clear_the_line(22); /* Cancella il numero di riga 22 */
clear_the_line(23); /* Cancella il numero di riga 23 */
clear_the_line(24); /* Cancella il numero di riga 24 */
gotossi(10,21);
cprintf("Inserisci il numero FNO del file che vuoi recuperare");
scanf("%u",&file_no); /* Ottieni il numero del file da
Recuperato */
loc=(root+(len*numero_file/2));
/* Conferma il nome del file da recuperare */
gotossi(10,22);
cprintf("Vuoi recuperare");
per(i=0;i<8;i++)
{
gotossi(30+i,22);
cprintf("%c",*(loc+i)); /* Nome file */
}
gotossi(38,22);
{NS} = "cprintf(".");
per(i=0;i<3;i++)
{
gotossi(39+i,22);
cprintf("%c",*(loc+8+i)); /* Estensione file */
}
inizio=*(loc+12);
/// Spiacenti, hai selezionato una directory \\\
se(*(loc+11)==16)
{
gotossi(5,23);
cprintf("È una directory. Vuoi vedere la
contenuto di questa directory S/N");
ch=getch();
se(ch==27)
principale();
se(ch=='y' || ch=='Y')
{
/* Calcola Geometria */
calcola(inizio,&cilindro,&testa,&settore);
/* Visualizza il contenuto della directory */
Display_Information (cilindro, testata, settore);
}
altro
/* Richiedi nuovamente il file A e continua il recupero */
recuperare(radice,len);
}
altro
{
dimensione=*(loc+13);
/* Calcola per informazioni CHS */
calcola(inizio,&cilindro,&testa,&settore);
/* Integra il file */
integra(dimensione,cilindro,testata,settore);
}
}
Commenti sulla codifica:
La funzione retrieve() serve per ottenere l'input dell'utente per avviare il recupero. Il numero di file fornito come input dall'utente per recuperare il file, è memorizzato in file_no.
Se il numero immesso è per la voce Directory, Display_Information() mostra il contenuto di quella directory, altrimenti il nome del file e l'estensione del numero file_no vengono visualizzati sullo schermo per confermare il file da recuperare.
Per recuperare il file specificato , le funzioni calculate() e integrate() vengono chiamate all'interno della funzione. La codifica della funzione calculate() è stata fornita di seguito:
/* Funzione per calcolare la geometria CHS per il recupero */
void calculate(unsigned int inizio,unsigned int *cilindro,
unsigned int *testa,unsigned int *settore)
{
intero senza segno temporaneo;
*cilindro=0;
*testa=1;
*settore=14;
se(inizio<5)
*settore=14+inizio;
altro
{
temp= (inizio-4)/18;
se(temp>0)
{
se(temp%2==0)
*testa=0;
altro
*testa=1;
*cilindro+=1+temp/2;
}
altro
{
*testa=0;
*cilindro=1;
}
*settore=(inizio-4)%18;
}
/// Visualizza il CHS del file da recuperare \\\
gotossi(10,23);
cprintf("Cilindro = %u, Testa = %u, Settore = %u",
*cilindro,*testa,*settore);
}
Commenti sulla codifica:
La funzione calculate() serve a calcolare le informazioni di Cilindro, Testa e Settore per il file da recuperare. Dopo il calcolo, i numeri di Cilindro, Testa e Settore vengono visualizzati sullo schermo.
Di seguito è riportata la codifica per la funzione integrate():
/* Integra il file e salva il file recuperato nel percorso e nel nome file specificati */
void integrate(long unsigned int dimensione,
cilindro int senza segno,
testa int senza segno,
settore int senza segno)
{
void clear_the_line(int senza segno);
/* Funzione per verificare la presenza di errori nel settore */
int verify_the_sector(int senza segno, int senza segno,
intero senza segno);
int stato;
char buf[512],*Nome file_con_percorso;
struct diskinfo_t dinfo;
risultato int senza segno;
FILE *fp;
int senza segno left,i;
intero senza segno sec;
/* Inserisci il percorso di destinazione e il nome del file in cui salvare il file recuperato */
gotossi(2,24);
cprintf("Inserisci percorso e nome file per recuperare il file: ");
{NS} è il modo più semplice per impostare il valore di default.
gets(NomeFile_con_percorso);
fp=fopen(Nome file_con_percorso,"wb");
/* Se si è verificato un errore, visualizza un messaggio di errore e ottieni nuovamente il percorso e il nome del file */
se(fp==NULL)
{
gotossi(5,25);
cprintf("Errore nell'apertura del file");
ottenere();
cancella_la_linea(24);
gotossi(0,25);
{NS} = ";
integrate(dimensione,cilindro,testa,settore); /* Inserisci il
Destinazione di nuovo */
}
/* Se tutto è a posto, integra e scrivi */
gotossi(50,23);
cprintf("Integrazione........");
sinistra= dimensione%512;
sec = dimensione/512;
secondo++;
mentre(sec>0)
{
dinfo.drive = 0x00; /* numero unità per A: */
dinfo.head = testa; /* numero della testina del disco */
dinfo.track = cilindro; /* numero traccia */
dinfo.sector= settore; /* numero settore */
dinfo.nsectors=1; /* conteggio settori */
dinfo.buffer = buf; /* buffer dati */
risultato = _bios_disk(_DISK_READ, &dinfo);
/* Se si verifica un errore durante la lettura di un settore */
se( (risultato & 0xff00) != 0)
{
gotossi(5,25);
cprintf("errore di lettura Cilindro %u, Testina %u, Settore %u",
cilindro, testata, settore);
}
altro
{
se(secondo==1)
{
per(i=0;i<sinistra;i++)
fputc(buf[i],fp); /* Scrivi l'integrato
Informazioni sul file */
}
altro
{
fwrite(buf,512,1,fp);
}
Commenti sulla codifica:
La funzione integrate() è il modulo effettivo per eseguire il recupero del file specificato dall'utente, in questo programma di recupero .
Il nome del file con il percorso di destinazione per memorizzare il file recuperato è memorizzato nel puntatore di carattere *Filename_with_path. Se si verifica un errore nell'apertura del file di destinazione, viene visualizzato un messaggio di errore e all'utente viene chiesto di nuovo di immettere la destinazione.
La funzione _bios_disk(_DISK_READ, &dinfo); legge i dati del file dall'area dati del disco settore per settore, specificata dalla struttura dinfo e memorizzata nel buffer dati buf. Questi dati di 512 byte vengono scritti nel file di destinazione. Ciò viene ripetuto finché il file completo non viene integrato.
La funzione status=verify_the_sector (cylinder,head,sector); verifica il settore da leggere. Se lo status = 10, rappresenta un settore danneggiato (0xA). La codifica della funzione è stata fornita di seguito:
/// Verificare il settore. (Nessun dato viene trasferito qui) \\\
int verify_the_sector(int senza segno c,int senza segno h,int senza segno s)
{
int stato;
carattere *buf;
unione REGS dentro, fuori;
la struttura SREGS è sg;
in.h.ah = 0x04; /* Numero funzione */
in.h.al = 1; /* Numero di settori da verificare*/
in.h.dl = 0x00; /* Numero disco per A: */
in.h.ch = c; /* Numero cilindro */
pollice.h.dh = h; /* Numero della testa */
in.h.cl = s; /* Numero del settore */
in.x.bx = FP_OFF(buf);/* Spostamento */
sg.es = FP_SEG(buf); /* Segmento */
int86x(0x13,&entrata,&uscita,&sg); /* Chiama la funzione 4H
da INT 13H */
se(out.x.cflag)
{
stato=out.h.ah;
}
ritorno(stato);
}
Commenti sulla codifica:
La funzione verify_the_sector() verifica il settore che verrà letto dalla funzione _bios_disk() e restituisce lo stato dell'operazione. La funzione utilizza INT 13H e la funzione 4H per controllare il settore.
*buf — buffer dati, 0x04 — numero funzione specificato da in.h.ah = 0x04; e in.al. = 1; indica che è necessario controllare un settore alla volta. in.h.dl = 0x00; utilizzato per i numeri di unità floppy disk A:, c, h e s sono i numeri di cilindro, testina e settore .
La funzione int86x() viene utilizzata per chiamare INT 13H (funzione 4H) con valori del registro di segmento . Lo stato dell'operazione viene restituito come stato intero.
La funzione clear_the_line() cancella la riga specificata sullo schermo. La codifica della funzione è la seguente:
/* Funzione per cancellare una riga sullo schermo per il numero di riga specificato */
void clear_the_line(stringa intera senza segno)
{
colonna di numeri interi senza segno;
/* Ci sono 80 colonne in una riga */
per(colonna=1;colonna<=80;colonna++)
{
gotoxy(colonna, riga);
{NS} = "; /* Cancella con " " */
}
}
Commenti sulla codifica:
La funzione viene utilizzata per cancellare la riga specificata sullo schermo . La funzione viene chiamata con il numero di riga che deve essere cancellato dallo schermo.