Κεφάλαιο – 10
Ανάκτηση δεδομένων από κατεστραμμένη δισκέτα
Ανάκτηση δεδομένων από κατεστραμμένη δισκέτα
Η δισκέτα είναι μια από τις πιο αναξιόπιστες πηγές αποθήκευσης δεδομένων. Εάν πάτε σε οποιονδήποτε οργανισμό που χρησιμοποιεί συστήματα υπολογιστών και ρωτήσετε τους υπαλλήλους του για τα προβλήματα που δημιουργούνται από τις δισκέτες, θα ακούσετε πολύ συχνά το πρόβλημα ότι ο υπάλληλος του οργανισμού είχε κάποια σημαντικά δεδομένα στη δισκέτα του και τώρα η δισκέτα δεν είναι αναγνώσιμο από τον υπολογιστή και εμφανίζεται ένα μήνυμα κάτι σαν,
“Δεν είναι δυνατή η ανάγνωση του δίσκου”
“Κακό κομμάτι 0”
“Μη έγκυρη μονάδα δίσκου ή χωρητικότητα”
“Ο δίσκος δεν έχει μορφοποιηθεί. Θέλετε να το μορφοποιήσετε τώρα;”
Αυτό είναι το καθημερινό πρόβλημα για τους οργανισμούς που χρησιμοποιούν συστήματα υπολογιστών και δισκέτες. Το πρόβλημα γίνεται κρίσιμο όταν καταλάβετε ότι δεν υπήρχε αντίγραφο ασφαλείας ή διαθέσιμο αντίγραφο ασφαλείας για τα δεδομένα που φαίνεται να χάνονται στην κατεστραμμένη δισκέτα.
Η μεγαλύτερη κόλαση του προβλήματος υποτίθεται ότι έρχεται όταν δημιουργείτε αντίγραφα ασφαλείας στη δισκέτα για τις κρίσιμες πληροφορίες σας, τους δίσκους διάσωσης του προγράμματος προστασίας από ιούς για να ξεπεράσετε την επίθεση του ιού ή τις εγγραφές εκκίνησης ή άλλα αντίγραφα ασφαλείας (μπορεί να υπάρχουν πολλές δυνατότητες) στο μια δισκέτα και όταν θέλετε να χρησιμοποιήσετε ξανά το αντίγραφο ασφαλείας από τη δισκέτα, εμφανίζεται ένα σφάλμα ανάγνωσης.
Σε αυτήν την κατάσταση πρόκειται να χάσετε σημαντικές πληροφορίες και δεδομένα ή ακόμα και σε ορισμένες περιπτώσεις όταν αισθάνεστε ότι δεν υπάρχουν αντίγραφα ασφαλείας και προγράμματος ανάκτησης για τις πληροφορίες εκκίνησης του υπολογιστή σας και Διάσωση επίθεσης από ιούς προγράμματα κ.λπ., ενδέχεται να υποστείτε μεγάλη απώλεια δεδομένων με τη μορφή σφάλματος του λειτουργικού συστήματος λόγω έλλειψης πληροφοριών, αποθηκευμένων στη δισκέτα που δεν είναι αναγνώσιμη από τον υπολογιστή τώρα.
Σε τέτοιες περιπτώσεις, η πιο σημαντική απαίτηση είναι η ανάκτηση των δεδομένων από τη δισκέτα που έχει χαρακτηριστεί κακή από το σύστημα του υπολογιστή σας.
Γιατί η δισκέτα δεν είναι αναγνώσιμη
Το πιο συνηθισμένο πρόβλημα που προκαλεί μια δισκέτα να εμφανίζει τέτοιου είδους μηνύματα σφάλματος είναι η καταστροφή της δισκέτας της εγγραφής εκκίνησης DOS (DBR), η οποία βοηθά τον υπολογιστή να γνωρίζει τη λογική αναγνώριση της δισκέτας.
Το DBR είναι ένα μικρό πρόγραμμα που αποθηκεύεται στο κομμάτι 0, στην κεφαλή 0 και στον τομέα 1 και περιέχει σημαντικές πληροφορίες για τη δισκέτα, όπως:
- Αριθμός byte ανά τομέα
- Τομέας ανά σύμπλεγμα
- Αριθμός ΛΙΠΩΝ
- Μέγιστος αριθμός ριζικών καταλόγων κ.λπ.
Εφόσον η δισκέτα δεν έχει λογικό σύστημα διαμερισμάτων, επομένως δεν υπάρχει διαθέσιμο MBR σε δισκέτα. Ο πρώτος τομέας δισκέτας κατέχει το DBR. Αυτή είναι επίσης μια κύρια διαφορά για τη σύγκριση της λογικής δομής του σκληρού δίσκου με μια δισκέτα.
Όταν διαβάζουμε τις πληροφορίες του τομέα εκκίνησης μιας δισκέτας με τη βοήθεια οποιουδήποτε προγράμματος επεξεργασίας δίσκου, θα εμφανίζει πληροφορίες όπως στο σχήμα που δίνεται παρακάτω.
Το παρακάτω σχήμα δείχνει τις πληροφορίες 512 Byte του DBR ενός 1,44 MB, 3½ Δισκέτα ίντσας.
Εάν αυτές οι πληροφορίες είναι κατεστραμμένες με οποιοδήποτε τρόπο ή γίνονται δυσανάγνωστες, η δισκέτα προκαλεί τέτοια μηνύματα σφάλματος ανάγνωσης. Μπορεί να οφείλεται σε φυσική ή λογική καταστροφή του πρώτου τομέα του δίσκου.
Η Λογική καταστροφή περιλαμβάνει τις περιπτώσεις κατά τις οποίες αλλάζουν οι πληροφορίες του πρώτου τομέα της δισκέτας, εμφανίζεται οποιοσδήποτε λογικός κακός τομέας ή ο DBR strong> της δισκέτας είναι κατεστραμμένο για οποιονδήποτε άλλο λόγο.
Η Φυσική διαφθορά υποτίθεται ότι λαμβάνει χώρα σε περίπτωση, εάν υπάρχουν φυσικοί κακοί τομείς (σημαίνει ότι ο τομέας 1 έχει υποστεί φυσική βλάβη) στον πρώτο τομέα του δισκέτα. Το πρόβλημα γίνεται πιο σοβαρό όταν διαπιστώσετε ότι η δισκέτα έχει περισσότερους από έναν κακούς τομείς στο κομμάτι 0.
Πώς να ανακτήσετε
Όπως μάθαμε και τα δύο αίτια της διαφθοράς, ελπίζω τώρα να καταλάβετε το πρόβλημα. Δεν είναι πολύ δύσκολο να ανακτήσετε τα δεδομένα από τη λογική διαφθορά ωστόσο η ανάκτηση από τη φυσική διαφθορά χρειάζεται λίγο περισσότερες προσπάθειες για να γίνει.
Μέθοδος – 1
Αποθηκεύστε την εικόνα εκκίνησης οποιασδήποτε νέας δισκέτας
Εάν το πρόβλημα είναι λογικό, τώρα καταλαβαίνουμε πώς μπορούμε να ανακτήσουμε τα δεδομένα. Αυτό που πρέπει να κάνουμε είναι απλώς να πάρουμε την κατάλληλη εγγραφή εκκίνησης από μια άλλη δισκέτα ίδιου μεγέθους και χωρητικότητας και να την επικολλήσουμε στον πρώτο τομέα της μη αναγνώσιμης δισκέτας. Αν και το πρόβλημα δημιουργήθηκε λόγω της κακής εγγραφής εκκίνησης, θα πρέπει να λειτουργήσει τώρα.
Υπάρχουν δύο βήματα που εμπλέκονται σε αυτήν τη διαδικασία, ακολουθώντας τα οποία ανακτούμε τα δεδομένα μας από μια μη αναγνώσιμη δισκέτα:
- Δημιουργία της εικόνας του DOS Boot Record μιας καλής δισκέτας
- Επικόλληση της εικόνας εκκίνησης στον πρώτο τομέα της μη αναγνώσιμης δισκέτας
Δημιουργία της εικόνας του DOS Boot Record μιας καλής δισκέτας
Για να αποθηκεύσετε την εικόνα της εγγραφής εκκίνησης μιας νέας δισκέτας, το πρόγραμμα πρέπει να εκτελέσει τις ακόλουθες τρεις εργασίες:
- Διαβάστε ακριβώς τα πρώτα 512 byte της καλής δισκέτας
- Ελέγξτε για την επιτυχή λειτουργία ανάγνωσης (το πιο σημαντικό)
- Αποθηκεύστε αυτά τα 512 byte στο καθορισμένο όνομα αρχείου και διαδρομή προορισμού
Ο τομέας της δισκέτας είναι 512 byte και είναι απαραίτητο να αντιγράψετε την ακριβή εικόνα του τομέα. Είναι το πιο σημαντικό και απαραίτητο βήμα σε περίπτωση οποιουδήποτε τύπου λειτουργιών που εφαρμόζονται σε δισκέτα να ελέγξετε εάν η λειτουργία ήταν επιτυχής ή όχι.
Μπορεί να υπάρχει οποιοδήποτε πρόβλημα προετοιμασίας ακόμα και με την καλή και φρέσκια δισκέτα. Αυτός είναι ο λόγος που στις περισσότερες περιπτώσεις όταν η λειτουργία εκτελείται σε δισκέτες, πρώτα από όλα εκτελείται αρχικοποίηση δισκέτας στον προγραμματισμό με τη λειτουργία επαναφοράς δίσκου (Λειτουργία 00 H του INT 13H).
Αν ακόμη και μετά την προετοιμασία, η δισκέτα που εισήχθη πρόσφατα ή η δισκέτα που έχει αλλάξει προκαλεί οποιοδήποτε σφάλμα ανάγνωσης, συνιστάται να εκτελέσετε ξανά το πρόγραμμα, πιθανότατα μπορεί να λειτουργήσει αυτή τη φορά.
Το παρακάτω πρόγραμμα είναι για την εκτέλεση αυτών των καθορισμένων εργασιών. Ας δούμε πώς θα προχωρήσει:
/* Αποθηκεύστε την εικόνα εκκίνησης σε ένα αρχείο από μια νέα δισκέτα */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store Boot Image");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
while(count<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff );
count++;
}
fclose(fp);
gotoxy(10,14);cprintf("Disk read from Floppy disk drive
: successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n", result);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Εφόσον θέλουμε να διαβάσουμε τον πρώτο τομέα του δίσκου, η θέση του τομέα θα είναι η εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- Ανοίξτε μια ροή αρχείου με όνομα αρχείου και διαδρομή που έχει δοθεί στο χρήστη για να αποθηκεύσετε τις πληροφορίες εικόνας εκκίνησης των 512 byte ακριβώς. Το όνομα του αρχείου και η διαδρομή αποθηκεύονται στον πίνακα χαρακτήρων fname.
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 13H (συνάρτηση 00h) όπου το regs.h.ah = 0x00 δείχνει τη συνάρτηση 00 H και το regs.h.dl = 0x00 χρησιμοποιείται για ένα: δισκέτα. Και το int86(0x13, ®s, ®s) καλεί την υπηρεσία διακοπής MS-DOS INT 13 H.
- Το _bios_disk(_DISK_READ, &dinfo) διαβάζει τον καθορισμένο τομέα της δισκέτας.
- Η κατάσταση που επιστράφηκε αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση ενός μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Επικόλληση της εικόνας εκκίνησης στον πρώτο τομέα της μη αναγνώσιμης δισκέτας
Για την επικόλληση της εικόνας εκκίνησης από το αρχείο στον πρώτο τομέα της μη αναγνώσιμης δισκέτας, πρέπει να εκτελέσουμε τις ακόλουθες τρεις κύριες εργασίες στο πρόγραμμά μας:
- Διαβάστε ακριβείς πληροφορίες 512 byte της εγγραφής εκκίνησης μιας νέας δισκέτας από το αρχείο που είχε αποθηκευτεί προηγουμένως.
- Γράψτε αυτές τις πληροφορίες στον πρώτο τομέα της δισκέτας που αυτή τη στιγμή δεν είναι αναγνώσιμος.
- Ελέγξτε για την επιτυχή ολοκλήρωση της λειτουργίας εγγραφής (το πιο σημαντικό).
Καθώς ο τομέας της δισκέτας είναι 512 byte και είναι απαραίτητο να επικολλήσετε την ακριβή εικόνα εκκίνησης στον τομέα. Είναι το πιο σημαντικό και απαραίτητο βήμα σε περίπτωση οποιουδήποτε τύπου λειτουργιών που εφαρμόζονται σε δισκέτα να ελέγξετε εάν η λειτουργία ήταν επιτυχής ή όχι.
Μπορεί να υπάρχει οποιοδήποτε πρόβλημα προετοιμασίας με τη δισκέτα κατά τη διάρκεια της λειτουργίας, επομένως πρέπει να αρχικοποιήσετε τη δισκέτα επαναφέροντας το σύστημα του δίσκου(χρησιμοποιώντας τη συνάρτηση 00H του INT 13H).
Αν ακόμη και μετά την προετοιμασία, η δισκέτα που εισήχθη πρόσφατα ή η δισκέτα που έχει αλλάξει προκαλεί οποιοδήποτε σφάλμα ανάγνωσης, συνιστάται να εκτελέσετε ξανά το πρόγραμμα, πιθανότατα μπορεί να λειτουργήσει αυτή τη φορά.
Το παρακάτω πρόγραμμα είναι για την εκτέλεση αυτών των καθορισμένων εργασιών. Ας δούμε πώς θα προχωρήσει:
/* Φορτώστε την εικόνα εκκίνησης στη μη αναγνώσιμη δισκέτα */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
char dbuf[512];
FILE *fp;
clrscr();
gotoxy(5,3);cprintf("Enter The File Name And Path, In Which Boot image of Floppy Is Stored");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"rb");
if((fp=fopen(fname,"rb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be Opened");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to Recover Floppy disk drive :\n");
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
while(count<512)
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Successful!!! I Hope Floppy May
Work Now.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Καθώς πρόκειται να γράψουμε τις πληροφορίες στον πρώτο τομέα του δίσκου, επομένως η θέση του τομέα θα είναι η εξής:
- Ανοίξτε το αρχείο στο οποίο είχαν αποθηκευτεί οι πληροφορίες της εικόνας εκκίνησης των 512 byte μιας νέας δισκέτας από το προηγούμενο πρόγραμμα. Το όνομα του αρχείου και η διαδρομή αποθηκεύονται στον πίνακα χαρακτήρων fname.
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 13H (συνάρτηση 00h) όπου το regs.h.ah = 0x00 δείχνει τη συνάρτηση 00 H και το regs.h.dl = 0x00 χρησιμοποιείται για ένα: δισκέτα. Και το int86(0x13, ®s, ®s) καλεί την υπηρεσία διακοπής MS-DOS INT 13 H.
- Το _bios_disk(_DISK_WRITE, &dinfo) εγγράφει τις πληροφορίες εκκίνησης από το καθορισμένο αρχείο στον πρώτο (καθορισμένο) τομέα της δισκέτας.
- Η κατάσταση που επιστράφηκε αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση ενός μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
Ας το κάνουμε με ένα μόνο πρόγραμμα
Ελπίζω ότι τώρα καταλάβατε την έννοια πίσω από τέτοιου είδους ανάκτηση δεδομένων από τη δισκέτα. Μετά από αυτό, ας φανταστούμε ένα μεμονωμένο πρόγραμμα που δίνει τα ίδια αποτελέσματα που πήραμε με τη βοήθεια δύο προγραμμάτων που συζητήθηκαν προηγουμένως.
Κάναμε τις ακόλουθες εργασίες με τα προγράμματα που συζητήθηκαν πρόσφατα:
- Αποθηκεύστε τις πληροφορίες εκκίνησης από μια καλή δισκέτα σε ένα αρχείο
- Επικολλήστε αυτές τις πληροφορίες στον πρώτο τομέα της τρέχουσας μη αναγνώσιμης δισκέτας Το αρχείο που χρησιμοποιούσαμε για την αποθήκευση της εικόνας εκκίνησης λειτουργούσε ως ενδιάμεση γέφυρα για τη σύνδεση των λειτουργιών και των δύο προγραμμάτων. Αλλά αν ορίσουμε αυτές τις πληροφορίες εκκίνησης στην ίδια την κωδικοποίηση του προγράμματός μας, δεν χρειάζεται να δημιουργήσουμε ένα αρχείο όπως επίσης δεν χρειάζεται να διαβάσουμε τις πληροφορίες εκκίνησης της δισκέτας από το αρχείο.
Στο επόμενο πρόγραμμά μας, λέμε στο πρόγραμμά μας τι πρέπει να γράψει στον πρώτο τομέα της μη αναγνώσιμης δισκέτας και έτσι μπορούμε να αποφύγουμε δύο διαφορετικά προγράμματα να κάνουν την ίδια εργασία και μπορούμε να ανακτήσουμε τα δεδομένα μας με τον ίδιο τρόπο όπως πριν από το νέο ενιαίο πρόγραμμα.
Έτσι, το πρόγραμμα γίνεται απλό με λιγότερη κωδικοποίηση και είμαστε σε θέση να μειώσουμε την πιθανότητα εμφάνισης σφαλμάτων ανάγνωσης, εγγραφής ή δημιουργίας αρχείων. Κάνουμε τις ακόλουθες τέσσερις σημαντικές εργασίες σε αυτό το πρόγραμμα:
Μην πιστεύετε ότι το πρόγραμμα είναι δύσκολο να γραφτεί και να κατανοηθεί βλέποντας τις δεκαεξαδικές πληροφορίες των 512 byte του dbuf[512]. Αργότερα, θα συζητήσουμε τον εύκολο τρόπο εγγραφής αυτών των πληροφοριών για την κωδικοποίηση του προγράμματός σας.
- Καθορίστε τις πληροφορίες εγγραφής εκκίνησης DOS σε δεκαεξαδικό σύστημα που θα εγγραφούν στον πρώτο τομέα της τρέχουσας μη αναγνώσιμης δισκέτας.
- Επαναφέρετε το σύστημα του δίσκου για να αρχικοποιήσετε τη δισκέτα (INT 13H, Function 00H).
- Γράψτε την εγγραφή εκκίνησης του DOS στον πρώτο τομέα της δισκέτας
- Ελέγξτε για την επιτυχή ολοκλήρωση της λειτουργίας και σφάλμα, εάν προέκυψε.
Ας εξετάσουμε το πρόγραμμα:
/* Μονό πρόγραμμα για τη φόρτωση της προεπιλεγμένης εικόνας εκκίνησης σε μη αναγνώσιμη δισκέτα */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Εικόνα εκκίνησης για φόρτωση στη μονάδα δισκέτας */
static char 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; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk Write Status :successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-
protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13 extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
Σε αυτήν την κωδικοποίηση προγράμματος, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Η προσωρινή μνήμη στατικών χαρακτήρων dbuf[512] παρέχει την πληροφορία των 512 byte σε δεκαεξαδικό σύστημα, η οποία πρόκειται να γραφτεί στον πρώτο τομέα της μη αναγνώσιμης δισκέτας. Το dbuf[512] λέει στον υπολογιστή κατά τη διάρκεια της λειτουργίας ότι ποιες πληροφορίες πρέπει να γραφτούν στον πρώτο τομέα της δισκέτας. (Δείτε το Επόμενο Πρόγραμμα)
- dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Καθώς πρόκειται να γράψουμε τις πληροφορίες στον πρώτο τομέα του δίσκου, επομένως η θέση του τομέα θα είναι η εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 13H (συνάρτηση 00h) όπου το regs.h.ah = 0x00 δείχνει τη συνάρτηση 00 H και το regs.h.dl = 0x00 χρησιμοποιείται για μια δισκέτα. Και το int86(0x13, ®s, ®s) καλεί την υπηρεσία διακοπής MS-DOS INT 13 H.
- Το _bios_disk(_DISK_WRITE, &dinfo) εγγράφει τις πληροφορίες εκκίνησης από το καθορισμένο αρχείο στον πρώτο (καθορισμένο) τομέα της δισκέτας.
Η κατάσταση που επιστρέφεται αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση ενός μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Αποθήκευση της εικόνας εκκίνησης σε δεκαεξαδικούς χαρακτήρες για χρήση στο προηγούμενο πρόγραμμά μας
Θα είναι πολύ δύσκολη δουλειά να γράψετε και τους 512 χαρακτήρες της εγγραφής εκκίνησης DOS της δισκέτας με μη αυτόματο τρόπο σε δεκαεξαδικό σύστημα χωρίς κανένα σφάλμα στο πρόγραμμα που συζητήσαμε πρόσφατα. Εάν μπορούμε να το γράψουμε με ακρίβεια, τότε θα είναι δύσκολο και χρονοβόρο να το κάνουμε. Ας χρησιμοποιήσουμε λίγο δύσκολο μυαλό για να αποθηκεύσουμε τα δεδομένα για την προσωρινή μνήμη δεδομένων dbuf[512] σε ένα αρχείο.
Γνωρίζουμε ότι στον προγραμματισμό C οι δεκαεξαδικοί χαρακτήρες αντιπροσωπεύονται με 0x έτσι ώστε εάν ο δεκαεξαδικός χαρακτήρας είναι A9 H, θα το γράψουμε στο πρόγραμμά μας C ως 0xA9. Το επόμενο πρόγραμμα μας κάνει το ίδιο. Θα αποθηκεύσει τα δεδομένα που πρέπει να γράψουμε στο προηγούμενο πρόγραμμά μας, ως δεδομένα του buffer δεδομένων dbuf[512].
Αυτό που πρέπει να κάνετε είναι απλώς να πάρετε μια νέα και νέα δισκέτα για να δημιουργήσετε την εικόνα του DBR και να αντιγράψετε την έξοδο αυτού του προγράμματος από το καθορισμένο αρχείο προορισμού και να επικολλήσετε αυτά τα δεδομένα στο πρόγραμμά σας. Κάντε κάποια μορφοποίηση εάν απαιτείται. Ας δούμε πώς λειτουργεί:
/* Πρόγραμμα για τη δημιουργία της εικόνας εκκίνησης της δισκέτας σε HEX χαρακτήρα */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result,i;
int count=0;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store The Boot Image in HEX System");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("Attempting to read from Floppy
disk drive :\n");
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk read from Floppy disk drive :
successful.\n");
while(count<512)
{
fprintf(fp,"0x%X, ",dbuf[count] & 0xff );
count++;
}
fclose(fp);
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
}
return 0;
}
Σχόλια για την κωδικοποίηση του προγράμματος:
Έτσι τα δεδομένα αποθηκεύονται στο καθορισμένο αρχείο. Απλώς αντιγράψτε τα δεδομένα στο πρόγραμμά σας και κάντε κάποια απαιτούμενη μορφοποίηση. Δεν πρέπει ποτέ να ξεχνάτε τις παρακάτω συμβουλές κατά τη διάρκεια της διαδικασίας:
- Βεβαιωθείτε ότι η λειτουργία του προγράμματος ήταν επιτυχής και ότι τα δεδομένα που έχουν αποθηκευτεί στο αρχείο προορισμού είναι τα κατάλληλα.
- Θα πρέπει να ελέγξετε πλήρως τη λειτουργία για την εμφάνιση αναμενόμενων σφαλμάτων.
- Πρέπει να αρχικοποιήσετε τη δισκέτα με το πρόγραμμα πριν διαβάσετε τον τομέα εκκίνησης. Μπορείτε να χρησιμοποιήσετε τη λειτουργία 00H του INT 13H για αυτό το σκοπό.
Μέθοδος – 2
Τι πρέπει να κάνετε εάν η μέθοδος – 1 δεν λειτουργεί;
Εάν η Μέθοδος – 1 δεν λειτουργεί και ο μη αναγνώσιμος δίσκος δεν επιτρέπει στο πρόγραμμα να ξαναγράψει τις πληροφορίες εκκίνησης στον πρώτο του τομέα, θα πρέπει να δοκιμάσετε αυτήν τη δεύτερη μέθοδο. Ο λόγος πίσω από την αποτυχία της First Method μπορεί να είναι η φυσική καταστροφή του πρώτου τομέα της δισκέτας.
Σε αυτήν τη δεύτερη μέθοδο, θα αντιγράψουμε προσωρινά όλα τα δεδομένα της επιφάνειας της μη αναγνώσιμης δισκέτας σε ένα μόνο αρχείο και, στη συνέχεια, θα επικολλήσουμε αυτήν την εικόνα απευθείας στην επιφάνεια ενός άλλου καλού δίσκου.
Η διαδικασία περιλαμβάνει τα ακόλουθα δύο σημαντικά βήματα:
- Τομέας ανά τομέα Αντιγράψτε προσωρινά όλα τα δεδομένα της επιφάνειας των μέσων δισκέτας σε ένα μόνο αρχείο.
- Επικολλήστε τα δεδομένα που είχαν αποθηκευτεί προηγουμένως στο αρχείο, σε μια νέα νέα δισκέτα ως έχει, στους ίδιους τομείς.
Αντιγράψτε όλα τα δεδομένα της επιφάνειας πολυμέσων σε ένα μόνο αρχείο
Για να αποθηκεύσει όλα τα δεδομένα της επιφάνειας του μέσου της δισκέτας, το πρόγραμμα πρέπει να εκτελέσει τις ακόλουθες τρεις εργασίες:
- Εκκινήστε σωστά το δίσκο με τη βοήθεια της συνάρτησης 00H του INT 13H.
- Διαβάστε τις πληροφορίες ανά τομέα της επιφάνειας και αποθηκεύστε τις σε ένα μόνο αρχείο.
- Ελέγξτε για την επιτυχή λειτουργία ανάγνωσης (το πιο σημαντικό)
Είναι πολύ συνηθισμένο να έχετε οποιοδήποτε πρόβλημα προετοιμασίας με μια δισκέτα που οδηγεί πολλά μηνύματα που δεν αναγνώστηκαν με επιτυχία. Αυτός είναι ο λόγος για τον οποίο ο δίσκος πρέπει να προετοιμαστεί πριν από τη λειτουργία ανάγνωσης εγγραφής με τη βοήθεια προγραμματισμού.
Είναι το πιο σημαντικό και απαραίτητο βήμα σε περίπτωση οποιουδήποτε τύπου λειτουργιών που εφαρμόζονται σε δισκέτα να ελέγξετε εάν η λειτουργία ήταν επιτυχής ή όχι.
Εάν, ακόμη και μετά την προετοιμασία, η δισκέτα που εισήχθη πρόσφατα ή η δισκέτα που έχει αλλάξει προκαλεί οποιοδήποτε σφάλμα ανάγνωσης, συνιστάται να εκτελέσετε ξανά το πρόγραμμα, πιθανότατα αυτή τη φορά μπορεί να λειτουργήσει.
Το παρακάτω πρόγραμμα προορίζεται για την εκτέλεση αυτών των καθορισμένων εργασιών. Ας δούμε πώς θα προχωρήσει:
/* Πρόγραμμα για την αποθήκευση των δεδομένων της φυσικής επιφάνειας της δισκέτας σε ένα αρχείο */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File,
Press any Key To EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result,head,track,sector);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track,head,sector);
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το όνομα αρχείου του πίνακα χαρακτήρων[80] αποθηκεύει τη διαδρομή που ορίζει ο χρήστης και το όνομα αρχείου του αρχείου στο οποίο πρόκειται να αποθηκεύσουμε τα δεδομένα προσωρινά.
- dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 13H (συνάρτηση 00h) όπου το regs.h.ah = 0x00 δείχνει τη συνάρτηση 00 H και το regs.h.dl = 0x00 χρησιμοποιείται για ένα: δισκέτα. Και το int86(0x13, ®s, ®s) καλεί την υπηρεσία διακοπής MS-DOS INT 13 H.
- Καθώς πρόκειται να διαβάσουμε όλες τις πληροφορίες της επιφάνειας του δίσκου, οι παράμετροι του _bios_disk θα είναι οι εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_READ, &dinfo) διαβάζει τα δεδομένα από τη φυσική επιφάνεια της δισκέτας από τον τομέα που καθορίζεται από το dinfo.
- Η κατάσταση που επιστράφηκε αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση ενός μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Να θυμάστε πάντα ότι το μέγεθος του αρχείου που περιέχει την εικόνα των δεδομένων της δισκέτας πρέπει να είναι ακριβώς 1.474.560 byte επειδή η δισκέτα έχει 80 κομμάτια (0 έως 79), 2 πλευρές ή κεφαλές (κεφαλίδα 0 και κεφαλίδα 1), κάθε κομμάτι έχει 18 τομείς σε αυτό και κάθε τομέας περιέχει τα 512 byte δεδομένων, επομένως
Σύνολο byte = (Αριθμός κομματιών) * (Αριθμός κεφαλαίων) *
(Αριθμός Τομέων ανά Κομμάτι) * 512
= 80*2*18*512
= 1.474.560 Byte
Έτσι, εάν υπάρχει κάποιο σφάλμα στην ανάγνωση σε οποιονδήποτε τομέα της δισκέτας, θα αλλάξει το μέγεθος του αρχείου από 1.474.560 Byte, κάτι που θα καταστήσει πλήρως ή εν μέρει όλες τις πληροφορίες άχρηστες για τη δισκέτα προορισμού στην οποία πηγαίνουμε για να γράψετε την εικόνα του δίσκου ανά τομέα από αυτό το αρχείο.
Αυτό συμβαίνει επειδή ο υπολογιστής διαβάζει τις πληροφορίες οποιουδήποτε αρχείου στην επιφάνεια του μέσου της δισκέτας εντός του εύρους τομέα, όπως έχει εκχωρηθεί στη μονάδα εκχώρησης. Τώρα αν αλλάξουν οι τομείς των δεδομένων των αρχείων, αλλάζουν οι πλήρεις πληροφορίες του αρχείου.
Σκεφτόμαστε για τη λύση του σφάλματος ανάγνωσης τομέων
Είναι πιθανό με την κακή ή μη αναγνώσιμη δισκέτα να έχει τόσο κακή περιοχή στην επιφάνειά της ώστε να μην μπορούμε να διαβάσουμε τις πληροφορίες από την επιφάνεια του δίσκου.
Σε αυτήν την κατάσταση, οι πληροφορίες αυτού του τομέα(ων) θα παραβλεφθούν και η εικόνα της δισκέτας θα παραμορφωθεί ακόμη και για τους άλλους τομείς, καθώς το μέγεθος του αρχείου εικόνας σε αυτήν την περίπτωση διαφέρει από 1.474.560 Byte.
Για να διατηρήσουμε το μέγεθος του αρχείου εικόνας και να επικολλήσουμε τις υπόλοιπες πληροφορίες στις ακριβείς τοποθεσίες τομέα στο δίσκο προορισμού, γράφουμε κάποιες άλλες πληροφορίες για λογαριασμό των αρχικών δεδομένων των 512 byte και με αυτόν τον τρόπο,’ Θα είναι σε θέση να αποθηκεύσει τις υπόλοιπες πληροφορίες, ωστόσο η ανάκτηση σε αυτήν την περίπτωση μπορεί να είναι η μερική ανάκτηση.
Εάν το σύστημά σας αποτυγχάνει επίσης να διαβάσει τον πρώτο τομέα της δισκέτας προέλευσης, αφού επικολλήσετε την εικόνα στη δισκέτα προορισμού, θα πρέπει να εκτελέσετε το πρόγραμμα που περιγράφηκε προηγουμένως, για να ξαναγράψετε την Εγγραφή εκκίνησης DOS της δισκέτας .
Ας δούμε πώς μπορούμε να το κάνουμε προγραμματίζοντας:
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
/*Πληροφορίες 512 Byte για την κάλυψη του χώρου του Bad Sector */
/// Χρησιμοποιούσα 512 μηδενικά για να γεμίσω το διάστημα των 512 byte \\\
static char dbuf2[512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result, head, track, sector);
/* Εάν ο τομέας δεν είναι αναγνώσιμος, καταλάβετε 512 byte ανά dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση του προγράμματος, κάθε βήμα είναι το ίδιο όπως στο προηγούμενο πρόγραμμα, εκτός από την προσωρινή μνήμη δεδομένων dbuf2[512], την οποία χρησιμοποιούμε για να χειριστούμε το σφάλμα που δημιουργείται από τον κακό τομέα κατά τη λειτουργία ανάγνωσης δίσκου και για να διατηρήσετε το μέγεθος του αρχείου εικόνας.
Κάνοντας αυτό, γεμίζουμε το χώρο των πληροφοριών, τις οποίες δεν καταφέραμε να διαβάσουμε από τον κακό τομέα και τώρα γράφουμε τις ψευδοπληροφορίες των 512 byte ώστε να μπορούμε να διατηρήσουμε την ακρίβεια της εικόνας του δίσκου.
Επικολλήστε τα δεδομένα από το αρχείο στη φυσική επιφάνεια της νέας δισκέτας:
Σε αυτό το βήμα, επικολλάμε τα δεδομένα που είναι αποθηκευμένα στο αρχείο από το προηγούμενο πρόγραμμα, στη φυσική επιφάνεια της νέας δισκέτας, τομέα προς τομέα με τον ίδιο τρόπο με τον οποίο τα αντιγράψαμε στο αρχείο.
Το πρόγραμμα προχωρά με τα ακόλουθα κύρια βήματα:
- Ανοίξτε προσωρινά το αρχείο στο οποίο αποθηκεύσαμε τα δεδομένα επιφάνειας της μη αναγνώσιμης δισκέτας.
- Εκκινήστε σωστά το σύστημα δίσκου με τη λειτουργία επαναφοράς 00H του INT 13H.
- Γράψτε τις πληροφορίες για τους τομείς της νέας δισκέτας από το αρχείο.
- Εμφανίστε την κατάσταση εγγραφής ταυτόχρονα για να βρείτε ή να αποφύγετε την εμφάνιση σφαλμάτων.
Ο πηγαίος κώδικας του προγράμματος έχει δοθεί παρακάτω. Ας εξετάσουμε πώς λειτουργεί:
/* Πρόγραμμα εγγραφής των δεδομένων στους τομείς της επιφάνειας της φρέσκιας δισκέτας από το αρχείο, που δημιουργήθηκε από το προηγούμενο πρόγραμμα */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
int count =0;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *fp;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((fp=fopen(filename,"rb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(1);
}
/// Εκκινήστε το σύστημα δίσκων \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
count =0;
while(count<512 )
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector;/* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result= _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
printf("Successful write on Track = %d, Head = %d,
Sector = %d.\n", track, head, sector);
else
printf("Cannot read drive A, status = 0x%02x\n",
result);
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το όνομα αρχείου του πίνακα χαρακτήρων[80] περιέχει τη διαδρομή και το όνομα αρχείου του αρχείου στο οποίο αποθηκεύσαμε προσωρινά τα δεδομένα της επιφάνειας μιας μη αναγνώσιμης δισκέτας.
- dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 13H (συνάρτηση 00h) όπου το regs.h.ah = 0x00 δείχνει τη συνάρτηση 00 H και το regs.h.dl = 0x00 χρησιμοποιείται για ένα: δισκέτα. Και το int86(0x13, ®s, ®s) καλεί την υπηρεσία διακοπής MS-DOS INT 13 H.
- Καθώς πρόκειται να γράψουμε τις πληροφορίες απευθείας σε τομείς της επιφάνειας του δίσκου, οι παράμετροι του _bios_disk θα είναι οι εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- Το _bios_disk(_DISK_WRITE, &dinfo) γράφει τα δεδομένα στους τομείς της φυσικής επιφάνειας της δισκέτας, που καθορίζονται από το dinfo.
- Η κατάσταση που επιστράφηκε αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση ενός μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Εάν μετά τη Μέθοδο – 2 η νέα σας δισκέτα δεν λειτουργεί, μπορείτε να εφαρμόσετε περαιτέρω τη μέθοδο – 1 στη νέα σας δισκέτα, την οποία χρησιμοποιήσατε ως δίσκο προορισμού κατά τη διάρκεια της μεθόδου – 2.
Όχι μόνο αυτό, αλλά και ο αριθμός των επισκέψεων και των δοκιμών μπορεί να διαφέρει ανάλογα με την καταστροφή του δίσκου. Αλλά δεν χρειάζεται να ανησυχείτε εάν ακόμη και μετά δεν έχετε τα ικανοποιητικά αποτελέσματα.
Μπορείτε να δοκιμάσετε την ανάκτηση αρχείου ανά αρχείο ή μπορείτε να δοκιμάσετε πολλές ακόμη συμβουλές που θα μάθετε στο επόμενο. Εδώ θα εφαρμόσουμε την ιδέα της συλλογής των πληροφοριών αρχείων από τους καταλόγους Root, στον προγραμματισμό μας για την ανάκτηση των δεδομένων.
Σκεφτείτε για λογική ανάκτηση για διαγραμμένα ή χαμένα δεδομένα:
Όλες οι προηγούμενες περιπτώσεις που συζητήσαμε σε αυτό το κεφάλαιο για ανάκτηση, ήταν για ανάκτηση των δεδομένων σε τέτοιες περιπτώσεις όπου περιμέναμε ότι μόνο το DBR είναι κατεστραμμένο και οι τομείς στο κομμάτι 0, με FAT1, FAT2 και Οι κατάλογοι Root είναι αναγνώσιμοι.
Αλλά εάν το πρόβλημα οφείλεται στην καταστροφή του FAT ή εάν τα δεδομένα έχουν διαγραφεί από το δίσκο ή θέλετε να ανακτήσετε τα δεδομένα απευθείας διαβάζοντας τις πληροφορίες του από τον κατάλογο Root, πρέπει να διαβάσουμε τις πληροφορίες όπως Όνομα αρχείου, συμπλέγμα έναρξης, μέγεθος αρχείου , Χαρακτηριστικό κ.λπ. από την καταχώριση καταλόγου ρίζας.
Όπως έχουμε ήδη συζητήσει σχετικά με τον Root Directory σε προηγούμενα κεφάλαια ότι υπάρχουν πληροφορίες 32 Byte για κάθε αρχείο ή κατάλογο. Αυτά τα 32 Byte χωρίζονται ως εξής:
Αριθμός Byte |
Περιγραφή πληροφοριών |
8 Bytes |
Filename |
3 Bytes |
Extension |
1 Byte |
Attribute |
10 Bytes |
Reserved |
2 Bytes |
Time, Created or Last Updated |
2 Bytes |
Date, Created or Last Updated |
2 Bytes |
Starting Cluster |
4 Bytes |
File Size |
ανακτούμε τα δεδομένα διαβάζοντας τις πληροφορίες των αρχείων από τον Root Directory και, στη συνέχεια, ενσωματώνουμε το αρχείο στη διαδρομή προορισμού και ανακτούμε το αρχείο. Το επόμενο πρόγραμμά μας εκτελεί τα ακόλουθα βήματα για την ανάκτηση των δεδομένων:
- Διαβάστε τις καταχωρήσεις του καταλόγου ρίζαςκαι εμφανίστε τις στην οθόνη με όλες τις πληροφορίες, όπως Όνομα αρχείου/καταλόγου, Επέκταση του αρχείου, Μέγεθος συμπλέγματος έναρξης των αρχείων σε Byte.
- Διαβάστε τις πληροφορίες Αρχείων και Καταλόγων στους Υποκαταλόγους και εμφανίστε τους εάν απαιτείται.
- Επιβεβαιώστε το όνομα αρχείου που θέλετε να ανακτήσετε και συνεχίστε την ανάκτηση.
- Υπολογίστε τις πληροφορίες CHS (Κύλινδρος, Κεφαλή και Τομέας) για το Καθορισμένο αρχείο προς ανάκτηση.
- Ενσωματώστε τα δεδομένα του αρχείου από την περιοχή δεδομένων του δίσκου και αποθηκεύστε το ανακτημένο αρχείο στο καθορισμένο όνομα αρχείου προορισμού στην καθορισμένη διαδρομή.
Αυτό το πρόγραμμα δεν ενδιαφέρεται εάν οι πληροφορίες εκκίνησης της δισκέτας είναι αναγνώσιμες ή όχι. Επομένως, μπορείτε επίσης να ανακτήσετε ακόμη και διαγραμμένα δεδομένα από την κατεστραμμένη δισκέτα. Ας δούμε την κωδικοποίηση του προγράμματος:
/* Πρόγραμμα για την ανάκτηση των δεδομένων από τη δισκέτα διαβάζοντας πληροφορίες αρχείου από τον κατάλογο ρίζας */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
unsigned int);
unsigned int track=0,head=1,sector=2;
Display_Information(track,head,sector);
} /*End of main */
void Display_Information(unsigned int track,
unsigned int head,
unsigned int sector)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // Buffer of 512 Bytes
char ch;
struct diskinfo_t finfo; //Structure, Used by _bios_disk
unsigned int result,i,j, count=0; /* Unsigned Integers
Defined */
unsigned int file_no; /* Unsigned Integer
for File Number */
struct
{
unsigned int name[8],ext[3]; /* File Name for DOS in 8.3
(Eight Dot Three) Format */
unsigned int attribute; // File/Directory Attribute
unsigned int start; // Starting Cluster of the File
long unsigned int size; // Size of the File in Bytes
}root[32]; /* 32 Bytes Information of
File/Directory in Root
Directory */
clrscr();
do
{
file_no=0;
finfo.drive = 0x00; /* drive number for A: */
finfo.head = head; /* disk head number */
finfo.track = track; /* track number */
finfo.sector= sector; /* sector number */
finfo.nsectors=1; /* sector count */
finfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &finfo); /* Read the
Sector */
if( (result & 0xff00) != 0) /* If Read Error, Display
Error Message and Exit*/
{
printf("Read error");
getch();
exit(0); // Go Back to DOS
}
/// Μορφή οθόνης προβολής πληροφοριών \\\
clrscr();
gotoxy(9,1);
cprintf("DISPLAY CYLN: %u, HEAD: %u, SECTOR: %u",
track, head, sector);
gotoxy(9,2);
cprintf("FNO NAME EXT ATTRIBUTE START SIZE");
gotoxy(7,3);
cprintf("--------------------------------------------");
/* Ένας Τομέας τη φορά. Κάθε καταχώρηση αρχείου/DIR παίρνει 32 byte */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Βρείτε το όνομα αρχείου/σκηνοθέτη \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Βρείτε την επέκταση \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Συστάδα εκκίνησης \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Υπολογίστε το Μέγεθος \\\
root[file_no].size =(long unsigned int)(0xff &
buf[31+i])*16*16*16*16*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[30+i])*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[29+i])*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[28+i]);
if((root[file_no].start == 0) ||
(root[file_no].attribute == 15))
continue;
else
{
gotoxy(8,i/32+4);
cprintf("%2u",file_no); /* Display File
Number */
for(j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Display File
Name */
}
for(j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Display
Extension */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Display
Attribute */
if(root[file_no].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Display if Directory Attribute */
}
else
{
gotoxy(33,i/32+4);
cprintf("<FILE>"); /* The Entry is of a file */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Display
Starting Cluster */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* size of the
File */
}
file_no++;
}
gotoxy(10,
cprintf("Press 'M' : To see list of more files &quo
gotoxy(10,
cprintf("Press 'R' :To recover a file from the above
list&quo
ch=getc
Θυμηθείτε ότι το όνομα αρχείου που ξεκινά με s (E5H) αντιπροσωπεύει ότι το αρχείο έχει διαγραφεί και επομένως ο πρώτος χαρακτήρας του ονόματος αρχείου έχει αντικατασταθεί με s (Δείτε την περιγραφή του ριζικού καταλόγου στα προηγούμενα κεφάλαια ).
Και η έξοδος του προγράμματος εμφανίζεται ως εξής:
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
--------------------------------------------------------------------------
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
Press 'M' : To see list of more files
Press 'R' :To recover a file from the above list R
|
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
----------------------------------------------------------------------------
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
Enter FNO. of the file you want to recover 1
You want to recover _2_INFO .C
Cylinder = 1, Head = 0, Sector = 1 Integrating........
Enter Path and Filename to recover the file: c:\windows\desktop\H2_INFO.C
Recovery Done !!!
|
Σχόλια σχετικά με την κωδικοποίηση:
Η λειτουργία Πληροφορίες_Προβολής είναι η ανάγνωση των πληροφοριών του αρχείου και του καταλόγου και από τον ριζικό κατάλογο. Στη Δομή διαβάζουμε τις πληροφορίες των 32 byte για κάθε αρχείο ή κατάλογο με root[32].
Το όνομα των ανυπόγραφων ακέραιων πινάκων[8] και ext[3] είναι για όνομα αρχείου ή καταλόγου για DOS σε μορφή 8.3 (Οκτώ κουκκίδες τρία). Ομοίως, ένα byte είναι για το χαρακτηριστικό και δύο byte για το αρχικό σύμπλεγμα. μακρύ ανυπόγραφο μέγεθος int. είναι να αποθηκεύσετε το μέγεθος του αρχείου των τεσσάρων byte.
Η συνάρτηση _bios_disk διαβάζει τον τομέα, που καθορίζεται από τη δομή finfo και η κατάσταση της λειτουργίας αποθηκεύεται ως αποτέλεσμα.
Από κάθε πληροφορία 512 byte που διαβάζεται από τη _bios_disk function, μέχρι να τελειώσει η περιοχή καταλόγου ρίζας, συλλέγουμε τις πληροφορίες των αρχείων και των καταλόγων που είναι αποθηκευμένα στο δίσκο και εμφανίστε τα στην οθόνη.
Ο ακέραιος file_no αποθηκεύει τον αριθμό του αρχείου ή του καταλόγου στη λίστα, ξεκινώντας από το 0. Γενικά το μέγεθος του ριζικού καταλόγου είναι 14 τομέων και ο ριζικός κατάλογος ξεκινά γενικά από Cylinder =0, Head = 0 και Sector =2 σε περίπτωση 1,44 MB και 3½ δισκέτα.
Εάν ο χρήστης δώσει τον χαρακτήρα ‘M’ ή ‘m’ Ως είσοδος, εμφανίζονται οι πληροφορίες του επόμενου τομέα εάν η επιλογή από τον χρήστη είναι ‘R’ ή ‘r’ καλούνται οι συναρτήσεις ανάκτησης. Η κωδικοποίηση της συνάρτησης recover() έχει δοθεί παρακάτω:
/* Λειτουργία για να ξεκινήσει η ανάκτηση για το καθορισμένο αρχείο */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Λειτουργία για ενσωμάτωση του καθορισμένου αρχείου */
void integrate(long unsigned int,unsigned int,
unsigned int,unsigned int);
unsigned int file_no,i;
char ch;
unsigned int *loc;
unsigned int cylinder,head,sector;
unsigned int start;
long unsigned int size;
clear_the_line(21); /* Clear The Row Number 21 */
clear_the_line(22); /* Clear The Row Number 22 */
clear_the_line(23); /* Clear The Row Number 23 */
clear_the_line(24); /* Clear The Row Number 24 */
gotoxy(10,21);
cprintf("Enter FNO. of the file you want to recover");
scanf("%u",&file_no); /* Get the File No. to be
Recovered */
loc=(root+(len*file_no/2));
/* Επιβεβαιώστε το όνομα αρχείου που πρόκειται να ανακτηθεί */
gotoxy(10,22);
cprintf("You want to recover");
for(i=0;i<8;i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* File name */
}
gotoxy(38,22);
cprintf(".");
for(i=0;i<3;i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* File Extension */
}
start=*(loc+12);
/// Λυπούμαστε, επιλέξατε έναν κατάλογο \\\
if(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Is A directory. Do you want to see the
contents of this directory Y/N");
ch=getch();
if(ch==27)
main();
if(ch=='y' || ch=='Y')
{
/* Υπολογίστε τη Γεωμετρία */
calculate(start,&cylinder,&head,§or);
/* Εμφάνιση περιεχομένων καταλόγου */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Υπολογίστε για πληροφορίες CHS */
calculate(start,&cylinder,&head,§or);
/* Integrate The File */
integrate(size,cylinder,head,sector);
}
}
Σχόλια σχετικά με την κωδικοποίηση:
Η λειτουργία recover() είναι να λαμβάνει τα στοιχεία του χρήστη για να ξεκινήσει η ανάκτηση. Ο αριθμός αρχείου που δίνεται ως είσοδος από τον χρήστη για την ανάκτηση του αρχείου, αποθηκεύεται στο file_no.
Εάν ο αριθμός που εισαγάγατε είναι για την καταχώριση καταλόγου, η Display_Information() εμφανίζει τα περιεχόμενα αυτού του καταλόγου, διαφορετικά Το όνομα αρχείου και η επέκταση του αριθμού αρχείου file_no εμφανίζεται στην οθόνη για επιβεβαίωση του αρχείου που πρόκειται να ανακτηθεί.
Για ανάκτηση του καθορισμένου αρχείου, οι συναρτήσεις calculate() και integrate() καλούνται εντός της συνάρτησης. Η κωδικοποίηση της συνάρτησηςcalculate() έχει δοθεί παρακάτω:
/* Λειτουργία Υπολογισμός της Γεωμετρίας CHS για την ανάκτηση */
void calculate(unsigned int start,unsigned int *cylinder,
unsigned int *head,unsigned int *sector)
{
unsigned int temp;
*cylinder=0;
*head=1;
*sector=14;
if(start<5)
*sector=14+start;
else
{
temp= (start-4)/18;
if(temp>0)
{
if(temp%2==0)
*head=0;
else
*head=1;
*cylinder+=1+temp/2;
}
else
{
*head=0;
*cylinder=1;
}
*sector=(start-4)%18;
}
/// Εμφάνιση του CHS του αρχείου προς ανάκτηση \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση calculate() είναι ο υπολογισμός των πληροφοριών κυλίνδρου, κεφαλής και τομέα για το αρχείο που πρόκειται να ανακτηθεί. Μετά τον υπολογισμό εμφανίζονται στην οθόνη οι αριθμοί κυλίνδρου, κεφαλής και τομέα.
Η κωδικοποίηση για τη συνάρτηση integrate() έχει δοθεί παρακάτω:
/* Ενσωμάτωση αρχείου και αποθήκευση του ανακτημένου αρχείου στην καθορισμένη διαδρομή και το όνομα αρχείου */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Λειτουργία για την επαλήθευση του τομέα για σφάλματα */
int verify_the_sector(unsigned int, unsigned int,
unsigned int);
int status;
char buf[512],*Filename_with_path;
struct diskinfo_t dinfo;
unsigned int result;
FILE *fp;
unsigned int left,i;
unsigned int sec;
/* Εισαγάγετε τη διαδρομή προορισμού και το όνομα αρχείου για να αποθηκεύσετε το ανακτημένο αρχείο */
gotoxy(2,24);
cprintf("Enter Path and Filename to recover the file: ");
fflush(stdin);
gets(Filename_with_path);
fp=fopen(Filename_with_path,"wb");
/* Εάν προέκυψε σφάλμα Εμφανίστε το μήνυμα λάθους και λάβετε ξανά τη διαδρομή και το όνομα αρχείου */
if(fp==NULL)
{
gotoxy(5,25);
cprintf("Error in opening the file");
getch();
clear_the_line(24);
gotoxy(0,25);
cprintf(" ");
integrate(size,cylinder,head,sector); /* Enter the
Destination Again */
}
/* Αν όλα είναι εντάξει, ενσωματώστε και γράψτε */
gotoxy(50,23);
cprintf("Integrating........");
left= size%512;
sec = size/512;
sec++;
while(sec>0)
{
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = cylinder; /* track number */
dinfo.sector= sector; /* sector number */
dinfo.nsectors=1; /* sector count */
dinfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
/* If there is Error While Reading any Sector */
if( (result & 0xff00) != 0)
{
gotoxy(5,25);
cprintf("read error Cylinder %u, Head %u, Sector %u",
cylinder, head, sector);
}
else
{
if(sec==1)
{
for(i=0;i<left;i++)
fputc(buf[i],fp); /* Write The Integrated
Information to the File */
}
else
{
fwrite(buf,512,1,fp);
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση integrate() είναι η πραγματική ενότητα για την εκτέλεση της ανάκτησης του καθορισμένου αρχείου από τον χρήστη, σε αυτό το πρόγραμμα ανάκτησης.
Το όνομα αρχείου με τη διαδρομή προορισμού για την αποθήκευση του ανακτημένου αρχείου αποθηκεύεται στον δείκτη χαρακτήρων *Filename_with_path. Εάν υπάρχει κάποιο σφάλμα στο άνοιγμα του αρχείου προορισμού, εμφανίζεται μήνυμα σφάλματος και ζητείται από τον χρήστη ξανά να εισαγάγει τον προορισμό.
Η συνάρτηση _bios_disk(_DISK_READ, &dinfo); διαβάζει τα δεδομένα του αρχείου από την περιοχή δεδομένων του τομέα του δίσκου ανά τομέα, που καθορίζονται από τη δομή dinfo και αποθηκεύονται στο buffer δεδομένων . Αυτά τα δεδομένα των 512 byte εγγράφονται στο αρχείο προορισμού. Αυτό επαναλαμβάνεται μέχρι να ενσωματωθεί ολόκληρο το αρχείο.
Η συνάρτηση status=verify_the_sector (κύλινδρος, κεφαλή, τομέας); επαληθεύει τον τομέα προς ανάγνωση. Εάν η κατάσταση = 10, αντιπροσωπεύει έναν κακό (0xA) τομέα. Η κωδικοποίηση της συνάρτησης έχει δοθεί παρακάτω:
/// Επαληθεύστε τον Τομέα. (Δεν μεταφέρονται δεδομένα εδώ) \\\
int verify_the_sector(unsigned int c,unsigned int h,unsigned int s)
{
int status;
char *buf;
union REGS in, out;
struct SREGS sg;
in.h.ah = 0x04; /* Function Number */
in.h.al = 1; /* Number of Sectors to Verify*/
in.h.dl = 0x00; /* Drive Number for A: */
in.h.ch = c; /* Cylinder Number */
in.h.dh = h; /* Head Number */
in.h.cl = s; /* Sector Number */
in.x.bx = FP_OFF(buf);/* Offset */
sg.es = FP_SEG(buf); /* Segment */
int86x(0x13,&in,&out,&sg); /* Call the Function 4H
of INT 13H */
if(out.x.cflag)
{
status=out.h.ah;
}
return(status);
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση verify_the_sector(), επαληθεύει τον τομέα που θα διαβαστεί από τη συνάρτηση _bios_disk() και επιστρέφει την κατάσταση της λειτουργίας. Η συνάρτηση χρησιμοποιεί INT 13H και συνάρτηση 4H για την επαλήθευση του τομέα.
*buf είναι η προσωρινή μνήμη δεδομένων, 0x04 είναι ο αριθμός συνάρτησης που καθορίζεται από το in.h.ah = 0x04; και in.h.al = 1; καθοδηγεί την επαλήθευση ενός τομέα κάθε φορά. in.h.dl = 0x00; χρησιμοποιείται για τον αριθμό μονάδας δίσκου για μονάδα δισκέτας A:, c,h και s είναι αριθμοί Κύλινδρος, Κεφαλή και Τομέας.
Η συνάρτηση int86x() χρησιμοποιείται για την κλήση του INT 13H (συνάρτηση 4H) με τιμές καταχωρητή τμημάτων. Η κατάσταση της λειτουργίας επιστρέφεται από την κατάσταση ακέραιου αριθμού.
Η συνάρτηση clear_the_line() διαγράφει την καθορισμένη σειρά στην οθόνη. Η κωδικοποίηση της συνάρτησης είναι η εξής:
/* Λειτουργία για διαγραφή της γραμμής στην οθόνη, για τον καθορισμένο αριθμό σειράς */
void clear_the_line(unsigned int row)
{
unsigned int column;
/* There are 80 Columns in a Row (Line) */
for(column=1;column<=80;column++)
{
gotoxy(column,row);
cprintf(" "); /* Clear With " " */
}
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση χρησιμοποιείται για την εκκαθάριση της καθορισμένης σειράς στην οθόνη. Η συνάρτηση καλείται με τον αριθμό της σειράς, η οποία πρέπει να διαγραφεί από την οθόνη.
Σελίδα Τροποποιήθηκε στις: 14/01/2022