Κεφάλαιο – 10
ΑΝΑΚΤΗΣΗ ΔΕΔΟΜΕΝΩΝ ΑΠΟ ΧΑΛΑΜΜΕΝΟ ΔΙΣΚΟ
Ανάκτηση δεδομένων από κατεστραμμένη δισκέτα
Μια δισκέτα είναι μια από τις πιο αναξιόπιστες πηγές αποθήκευσης δεδομένων. Εάν πάτε σε οποιονδήποτε οργανισμό που χρησιμοποιεί συστήματα υπολογιστών και ρωτήσετε τους υπαλλήλους του για προβλήματα που προκαλούνται από δισκέτες, θα ακούσετε πολύ συχνά ότι το πρόβλημα είναι ότι ένας υπάλληλος του οργανισμού είχε κάποια σημαντικά δεδομένα στη δισκέτα του και τώρα η δισκέτα δεν είναι αναγνώσιμη από τον υπολογιστή και εμφανίζεται ένα μήνυμα στην οθόνη παρόμοιο με:
"Δεν είναι δυνατή η ανάγνωση του δίσκου"
"Εσφαλμένο κομμάτι 0"
"Μη έγκυρος δίσκος ή χωρητικότητα"
"Ο δίσκος δεν έχει διαμορφωθεί. Θέλετε να το μορφοποιήσετε τώρα;
Αυτό είναι ένα καθημερινό πρόβλημα για οργανισμούς που χρησιμοποιούν συστήματα υπολογιστών και δισκέτες. Το πρόβλημα γίνεται κρίσιμο όταν ανακαλύψετε ότι δεν δημιουργήθηκε αντίγραφο ασφαλείας ή ότι δεν υπάρχει διαθέσιμο αντίγραφο ασφαλείας για τα δεδομένα που φαίνεται να χάνονται στην κατεστραμμένη δισκέτα.
Το μεγαλύτερο πρόβλημα παρουσιάζεται όταν δημιουργείτε αντίγραφα ασφαλείας κρίσιμων πληροφοριών σε μια δισκέτα, επαναφέρετε δίσκους προγραμμάτων προστασίας από ιούς για να ξεπεράσετε μια επίθεση ιού ή εγγραφές εκκίνησης ή άλλα αντίγραφα ασφαλείας (μπορεί να υπάρχουν πολλές επιλογές) σε μια δισκέτα και όταν θέλετε να χρησιμοποιήσετε ξανά το αντίγραφο ασφαλείας από τη δισκέτα, παρουσιάζεται σφάλμα ανάγνωσης.
Σε μια τέτοια περίπτωση, κινδυνεύετε να χάσετε σημαντικές πληροφορίες και δεδομένα, και σε ορισμένες περιπτώσεις, όταν αισθάνεστε έλλειψη αντιγράφων ασφαλείας και προγραμμάτων ανάκτησης για τις πληροφορίες εκκίνησης του υπολογιστή σας, προγράμματα διάσωσης από ιούς κ.λπ., ενδέχεται να υποστείτε σημαντική απώλεια δεδομένων με τη μορφή αποτυχίας του λειτουργικού συστήματος λόγω της έλλειψης πληροφοριών που είναι αποθηκευμένες στη δισκέτα, οι οποίες δεν μπορούν να διαβαστούν από τον υπολογιστή αυτήν τη στιγμή.
Σε τέτοιες περιπτώσεις, η πιο σημαντική απαίτηση είναι η ανάκτηση δεδομένων από μια δισκέτα που το σύστημα του υπολογιστή σας έχει αναγνωρίσει ως ελαττωματικό.
Γιατί η δισκέτα δεν είναι αναγνώσιμη;
Το πιο συνηθισμένο πρόβλημα που προκαλεί μια δισκέτα να δίνει τέτοια μηνύματα σφάλματος είναι η καταστροφή του DOS Boot Record (DBR) της δισκέτας, η οποία βοηθά τον υπολογιστή να γνωρίζει τη λογική ταυτότητα της δισκέτας.
Το DBR είναι ένα μικρό πρόγραμμα αποθηκευμένο στο κομμάτι 0, στην κεφαλή 0 και στον τομέα 1 που περιέχει σημαντικές πληροφορίες για τη δισκέτα, όπως:
- Αριθμός byte ανά τομέα
- Τομέας ανά σύμπλεγμα
- Αριθμός FAT
- Μέγιστος αριθμός ριζικών καταλόγων κ.λπ.
Δεδομένου ότι η δισκέτα δεν διαθέτει σύστημα λογικού διαμερίσματος, δεν υπάρχει MBR στη δισκέτα. Ο πρώτος τομέας της δισκέτας περιέχει το DBR. Αυτή είναι επίσης η κύρια διαφορά κατά τη σύγκριση της λογικής δομής ενός σκληρού δίσκου με μια δισκέτα.
Όταν διαβάζουμε τις πληροφορίες του τομέα εκκίνησης της δισκέτας χρησιμοποιώντας οποιοδήποτε πρόγραμμα επεξεργασίας δίσκου, θα εμφανίζει πληροφορίες όπως αυτή που φαίνεται στην παρακάτω εικόνα.
Το παρακάτω σχήμα δείχνει 512 byte πληροφοριών DBR σε μια δισκέτα 1,44 MB, 3½ ιντσών.

Εάν αυτές οι πληροφορίες καταστραφούν με κάποιο τρόπο ή γίνουν δυσανάγνωστες, η δισκέτα θα παράγει αυτά τα μηνύματα σφάλματος ανάγνωσης. Αυτό μπορεί να οφείλεται σε φυσική ή λογική βλάβη στον πρώτο τομέα του δίσκου.
Η λογική καταστροφή περιλαμβάνει περιπτώσεις όπου οι πληροφορίες στον πρώτο τομέα της δισκέτας αλλάζουν, υπάρχει κάποιος λογικά κατεστραμμένος τομέας ή το DBR της δισκέτας έχει καταστραφεί για κάποιο άλλο λόγο.
Θεωρείται ότι συμβαίνει φυσική βλάβη εάν ο πρώτος τομέας της δισκέτας έχει φυσικούς κατεστραμμένους τομείς (δηλαδή ο τομέας 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 (κενό)
{
struct diskinfo_t dinfo;
ένωση REGS regs;
int αποτέλεσμα?
int count=0, i;
char fname[80];
στατικό char dbuf[512];
ΑΡΧΕΙΟ *fp;
dinfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = 0; /* αριθμός κεφαλής δίσκου */
dinfo.track = 0; /* αριθμός κομματιού */
dinfo.sector = 1; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
clrscr();
gotoxy(10,3);cprintf("Εισαγάγετε το όνομα αρχείου και τη διαδρομή προς
Store Boot Image");
gotoxy (5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("Δεν ήταν δυνατή η δημιουργία αρχείου");
getch();
exit(0);
}
gotoxy (10,9);
cprintf("Προσπάθεια ανάγνωσης από μονάδα δισκέτας :\n");
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
αποτέλεσμα = _bios_disk(_DISK_READ, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
ενώ (count<512)
{
fprintf(fp,"%c", dbuf[count] & 0xff );
count++;
}
fclose(fp);
gotoxy(10,14);cprintf("Ανάγνωση δίσκου από μονάδα δισκέτας
: επιτυχημένη.\n");
}
αλλού
{
gotoxy (10,14);
cprintf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση = 0x%02x\n", αποτέλεσμα);
διακόπτης (αποτέλεσμα)
{
περίπτωση 0x00:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κανένα σφάλμα!! ");
διακοπή;
περίπτωση 0x01:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κακή εντολή ");
διακοπή;
περίπτωση 0x02:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το σημάδι διεύθυνσης δεν βρέθηκε ");
διακοπή;
περίπτωση 0x03:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εγγραφής σε δίσκο με προστασία εγγραφής ");
διακοπή;
περίπτωση 0x04:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τομέας δεν βρέθηκε ");
διακοπή;
περίπτωση 0x06:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο δίσκος άλλαξε από την τελευταία λειτουργία ");
διακοπή;
περίπτωση 0x08:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση άμεσης πρόσβασης στη μνήμη (DMA) ");
διακοπή;
περίπτωση 0x09:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εκτέλεσης DMA κατά μήκος ορίων 64K ");
διακοπή;
θήκη 0x0C:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τύπος μέσου δεν βρέθηκε ");
διακοπή;
θήκη 0x10:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένη ανάγνωση CRC/ECC στο δίσκο ");
διακοπή;
θήκη 0x20:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο ελεγκτής απέτυχε ");
διακοπή;
θήκη 0x31:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Δεν υπάρχουν μέσα στη μονάδα δίσκου (επεκτάσεις IBM/MS INT 13H) ");
διακοπή;
θήκη 0x32:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένος τύπος μονάδας δίσκου αποθηκευμένος στο CMOS (Compaq) ");
διακοπή;
θήκη 0x40:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Η λειτουργία αναζήτησης απέτυχε ");
διακοπή;
θήκη 0x80:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το συνημμένο απέτυχε να ανταποκριθεί (Λήξη χρόνου δίσκου) ");
διακοπή;
θήκη 0xB0:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν είναι κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB1:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB2:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν αφαιρείται (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB3:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Τόμος σε χρήση (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB4:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση του αριθμού κλειδώματος (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB5:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το έγκυρο αίτημα εξαγωγής απέτυχε (επεκτάσεις INT 13H) ");
διακοπή;
προεπιλογή: cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: ΑΓΝΩΣΤΟΣ ΚΩΔΙΚΟΣ Κατάστασης για σφάλματα δισκέτας ");
}
}
επιστροφή 0;
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Εφόσον θέλουμε να διαβάσουμε τον πρώτο τομέα του δίσκου, η θέση του τομέα θα είναι η εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
Υποδεικνύει τη μονάδα δίσκου 0 που είναι μονάδα δισκέτας ( a: ) |
dinfo.head = 0 |
Δείχνει στον αριθμό κεφαλής 0 |
dinfo.track = 0 |
Δείχνει στο κομμάτι 0 |
dinfo.sector = 1 |
Πρώτος τομέας της δισκέτας που είναι ο τομέας 1 |
dinfo.sector = 1 |
Αριθμός τομέων που πρέπει να ληφθούν υπόψη για λειτουργία ανάγνωσης = 1 |
dinfo.buffer = dbuf |
Προσωρινή μνήμη δεδομένων για τη λειτουργία |
- Ανοίξτε μια ροή αρχείου με όνομα αρχείου και διαδρομή που έχει δοθεί από τον χρήστη για να αποθηκεύσετε τις πληροφορίες εικόνας εκκίνησης ακριβών 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 (κενό)
{
struct diskinfo_t dinfo;
ένωση REGS regs;
int αποτέλεσμα?
int count=0, i;
char fname[80];
char dbuf[512];
ΑΡΧΕΙΟ *fp;
clrscr();
gotoxy(5,3);cprintf("Εισαγάγετε το όνομα και τη διαδρομή του αρχείου, στην οποία αποθηκεύεται η εικόνα εκκίνησης της δισκέτας");
gotoxy (5,5);
gets(fname);
fp=fopen(fname"rb");
if((fp=fopen(fname"rb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("Το αρχείο δεν ήταν δυνατό να ανοίξει");
getch();
exit(0);
}
gotoxy (10,9);
cprintf("Προσπάθεια ανάκτησης μονάδας δισκέτας :\n");
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
ενώ (count<512)
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = 0; /* αριθμός κεφαλής δίσκου */
dinfo.track = 0; /* αριθμός κομματιού */
dinfo.sector = 1; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
αποτέλεσμα = _bios_disk(_DISK_WRITE, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Successful!!! I Hope Floppy May
Εργασία τώρα.\n");
}
αλλού
{
gotoxy (10,14);
cprintf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση = 0x%02x\n", αποτέλεσμα);
gotoxy(10,16);
διακόπτης (αποτέλεσμα)
{
περίπτωση 0x00:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κανένα σφάλμα!! ");
διακοπή;
περίπτωση 0x01:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κακή εντολή ");
διακοπή;
περίπτωση 0x02:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το σημάδι διεύθυνσης δεν βρέθηκε ");
διακοπή;
περίπτωση 0x03:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εγγραφής σε δίσκο με προστασία εγγραφής ");
διακοπή;
περίπτωση 0x04:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τομέας δεν βρέθηκε ");
διακοπή;
περίπτωση 0x06:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο δίσκος άλλαξε από την τελευταία λειτουργία ");
διακοπή;
περίπτωση 0x08:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση άμεσης πρόσβασης στη μνήμη (DMA) ");
διακοπή;
περίπτωση 0x09:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εκτέλεσης DMA κατά μήκος ορίων 64K ");
διακοπή;
θήκη 0x0C:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τύπος μέσου δεν βρέθηκε ");
διακοπή;
θήκη 0x10:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένη ανάγνωση CRC/ECC στο δίσκο ");
διακοπή;
θήκη 0x20:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο ελεγκτής απέτυχε ");
διακοπή;
θήκη 0x31:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Δεν υπάρχουν μέσα στη μονάδα δίσκου (επεκτάσεις IBM/MS INT 13H) ");
διακοπή;
θήκη 0x32:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένος τύπος μονάδας δίσκου αποθηκευμένος στο CMOS (Compaq) ");
διακοπή;
θήκη 0x40:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Η λειτουργία αναζήτησης απέτυχε ");
διακοπή;
θήκη 0x80:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το συνημμένο απέτυχε να ανταποκριθεί (Λήξη χρόνου δίσκου) ");
διακοπή;
θήκη 0xB0:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν είναι κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB1:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB2:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν αφαιρείται (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB3:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Τόμος σε χρήση (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB4:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση του αριθμού κλειδώματος (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB5:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το έγκυρο αίτημα εξαγωγής απέτυχε (επεκτάσεις INT 13H) ");
διακοπή;
προεπιλογή: cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: ΑΓΝΩΣΤΟΣ ΚΩΔΙΚΟΣ Κατάστασης για σφάλματα δισκέτας ");
}
}
επιστροφή 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 |
Υποδεικνύει τη μονάδα δίσκου 0 που είναι μονάδα δισκέτας ( a: ) |
dinfo.head = 0 |
Δείχνει στον αριθμό κεφαλής 0 |
dinfo.track = 0 |
Δείχνει στο κομμάτι 0 |
dinfo.sector = 1 |
Πρώτος τομέας της δισκέτας που είναι ο τομέας 1 |
dinfo.sector = 1 |
Αριθμός τομέων που πρέπει να ληφθούν υπόψη για τη λειτουργία εγγραφής = 1 |
dinfo.buffer = dbuf |
Προσωρινή μνήμη δεδομένων για τη λειτουργία |
Ας το κάνουμε με ένα μόνο πρόγραμμα
Ελπίζω, τώρα να καταλάβατε την έννοια πίσω από τέτοιου είδους ανάκτηση δεδομένων από τη δισκέτα . Μετά από αυτό, ας φανταστούμε ένα ενιαίο πρόγραμμα που δίνει τα ίδια αποτελέσματα που πήραμε με τη βοήθεια δύο προγραμμάτων που συζητήθηκαν προηγουμένως.
Κάναμε τις ακόλουθες εργασίες με τα προγράμματα που συζητήθηκαν πρόσφατα:
- Αποθηκεύστε τις πληροφορίες εκκίνησης από μια καλή δισκέτα σε ένα αρχείο
- Επικολλήστε αυτές τις πληροφορίες στον πρώτο τομέα της τρέχουσας δυσανάγνωστης δισκέτας Το αρχείο που χρησιμοποιούσαμε για την αποθήκευση της εικόνας εκκίνησης λειτουργούσε ως ενδιάμεση γέφυρα για τη σύνδεση των λειτουργιών και των δύο προγραμμάτων. Αλλά αν ορίσουμε αυτές τις πληροφορίες εκκίνησης στην ίδια την κωδικοποίηση του προγράμματός μας, δεν χρειάζεται να δημιουργήσουμε ένα αρχείο όπως επίσης δεν χρειάζεται να διαβάσουμε τις πληροφορίες εκκίνησης της δισκέτας από το αρχείο.
Στο επόμενο πρόγραμμά μας λέμε στο πρόγραμμά μας τι πρέπει να γράψει στον πρώτο τομέα της δυσανάγνωστης δισκέτας και έτσι μπορούμε να αποφύγουμε δύο διαφορετικά προγράμματα να κάνουν την ίδια εργασία και μπορούμε να ανακτήσουμε τα δεδομένα μας με τον ίδιο τρόπο όπως πριν από το νέο μεμονωμένο πρόγραμμα.
Το πρόγραμμα γίνεται έτσι απλό με λιγότερη κωδικοποίηση και μπορούμε να μειώσουμε την πιθανότητα εμφάνισης σφαλμάτων ανάγνωσης, εγγραφής ή δημιουργίας αρχείων . Κάνουμε τις ακόλουθες τέσσερις σημαντικές εργασίες σε αυτό το πρόγραμμα:
Μην νομίζετε ότι το πρόγραμμα είναι δύσκολο να γραφτεί και να κατανοηθεί βλέποντας τις δεκαεξαδικές πληροφορίες 512 byte του dbuf[512]. Αργότερα, θα συζητήσουμε τον εύκολο τρόπο εγγραφής αυτών των πληροφοριών για την κωδικοποίηση του προγράμματός σας.
- Καθορίστε τις πληροφορίες εγγραφής εκκίνησης DOS σε δεκαεξαδικό σύστημα που θα εγγραφούν στον πρώτο τομέα της τρέχουσας μη αναγνώσιμης δισκέτας.
- Επαναφέρετε το σύστημα του δίσκου για να προετοιμάσει τη δισκέτα (INT 13H, Function 00H).
- Γράψτε την εγγραφή εκκίνησης του DOS στον πρώτο τομέα της δισκέτας
- Ελέγξτε για την επιτυχή ολοκλήρωση της λειτουργίας και σφάλμα, εάν προέκυψε.
Ας εξετάσουμε το πρόγραμμα:
/* Ένα πρόγραμμα για τη φόρτωση της προεπιλεγμένης εικόνας εκκίνησης σε μη αναγνώσιμη δισκέτα */
#include <bios.h>
#include <stdio.h>
int main (κενό)
{
struct diskinfo_t dinfo;
συνδικαλιστικοί κανόνες REGS:
int αποτέλεσμα, i;
/* Εικόνα εκκίνησης που θα φορτωθεί στη μονάδα δισκέτας */
στατικό 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; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = 0; /* αριθμός κεφαλής δίσκου */
dinfo.track = 0; /* αριθμός κομματιού */
dinfo.sector = 1; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
gotoxy (10,9);
cprintf("Προσπάθεια ανάγνωσης από μονάδα δισκέτας :\n");
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
αποτέλεσμα = _bios_disk(_DISK_WRITE, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
gotoxy (10,14);
cprintf("Κατάσταση εγγραφής δίσκου :επιτυχής.\n");
}
αλλού
{
gotoxy (10,14);
cprintf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση = 0x%02x\n",
αποτέλεσμα);
gotoxy(10,16);
διακόπτης (αποτέλεσμα)
{
περίπτωση 0x00:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κανένα σφάλμα!! ");
διακοπή;
περίπτωση 0x01:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Κακή εντολή ");
διακοπή;
περίπτωση 0x02:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το σημάδι διεύθυνσης δεν βρέθηκε ");
διακοπή;
περίπτωση 0x03:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εγγραφής για εγγραφή-
προστατευμένος δίσκος ");
διακοπή;
περίπτωση 0x04:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τομέας δεν βρέθηκε ");
διακοπή;
περίπτωση 0x06:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο δίσκος άλλαξε από την τελευταία λειτουργία ");
διακοπή;
περίπτωση 0x08:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση άμεσης πρόσβασης στη μνήμη (DMA) ");
διακοπή;
περίπτωση 0x09:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Προσπάθεια εκτέλεσης DMA κατά μήκος ορίων 64K ");
διακοπή;
θήκη 0x0C:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τύπος μέσου δεν βρέθηκε ");
διακοπή;
θήκη 0x10:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένη ανάγνωση CRC/ECC στο δίσκο ");
διακοπή;
θήκη 0x20:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο ελεγκτής απέτυχε ");
διακοπή;
θήκη 0x31:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Δεν υπάρχουν μέσα στη μονάδα δίσκου (επεκτάσεις IBM/MS INT 13H) ");
διακοπή;
θήκη 0x32:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Εσφαλμένος τύπος μονάδας δίσκου αποθηκευμένος στο CMOS (Compaq) ");
διακοπή;
θήκη 0x40:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Η λειτουργία αναζήτησης απέτυχε ");
διακοπή;
θήκη 0x80:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το συνημμένο απέτυχε να ανταποκριθεί (Λήξη χρόνου δίσκου) ");
διακοπή;
θήκη 0xB0:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν είναι κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB1:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος κλειδωμένος στη μονάδα δίσκου (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB2:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Ο τόμος δεν αφαιρείται (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB3:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Τόμος σε χρήση (INT 13 επεκτάσεις) ");
διακοπή;
θήκη 0xB4:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Υπέρβαση του αριθμού κλειδώματος (επεκτάσεις INT 13H) ");
διακοπή;
θήκη 0xB5:
cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: Το έγκυρο αίτημα εξαγωγής απέτυχε (επεκτάσεις INT 13H) ");
διακοπή;
προεπιλογή: cprintf("\n\n ΚΑΤΑΣΤΑΣΗ: ΑΓΝΩΣΤΟΣ ΚΩΔΙΚΟΣ Κατάστασης για σφάλματα δισκέτας ");
}
}
επιστροφή 0;
}
Σε αυτήν την κωδικοποίηση προγράμματος, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Η προσωρινή μνήμη στατικών χαρακτήρων dbuf[512] παρέχει την πληροφορία των 512 byte σε δεκαεξαδικό σύστημα, η οποία πρόκειται να γραφτεί στον πρώτο τομέα της μη αναγνώσιμης δισκέτας. Το dbuf[512] λέει στον υπολογιστή κατά τη διάρκεια της λειτουργίας ότι ποιες πληροφορίες πρέπει να γραφτούν στον πρώτο τομέα της δισκέτας. (Δείτε το Επόμενο Πρόγραμμα)
- Το dinfo δείχνει στη δομή diskinfo_t που περιέχει τις πληροφορίες των παραμέτρων που απαιτούνται από τη λειτουργία που εκτελείται από τη συνάρτηση _bios_disk.
- Καθώς πρόκειται να γράψουμε τις πληροφορίες στον πρώτο τομέα του δίσκου, επομένως η θέση του τομέα θα είναι η εξής:
Παράμετρος |
Τι σημαίνει |
dinfo.drive = 0x00 |
Υποδεικνύει τη μονάδα δίσκου 0 που είναι μονάδα δισκέτας ( a: ) |
dinfo.head = 0 |
Δείχνει στον αριθμό κεφαλής 0 |
dinfo.track = 0 |
Δείχνει στο κομμάτι 0 |
dinfo.sector = 1 |
Πρώτος τομέας της δισκέτας που είναι ο τομέας 1 |
dinfo.sector = 1 |
Αριθμός τομέων που πρέπει να ληφθούν υπόψη για τη λειτουργία εγγραφής = 1 |
dinfo.buffer = dbuf |
Προσωρινή μνήμη δεδομένων για τη λειτουργία |
- Εκκινήστε το σύστημα δίσκου χρησιμοποιώντας τη διακοπή 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 Boot Record της δισκέτας με μη αυτόματο τρόπο σε δεκαεξαδικό σύστημα χωρίς κανένα σφάλμα στο πρόγραμμα που συζητήσαμε πρόσφατα. Εάν μπορούμε να το γράψουμε με ακρίβεια, τότε θα είναι δύσκολο και χρονοβόρο να το κάνουμε. Ας χρησιμοποιήσουμε λίγο δύσκολο μυαλό για να αποθηκεύσουμε τα δεδομένα για την προσωρινή μνήμη δεδομένων dbuf[512] σε ένα αρχείο.
Γνωρίζουμε ότι στον προγραμματισμό C οι δεκαεξαδικοί χαρακτήρες αντιπροσωπεύονται με 0x έτσι ώστε εάν ο δεκαεξαδικός χαρακτήρας είναι A9 H, θα το γράψουμε στο πρόγραμμά μας C ως 0xA9. Το επόμενο πρόγραμμα μας κάνει το ίδιο. Θα αποθηκεύσει τα δεδομένα που πρέπει να γράψουμε στο προηγούμενο πρόγραμμά μας, ως δεδομένα του buffer δεδομένων dbuf[512].
Αυτό που πρέπει να κάνετε είναι απλώς να πάρετε μια νέα και νέα δισκέτα για να δημιουργήσετε την εικόνα του DBR και να αντιγράψετε την έξοδο αυτού του προγράμματος από το καθορισμένο αρχείο προορισμού και να επικολλήσετε αυτά τα δεδομένα στο πρόγραμμά σας. Κάντε κάποια μορφοποίηση εάν απαιτείται. Ας δούμε πώς λειτουργεί:
/* Πρόγραμμα για τη δημιουργία της εικόνας εκκίνησης της δισκέτας σε HEX χαρακτήρα */
#include <bios.h>
#include <stdio.h>
int main (κενό)
{
struct diskinfo_t dinfo;
ένωση REGS regs;
int αποτέλεσμα,i;
int count=0;
char fname[80];
στατικό char dbuf[512];
ΑΡΧΕΙΟ *fp;
dinfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = 0; /* αριθμός κεφαλής δίσκου */
dinfo.track = 0; /* αριθμός κομματιού */
dinfo.sector = 1; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
clrscr();
gotoxy(10,3);cprintf("Εισαγάγετε το όνομα αρχείου και τη διαδρομή προς
Αποθηκεύστε την εικόνα εκκίνησης στο σύστημα HEX");
gotoxy (5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("Δεν ήταν δυνατή η δημιουργία αρχείου");
getch();
exit(0);
}
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
gotoxy (10,9); cprintf("Προσπάθεια ανάγνωσης από τη δισκέτα
μονάδα δίσκου :\n");
αποτέλεσμα = _bios_disk(_DISK_READ, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
gotoxy (10,14);
cprintf("Ανάγνωση δίσκου από μονάδα δισκέτας:
επιτυχής.\n");
ενώ (count<512)
{
fprintf(fp,"0x%X, ",dbuf[count] & 0xff );
count++;
}
fclose(fp);
}
αλλού
{
gotoxy (10,14);
cprintf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση = 0x%02x\n",
αποτέλεσμα);
}
επιστροφή 0;
}
Σχόλια για την κωδικοποίηση του προγράμματος:
Έτσι τα δεδομένα αποθηκεύονται στο καθορισμένο αρχείο. Απλώς αντιγράψτε τα δεδομένα στο πρόγραμμά σας και κάντε κάποια απαιτούμενη μορφοποίηση. Δεν πρέπει ποτέ να ξεχνάτε τις παρακάτω συμβουλές κατά τη διάρκεια της διαδικασίας:
- Βεβαιωθείτε ότι η λειτουργία του προγράμματος ήταν επιτυχής και ότι τα δεδομένα που έχουν αποθηκευτεί στο αρχείο προορισμού είναι τα κατάλληλα.
- Θα πρέπει να ελέγξετε τη λειτουργία για την εμφάνιση αναμενόμενων σφαλμάτων.
- Πρέπει να αρχικοποιήσετε τη δισκέτα με το πρόγραμμα πριν διαβάσετε τον τομέα εκκίνησης. Μπορείτε να χρησιμοποιήσετε τη λειτουργία 00H του INT 13H για αυτό το σκοπό.
Μέθοδος - 2
Τι να κάνετε εάν η Μέθοδος – 1 δεν λειτουργεί;
Εάν η Μέθοδος – 1 δεν λειτουργεί και ο μη αναγνώσιμος δίσκος δεν επιτρέπει στο πρόγραμμα να ξαναγράψει τις πληροφορίες εκκίνησης στον πρώτο του τομέα, θα πρέπει να δοκιμάσετε αυτήν τη δεύτερη μέθοδο. Ο λόγος πίσω από την αποτυχία της First Method μπορεί να είναι η φυσική καταστροφή του πρώτου τομέα της δισκέτας.
Σε αυτή τη δεύτερη μέθοδο θα αντιγράψουμε προσωρινά όλα τα δεδομένα της επιφάνειας της μη αναγνώσιμης δισκέτας σε ένα μόνο αρχείο και στη συνέχεια θα επικολλήσουμε αυτήν την εικόνα απευθείας στην επιφάνεια ενός άλλου καλού δίσκου.
Η διαδικασία περιλαμβάνει τα ακόλουθα δύο σημαντικά βήματα:
- Τομέας ανά τομέα Αντιγράψτε προσωρινά όλα τα δεδομένα της επιφάνειας του μέσου της δισκέτας σε ένα μόνο αρχείο.
- Επικολλήστε τα δεδομένα που είχαν αποθηκευτεί προηγουμένως στο αρχείο, σε μια νέα νέα δισκέτα ως έχει, στους ίδιους τομείς.
Αντιγράψτε όλα τα δεδομένα της επιφάνειας πολυμέσων σε ένα μόνο αρχείο
Για να αποθηκεύσει όλα τα δεδομένα της επιφάνειας του μέσου της δισκέτας, το πρόγραμμα πρέπει να κάνει τις ακόλουθες τρεις εργασίες:
- Αρχικοποιήστε σωστά το δίσκο με τη βοήθεια της συνάρτησης 00H του INT 13H.
- Διαβάστε τις πληροφορίες ανά τομέα της επιφάνειας και αποθηκεύστε τις σε ένα μόνο αρχείο.
- Ελέγξτε για επιτυχή λειτουργία ανάγνωσης (το πιο σημαντικό)
Είναι πολύ συνηθισμένο να έχετε οποιοδήποτε πρόβλημα προετοιμασίας με μια δισκέτα που οδηγεί πολλά μηνύματα ανάγνωσης που δεν έχουν επιτυχία. Αυτός είναι ο λόγος για τον οποίο ο δίσκος πρέπει να προετοιμαστεί πριν από τη λειτουργία ανάγνωσης εγγραφής με τη βοήθεια προγραμματισμού.
Είναι το πιο σημαντικό και απαραίτητο βήμα σε περίπτωση οποιουδήποτε τύπου λειτουργιών που εφαρμόζονται σε δισκέτα να ελέγξετε εάν η λειτουργία ήταν επιτυχής ή όχι.
Εάν, ακόμη και μετά την προετοιμασία, η πρόσφατα τοποθετημένη δισκέτα ή η αλλαγμένη δισκέτα προκαλέσει οποιοδήποτε σφάλμα ανάγνωσης, συνιστάται να εκτελέσετε ξανά το πρόγραμμα, πιθανότατα αυτή τη φορά μπορεί να λειτουργήσει.
Το παρακάτω πρόγραμμα είναι για να εκτελέσει αυτές τις καθορισμένες εργασίες. Ας δούμε πώς θα προχωρήσει:
/* Πρόγραμμα για την αποθήκευση των δεδομένων της φυσικής επιφάνειας της δισκέτας σε ένα αρχείο */
#include <bios.h>
#include <stdio.h>
κενό κύριο (κενό)
{
int head,track?
ένωση REGS regs;
int αποτέλεσμα,i,τομέας;
όνομα αρχείου char[80];
struct diskinfo_t dinfo;
στατικό char dbuf[512];
ΑΡΧΕΙΟ *tt;
clrscr();
printf("\n Εισαγάγετε το όνομα του αρχείου με τη διαδρομή για να αποθηκεύσετε το
Δεδομένα προσωρινά\n");
gets(όνομα αρχείου);
if((tt=fopen(όνομα αρχείου,"wb"))==NULL)
{
printf("Δεν ήταν δυνατή η δημιουργία του αρχείου,
Πατήστε οποιοδήποτε πλήκτρο για EXIT");
getch();
exit(0);
}
printf("\n Αρχικοποίηση συστήματος δισκέτας...\n");
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
για(τομέας=1;τομέας<=18;τομέας++)
{
dinfo.drive = 0; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = κεφάλι; /* αριθμός κεφαλής δίσκου */
dinfo.track = κομμάτι; /* αριθμός κομματιού */
dinfo.sector = τομέας; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
αποτέλεσμα = _bios_disk(_DISK_READ, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c", dbuf[i] & 0xff);
}
αλλού
{
printf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση =
0x%02x\t%d\t%d\t%d\n", αποτέλεσμα, κεφάλι, πίστα, τομέας);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
πίστα, κεφάλι, τομέας).
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το όνομα αρχείου του πίνακα χαρακτήρων[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 |
Υποδεικνύει τη μονάδα δίσκου 0 που είναι μονάδα δισκέτας ( a: ) |
dinfo.κεφάλι = κεφάλι |
Δείχνει στον αριθμό κεφαλής 0 και 1 καθώς η δισκέτα έχει δύο πλευρές (δύο κεφαλές) |
dinfo.track = πίστα |
Δείχνει στο κομμάτι 0 έως 79 καθώς υπάρχουν 80 κομμάτια σε κάθε πλευρά της δισκέτας. |
dinfo.τομέας = τομέας |
Δείχνει τον τομέα 1 έως 18 καθώς υπάρχουν 18 τομείς σε κάθε κομμάτι. |
dinfo.sector = 1 |
Αριθμός τομέων που πρέπει να ληφθούν υπόψη για λειτουργία ανάγνωσης = 1 |
dinfo.buffer = dbuf |
Προσωρινή μνήμη δεδομένων για τη λειτουργία |
- Το _bios_disk(_DISK_READ, &dinfo) διαβάζει τα δεδομένα από τη φυσική επιφάνεια της δισκέτας από τον τομέα που καθορίζεται από το dinfo.
- Η κατάσταση που επιστρέφεται αποθηκεύεται ως αποτέλεσμα που χρησιμοποιείται για την εμφάνιση του μηνύματος για επιτυχή λειτουργία ή για την εμφάνιση μηνύματος σφάλματος στην οθόνη εάν παρουσιαστεί κάποιο σφάλμα.
Να θυμάστε πάντα ότι το μέγεθος του αρχείου που περιέχει την εικόνα των δεδομένων της δισκέτας πρέπει να είναι ακριβώς 1.474.560 byte, επειδή η δισκέτα έχει 80 κομμάτια (0 έως 79), 2 πλευρές ή κεφαλές (κεφαλίδα 0 και κεφαλή 1), κάθε κομμάτι έχει 18 τομείς σε αυτό και κάθε τομέας περιέχει 512 bytes δεδομένων.
Σύνολο 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>
κενό κύριο (κενό)
{
int head,track?
ένωση REGS regs;
int αποτέλεσμα,i,τομέας;
όνομα αρχείου char[80];
struct diskinfo_t dinfo;
στατικό char dbuf[512];
/* Πληροφορίες 512 Byte για την κάλυψη του χώρου του Bad Sector */
/// Χρησιμοποίησα 512 μηδενικά για να γεμίσω το χώρο των 512 byte \\\
στατικό char dbuf2[512] =
"00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000";
ΑΡΧΕΙΟ *tt;
clrscr();
printf("\n Εισαγάγετε το όνομα του αρχείου με τη διαδρομή για να αποθηκεύσετε το
Δεδομένα προσωρινά\n");
gets(όνομα αρχείου);
if((tt=fopen(όνομα αρχείου,"wb"))==NULL)
{
printf("Δεν ήταν δυνατή η δημιουργία του αρχείου, πατήστε οποιοδήποτε πλήκτρο To
ΕΞΟΔΟΣ");
getch();
exit(0);
}
printf("\n Αρχικοποίηση συστήματος δισκέτας...\n");
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
για(τομέας=1;τομέας<=18;τομέας++)
{
dinfo.drive = 0; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = κεφάλι; /* αριθμός κεφαλής δίσκου */
dinfo.track = κομμάτι; /* αριθμός κομματιού */
dinfo.sector = τομέας; /* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
αποτέλεσμα = _bios_disk(_DISK_READ, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c", dbuf[i] & 0xff);
}
αλλού
{
printf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση =
0x%02x\t%d\t%d\t%d\n", αποτέλεσμα, κεφάλι, κομμάτι, τομέας);
/* Εάν ο τομέας δεν είναι αναγνώσιμος, καταλάβετε 512 byte κατά dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
πίστα, κεφάλι, τομέας).
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση του προγράμματος, κάθε βήμα είναι το ίδιο όπως στο προηγούμενο πρόγραμμα, εκτός από το buffer δεδομένων dbuf2[512], το οποίο χρησιμοποιούμε για να χειριστούμε το σφάλμα που δημιουργείται από τον κακό τομέα κατά τη λειτουργία ανάγνωσης δίσκου και να διατηρήσουμε το μέγεθος του αρχείου εικόνας.
Κάνοντας αυτό, γεμίζουμε το χώρο των πληροφοριών, που δεν καταφέραμε να διαβάσουμε από τον κακό τομέα και τώρα γράφουμε τις ψευδοπληροφορίες των 512 byte, ώστε να διατηρήσουμε την ακρίβεια της εικόνας του δίσκου.
Επικολλήστε τα δεδομένα από το αρχείο στη φυσική επιφάνεια της νέας δισκέτας:
Σε αυτό το βήμα, επικολλάμε τα δεδομένα που είναι αποθηκευμένα στο αρχείο από το προηγούμενο πρόγραμμα, στη φυσική επιφάνεια της φρέσκιας δισκέτας, τομέα προς τομέα με τον ίδιο τρόπο που τα αντιγράψαμε στο αρχείο.
Το πρόγραμμα προχωρά με τα ακόλουθα βασικά βήματα:
- Ανοίξτε προσωρινά το αρχείο στο οποίο αποθηκεύσαμε τα δεδομένα επιφάνειας της δυσανάγνωστης δισκέτας.
- Εκκινήστε σωστά το σύστημα δίσκου με τη λειτουργία επαναφοράς 00H του INT 13H.
- Γράψτε τις πληροφορίες για τους τομείς της νέας δισκέτας από το αρχείο.
- Εμφανίστε την κατάσταση εγγραφής ταυτόχρονα για να βρείτε ή να αποφύγετε την εμφάνιση σφαλμάτων.
Ο πηγαίος κώδικας του προγράμματος έχει δοθεί παρακάτω. Ας εξετάσουμε πώς λειτουργεί:
/* Πρόγραμμα εγγραφής των δεδομένων στους τομείς της επιφάνειας της φρέσκιας δισκέτας από το αρχείο, που δημιουργήθηκε από το προηγούμενο πρόγραμμα */
#include <bios.h>
#include <stdio.h>
κενό κύριο (κενό)
{
int head,track?
ένωση REGS regs;
int αποτέλεσμα,i,τομέας;
int count =0;
όνομα αρχείου char[80];
struct diskinfo_t dinfo;
στατικό char dbuf[512];
ΑΡΧΕΙΟ *fp;
clrscr();
printf("\n Εισαγάγετε το όνομα του αρχείου με τη διαδρομή για να αποθηκεύσετε το
Δεδομένα προσωρινά\n");
gets(όνομα αρχείου);
if((fp=fopen(όνομα αρχείου"rb"))==NULL)
{
printf("Δεν ήταν δυνατή η δημιουργία του αρχείου, πατήστε οποιοδήποτε πλήκτρο To
ΕΞΟΔΟΣ");
getch();
exit(1);
}
/// Εκκίνηση του συστήματος δίσκου \\\
for(i=0; i<3; i++)
{
reg.h.ah = 0x00; /* Επαναφορά συστήματος δίσκου */
reg.h.dl = 0x00; /* Δισκέτα α: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
για(τομέας=1;τομέας<=18;τομέας++)
{
καταμέτρηση =0;
ενώ (count<512 )
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = κεφάλι; /* αριθμός κεφαλής δίσκου */
dinfo.track = κομμάτι; /* αριθμός κομματιού */
dinfo.sector = τομέας;/* αριθμός τομέα */
dinfo.nsectors = 1; /* καταμέτρηση τομέα */
dinfo.buffer = dbuf; /* buffer δεδομένων */
αποτέλεσμα= _bios_disk(_DISK_WRITE, &dinfo);
αν ((αποτέλεσμα & 0xff00) == 0)
printf("Επιτυχής εγγραφή στο κομμάτι = %d, Head = %d,
Τομέας = %d.\n", κομμάτι, κεφαλή, τομέας);
αλλού
printf("Δεν είναι δυνατή η ανάγνωση της μονάδας δίσκου A, κατάσταση = 0x%02x\n",
αποτέλεσμα);
}
}
}
}
Σχόλια σχετικά με την κωδικοποίηση προγράμματος:
Στην κωδικοποίηση προγράμματος που δόθηκε προηγουμένως, βασικά προχωράμε στην εκτέλεση των παρακάτω εργασιών βήμα προς βήμα:
- Το όνομα αρχείου του πίνακα χαρακτήρων[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 |
Υποδεικνύει τη μονάδα δίσκου 0 που είναι μονάδα δισκέτας ( a: ) |
dinfo.κεφάλι = κεφάλι |
Δείχνει στον αριθμό κεφαλής 0 και 1 καθώς η δισκέτα έχει δύο πλευρές (δύο κεφαλές) |
dinfo.track = πίστα |
Δείχνει στο κομμάτι 0 έως 79 καθώς υπάρχουν 80 κομμάτια σε κάθε πλευρά της δισκέτας. |
dinfo.τομέας = τομέας |
Δείχνει τον τομέα 1 έως 18 καθώς υπάρχουν 18 τομείς σε κάθε κομμάτι. |
dinfo.sector = 1 |
Αριθμός τομέων που πρέπει να ληφθούν υπόψη για τη λειτουργία εγγραφής = 1 |
dinfo.buffer = dbuf |
Προσωρινή μνήμη δεδομένων για τη λειτουργία |
- Το _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 Byte |
Όνομα αρχείου |
3 Byte |
Επέκταση |
1 Byte |
Ιδιότης |
10 Byte |
Ρεζερβέ |
2 Byte |
Ώρα, Δημιουργία ή Τελευταία Ενημέρωση |
2 Byte |
Ημερομηνία, Δημιουργία ή Τελευταία Ενημέρωση |
2 Byte |
Συστάδα εκκίνησης |
4 Byte |
Μέγεθος αρχείου |
Ανακτούμε τα δεδομένα διαβάζοντας τις πληροφορίες των αρχείων από το Root Directory και στη συνέχεια ενσωματώνουμε το αρχείο στη διαδρομή προορισμού και ανακτούμε το αρχείο. Το επόμενο πρόγραμμά μας εκτελεί τα ακόλουθα βήματα για την ανάκτηση των δεδομένων:
- Διαβάστε τις καταχωρήσεις του καταλόγου ρίζας και εμφανίστε τις στην οθόνη με όλες τις πληροφορίες, όπως όνομα αρχείου/καταλόγου, επέκταση του αρχείου, μέγεθος συμπλέγματος έναρξης των αρχείων σε Byte.
- Διαβάστε τις πληροφορίες Αρχείων και Καταλόγων στους Υποκαταλόγους και εμφανίστε τους εάν απαιτείται.
- Επιβεβαιώστε το όνομα αρχείου που θέλετε να ανακτήσετε και συνεχίστε την ανάκτηση.
- Υπολογίστε τις πληροφορίες CHS (Κύλινδρος, Κεφαλή και Τομέας) για το Καθορισμένο αρχείο προς ανάκτηση.
- Ενσωματώστε τα δεδομένα του αρχείου από την περιοχή δεδομένων του δίσκου και αποθηκεύστε το ανακτημένο αρχείο στο καθορισμένο όνομα αρχείου προορισμού στην καθορισμένη διαδρομή.
Αυτό το Πρόγραμμα δεν ενδιαφέρεται αν οι πληροφορίες εκκίνησης της δισκέτας είναι αναγνώσιμες ή όχι. Επομένως, μπορείτε να ανακτήσετε ακόμη και διαγραμμένα δεδομένα από την κατεστραμμένη δισκέτα . Ας δούμε την κωδικοποίηση του προγράμματος:
/* Πρόγραμμα για την ανάκτηση των δεδομένων από τη δισκέτα διαβάζοντας πληροφορίες αρχείου από τον κατάλογο ρίζας */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
ανυπόγραφο int)
ανυπόγραφο int track=0,head=1,sector=2;
Εμφάνιση_Πληροφοριών (κομμάτι, κεφαλή, τομέας);
} /*Τέλος κύριας */
void Display_Information(unsigned int track,
ανυπόγραφη κεφαλή,
ανυπόγραφος εσωτερικός τομέας)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // Buffer 512 Byte
char ch;
struct diskinfo_t finfo; //Structure, Χρησιμοποιείται από _bios_disk
ανυπόγραφο αποτέλεσμα int,i,j, count=0; /* Ανυπόγραφοι ακέραιοι αριθμοί
Καθορισμένο */
ανυπόγραφο int file_no; /* Ανυπόγραφος ακέραιος αριθμός
για τον αριθμό αρχείου */
struct
{
ανυπόγραφο όνομα int[8],ext[3]; /* Όνομα αρχείου για το DOS στην έκδοση 8.3
(Οκτώ κουκκίδες τρία) Μορφή */
ανυπόγραφο χαρακτηριστικό int. // Χαρακτηριστικό αρχείου/καταλόγου
ανυπόγραφη έναρξη int. // Εκκίνηση συμπλέγματος του αρχείου
μακρύ ανυπόγραφο μέγεθος int. // Μέγεθος αρχείου σε Byte
}root[32]; /* 32 Bytes Πληροφορίες του
Αρχείο/Κατάλογος σε Root
Κατάλογος */
clrscr();
κάνω
{
file_no=0;
finfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
finfo.head = κεφάλι; /* αριθμός κεφαλής δίσκου */
finfo.track = κομμάτι; /* αριθμός κομματιού */
finfo.sector= τομέας; /* αριθμός τομέα */
finfo.nsectors=1; /* καταμέτρηση τομέα */
finfo.buffer = buf; /* buffer δεδομένων */
αποτέλεσμα = _bios_disk(_DISK_READ, &finfo); /* Διαβάστε το
Τομέας */
if( (αποτέλεσμα & 0xff00) != 0) /* Εάν Σφάλμα ανάγνωσης, Εμφάνιση
Μήνυμα σφάλματος και έξοδος*/
{
printf("Σφάλμα ανάγνωσης");
getch();
exit(0); // Επιστροφή στο DOS
}
/// Μορφή οθόνης προβολής πληροφοριών \\\
clrscr();
gotoxy(9,1);
cprintf("DISPLAY CYLN: %u, HEAD: %u, SECTOR: %u",
πίστα, κεφάλι, τομέας).
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[αρχείο_όχι].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Ιδιότητα
/// Έναρξη συμπλέγματος \\\
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))
συνεχίζω;
αλλού
{
gotoxy(8,i/32+4);
cprintf("%2u",αρχείο_no); /* Εμφάνιση αρχείου
Αριθμός */
for(j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Εμφάνιση αρχείου
Όνομα */
}
for(j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Εμφάνιση
Επέκταση */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Εμφάνιση
Ιδιότητα */
if(root[file_no].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Εμφάνιση εάν Χαρακτηριστικό καταλόγου */
}
αλλού
{
gotoxy(33,i/32+4);
cprintf("<ΑΡΧΕΙΟ>"); /* Η καταχώριση είναι αρχείου */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Εμφάνιση
Αρχικό σύμπλεγμα */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* μέγεθος του
Αρχείο */
}
file_no++;
}
gotoxy(10,
cprintf("Πατήστε 'M' : Για να δείτε τη λίστα με περισσότερα αρχεία &quo
gotoxy(10,
cprintf("Πατήστε 'R' :Για να ανακτήσετε ένα αρχείο από τα παραπάνω
λίστα&quo
ch=getc
Θυμηθείτε ότι το όνομα αρχείου που ξεκινά με s (E5H) αντιπροσωπεύει ότι το αρχείο έχει διαγραφεί και επομένως ο πρώτος χαρακτήρας του ονόματος αρχείου έχει αντικατασταθεί με s (Δείτε την περιγραφή του ριζικού καταλόγου στα προηγούμενα κεφάλαια ).
Και η έξοδος του προγράμματος εμφανίζεται ως εξής:
ΚΥΛΛΟΣ ΕΜΦΑΝΙΣΗΣ: 0, ΚΕΦΑΛΗ: 1, ΤΟΜΕΑΣ: 2
FNO ΟΝΟΜΑ ΕΞΩΤΕΡΙΚΟ ΧΑΡΑΚΤΗΡΙΣΤΙΚΟ ΜΕΓΕΘΟΣ
ΕΝΑΡΞΗΣ ------------------------------------------------------------------
WE 32 <ΑΡΧΕΙΟ> 15 1800
1 s2_INFO C 32 <ΑΡΧΕΙΟ> 5 4700
2 THELP CFG 32 <ΑΡΧΕΙΟ> 2 22
3 THELP COM 32 <ΑΡΧΕΙΟ> 3 11072
4 TIMEIT CPP 32
<ΑΡΧΕΙΟ> 39 1186 5 TOUCH COM
12PP 4 3 32 <ΑΡΧΕΙΟ> 53 1581
7 TURBOC CFG 32 <ΑΡΧΕΙΟ> 57 30
8 AA CPP 32 <
ΑΡΧΕΙΟ> 58 260 9 ABC
CPP 32 <ΑΡΧΕΙΟ> 59 1036
10 ASSIGN1 CPP 32 <12CH24 6 <ΑΡΧΕΙΟ> 71 834
12 sBSDISK1 C 32 <ΑΡΧΕΙΟ> 73 911
13 sH24_25 C 32 <ΑΡΧΕΙΟ> 75 594
14 sBSDISK C 32 <ΑΡΧΕΙΟ> 77 840
Πατήστε 'M' : Για να δείτε τη λίστα περισσότερων αρχείων
Πατήστε 'R' :Για να ανακτήσετε ένα αρχείο από την παραπάνω λίστα R
|
ΚΥΛΛΟΣ ΕΜΦΑΝΙΣΗΣ: 0, ΚΕΦΑΛΗ: 1, ΤΟΜΕΑΣ: 2
FNO ΟΝΟΜΑ ΕΞΩΤΕΡΙΚΟ ΧΑΡΑΚΤΗΡΙΣΤΙΚΟ ΜΕΓΕΘΟΣ ΕΝΑΡΞΗΣ
---------------------------------------------------------------
0 WE 32 <ΑΡΧΕΙΟ> 15 1800
1 s2_INFO C 32 <ΑΡΧΕΙΟ> 5 4700
2 THELP CFG 32 <ΑΡΧΕΙΟ> 2 22
3 THELP COM 32 <ΑΡΧΕΙΟ> 3 11072
4 TIMEIT CPP 32
<ΑΡΧΕΙΟ> 39 1186 5 TOUCH COM
12PP 4 3 32 <ΑΡΧΕΙΟ> 53 1581
7 TURBOC CFG 32 <ΑΡΧΕΙΟ> 57 30
8 AA CPP 32 <
ΑΡΧΕΙΟ> 58 260 9 ABC
CPP 32 <ΑΡΧΕΙΟ> 59 1036
10 ASSIGN1 CPP 32 <12CH24 6 <ΑΡΧΕΙΟ> 71 834
12 sBSDISK1 C 32 <ΑΡΧΕΙΟ> 73 911
13 sH24_25 C 32 <ΑΡΧΕΙΟ> 75 594
14 sBSDISK C 32 <ΑΡΧΕΙΟ> 77 840
Εισαγάγετε FNO. του αρχείου που θέλετε να ανακτήσετε 1
Θέλετε να ανακτήσετε _2_INFO .C
Cylinder = 1, Head = 0, Sector = 1 Integrating.........
Εισαγάγετε Path και Filename για να ανακτήσετε το αρχείο: c:\windows\desktop\H2_INFO.C
Η ανάκτηση ολοκληρώθηκε !!!
|
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση Display_Information είναι η ανάγνωση των πληροφοριών αρχείου και καταλόγου και από τον ριζικό κατάλογο. Στη Δομή διαβάζουμε τις πληροφορίες των 32 byte για κάθε αρχείο ή κατάλογο με root[32].
Το όνομα[8] και το ext[3] των μη υπογεγραμμένων ακέραιων πινάκων είναι για όνομα αρχείου ή καταλόγου για DOS σε μορφή 8.3 (Οκτώ κουκκίδες τρία). Ομοίως, ένα byte είναι για το χαρακτηριστικό και δύο byte για το αρχικό σύμπλεγμα. μακρύ ανυπόγραφο μέγεθος int. είναι να αποθηκεύσετε το μέγεθος του αρχείου των τεσσάρων byte.
Η συνάρτηση _bios_disk διαβάζει τον τομέα, που καθορίζεται από τη δομή finfo και η κατάσταση της λειτουργίας αποθηκεύεται ως αποτέλεσμα.
Από κάθε πληροφορία 512 byte που διαβάζει η συνάρτηση _bios_disk , μέχρι να τελειώσει η περιοχή του ριζικού καταλόγου , συλλέγουμε τις πληροφορίες των αρχείων και των καταλόγων που είναι αποθηκευμένα στο δίσκο και τα εμφανίζουμε στην οθόνη.
Ο ακέραιος file_no αποθηκεύει τον αριθμό του αρχείου ή του καταλόγου στη λίστα, ξεκινώντας από το 0. Γενικά το μέγεθος του ριζικού καταλόγου είναι 14 τομείς και ο ριζικός κατάλογος ξεκινά γενικά από Cylinder =0, Head = 0 και Sector =2 στην περίπτωση 1,44MB και 3½ δισκέτας.
Εάν ο χρήστης δώσει τον χαρακτήρα «M» ή «m» ως είσοδο, εμφανίζονται οι πληροφορίες του επόμενου τομέα εάν η επιλογή από τον χρήστη είναι «R» ή «r», καλούνται οι συναρτήσεις ανάκτησης. Η κωδικοποίηση της συνάρτησης recover() έχει δοθεί παρακάτω:
/* Λειτουργία εκκίνησης ανάκτησης για το καθορισμένο αρχείο */
void recover (unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Λειτουργία για εκκαθάριση σειράς στην οθόνη */
/* Λειτουργία για ενσωμάτωση του καθορισμένου αρχείου */
void integrate (μακρύ ανυπόγραφο int, unsigned int,
ανυπόγραφο int, unsigned int)
ανυπόγραφο int file_no,i;
char ch;
ανυπόγραφο int *loc;
ανυπόγραφο int κύλινδρος, κεφαλή, τομέας.
ανυπόγραφη έναρξη int.
μακρύ ανυπόγραφο μέγεθος int.
clear_the_line(21); /* Διαγραφή του αριθμού σειράς 21 */
clear_the_line(22); /* Διαγραφή του αριθμού σειράς 22 */
clear_the_line(23); /* Διαγραφή του αριθμού σειράς 23 */
clear_the_line(24); /* Διαγραφή του αριθμού σειράς 24 */
gotoxy (10,21);
cprintf("Εισαγάγετε το FNO. του αρχείου που θέλετε να ανακτήσετε");
scanf("%u",&file_no); /* Λάβετε τον αριθμό αρχείου για να είναι
Ανακτήθηκε */
loc=(root+(len*file_no/2));
/* Επιβεβαιώστε το όνομα αρχείου προς ανάκτηση */
gotoxy (10,22);
cprintf("Θέλετε να ανακτήσετε");
for(i=0;i<8;i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* Όνομα αρχείου */
}
gotoxy(38,22);
cprintf(".");
for(i=0;i<3;i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* Επέκταση αρχείου */
}
start=*(loc+12);
/// Λυπούμαστε, επιλέξατε έναν κατάλογο \\\
if(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Είναι ένας κατάλογος. Θέλετε να δείτε το
περιεχόμενα αυτού του καταλόγου Ν/Ο");
ch=getch();
if(ch==27)
κύριος();
if(ch=='y' || ch=='Y')
{
/* Υπολογισμός γεωμετρίας */
υπολογισμός(έναρξη,&κύλινδρος,&κεφαλή,&τομέας);
/* Εμφάνιση περιεχομένων καταλόγου */
Display_Information (κύλινδρος, κεφαλή, τομέας);
}
αλλού
/* Ζητήστε ξανά ένα αρχείο και συνεχίστε την ανάκτηση */
ανάκτηση (root,len);
}
αλλού
{
μέγεθος=*(loc+13);
/* Υπολογισμός για πληροφορίες CHS */
υπολογισμός(έναρξη,&κύλινδρος,&κεφαλή,&τομέας);
/* Ενσωμάτωση του αρχείου */
ενσωμάτωση (μέγεθος, κύλινδρος, κεφαλή, τομέας);
}
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση recover() είναι να λαμβάνει τα στοιχεία του χρήστη για να ξεκινήσει η ανάκτηση. Ο αριθμός αρχείου που δίνεται ως είσοδος από τον χρήστη για την ανάκτηση του αρχείου, αποθηκεύεται στο file_no.
Εάν ο αριθμός που εισάγατε είναι για την καταχώρηση Directory, η Display_Information() εμφανίζει τα περιεχόμενα αυτού του καταλόγου, διαφορετικά Το όνομα αρχείου και η επέκταση του αριθμού αρχείου file_no εμφανίζεται στην οθόνη για επιβεβαίωση του αρχείου προς ανάκτηση.
Για να ανακτήσετε το καθορισμένο αρχείο , οι συναρτήσειςcalculate() και integrate() καλούνται εντός της συνάρτησης. Η κωδικοποίηση της συνάρτησηςcalculate() έχει δοθεί παρακάτω:
/* Συνάρτηση Υπολογισμός της Γεωμετρίας CHS για την ανάκτηση */
void υπολογισμός(ανυπόγραφη int start,unsigned int *cylinder,
ανυπόγραφο int *κεφαλή, ανυπόγραφο int *τομέας)
{
ανυπόγραφο int temp?
*κύλινδρος=0;
*κεφαλή=1;
*τομέας=14;
if (έναρξη<5)
*τομέας=14+έναρξη;
αλλού
{
temp= (έναρξη-4)/18;
if (θερμοκρασία>0)
{
εάν(θερμοκρασία%2==0)
*κεφαλή=0;
αλλού
*κεφαλή=1;
*κύλινδρος+=1+θερμοκρασία/2;
}
αλλού
{
*κεφαλή=0;
*κύλινδρος=1;
}
*sector=(start-4)%18;
}
/// Εμφάνιση του CHS του αρχείου προς ανάκτηση \\\
gotoxy (10,23);
cprintf("Κύλινδρος = %u, Κεφαλή = %u, Τομέας = %u",
*κύλινδρος,*κεφαλή,*τομέας);
}
Σχόλια σχετικά με την κωδικοποίηση:
Η συνάρτηση υπολογισμός() είναι ο υπολογισμός των πληροφοριών κυλίνδρου, κεφαλής και τομέα για το αρχείο που πρόκειται να ανακτηθεί. Μετά τον υπολογισμό εμφανίζονται στην οθόνη οι αριθμοί κυλίνδρου, κεφαλής και τομέα.
Η κωδικοποίηση για τη συνάρτηση integrate() έχει δοθεί παρακάτω:
/* Ενσωμάτωση αρχείου και αποθήκευση του ανακτημένου αρχείου στην καθορισμένη διαδρομή και το όνομα αρχείου */
void integrate (μεγάλο ανυπόγραφο μέγεθος int,
ανυπόγραφος εσωτερικός κύλινδρος,
ανυπόγραφη κεφαλή,
ανυπόγραφος εσωτερικός τομέας)
{
void clear_the_line(unsigned int);
/* Λειτουργία επαλήθευσης του τομέα για σφάλματα */
int verify_the_sector(unsigned int, unsigned int,
ανυπόγραφο int)
int status?
char buf[512],*Filename_with_path;
struct diskinfo_t dinfo;
ανυπόγραφο αποτέλεσμα int.
ΑΡΧΕΙΟ *fp;
ανυπόγραφο int αριστερά,i;
ανυπόγραφο int sec.
/* Εισαγάγετε τη διαδρομή προορισμού και το όνομα αρχείου για να αποθηκεύσετε το ανακτημένο αρχείο */
gotoxy(2,24);
cprintf("Εισαγάγετε τη διαδρομή και το όνομα αρχείου για να ανακτήσετε το αρχείο: ");
flush(stdin);
gets(Filename_with_path);
fp=fopen(Όνομα_αρχείου_με_διαδρομή,"wb");
/* Εάν προέκυψε σφάλμα Εμφανίστε το μήνυμα λάθους και λάβετε ξανά τη διαδρομή και το όνομα αρχείου */
if(fp==NULL)
{
gotoxy (5,25);
cprintf("Σφάλμα στο άνοιγμα του αρχείου");
getch();
clear_the_line(24);
gotoxy (0,25);
cprintf(" ");
ενσωμάτωση (μέγεθος, κύλινδρος, κεφαλή, τομέας); /* Εισαγάγετε το
Προορισμός ξανά */
}
/* Εάν όλα είναι εντάξει, ενσωματώστε και γράψτε */
gotoxy (50,23);
cprintf("Integrating.........");
αριστερά= μέγεθος%512;
sec = μέγεθος/512;
sec++;
ενώ(δευτ.>0)
{
dinfo.drive = 0x00; /* αριθμός μονάδας δίσκου για A: */
dinfo.head = κεφάλι; /* αριθμός κεφαλής δίσκου */
dinfo.track = κύλινδρος; /* αριθμός κομματιού */
dinfo.sector= τομέας; /* αριθμός τομέα */
dinfo.nsectors=1; /* καταμέτρηση τομέα */
dinfo.buffer = buf; /* buffer δεδομένων */
αποτέλεσμα = _bios_disk(_DISK_READ, &dinfo);
/* Εάν υπάρχει σφάλμα κατά την ανάγνωση οποιουδήποτε τομέα */
if( (αποτέλεσμα & 0xff00) != 0)
{
gotoxy (5,25);
cprintf("σφάλμα ανάγνωσης κυλίνδρου %u, κεφαλής %u, τομέας %u",
κύλινδρος, κεφαλή, τομέας).
}
αλλού
{
if(sec==1)
{
for(i=0;i<αριστερά;i++)
fputc(buf[i],fp); /* Γράψτε το ολοκληρωμένο
Πληροφορίες για το Αρχείο */
}
αλλού
{
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(ανυπόγραφο int c, ανυπόγραφο int h, ανυπόγραφο int s)
{
int status?
char *buf;
ένωση REGS μέσα, έξω?
struct SREGS sg;
in.h.ah = 0x04; /* Αριθμός συνάρτησης */
in.h.al = 1; /* Αριθμός τομέων προς επαλήθευση*/
in.h.dl = 0x00; /* Αριθμός δίσκου για A: */
in.h.ch = c; /* Αριθμός κυλίνδρου */
in.h.dh = h; /* Αριθμός κεφαλής */
in.h.cl = s; /* Αριθμός τομέα */
in.x.bx = FP_OFF(buf);/* Μετατόπιση */
sg.es = FP_SEG(buf); /* Τμήμα */
int86x(0x13,&in,&out,&sg); /* Συνάρτηση κλήσης 4Η
από INT 13H */
if(out.x.cflag)
{
status=out.h.ah;
}
επιστροφή(κατάσταση);
}
Σχόλια κωδικοποίησης:
Η συνάρτηση verify_the_sector() επαληθεύει τον τομέα που θα διαβαστεί από τη συνάρτηση _bios_disk() και επιστρέφει την κατάσταση της λειτουργίας. Η συνάρτηση χρησιμοποιεί INT 13H και λειτουργία 4H για να ελέγξει τον τομέα.
*buf — buffer δεδομένων, 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 (ανυπόγραφη ακέραια συμβολοσειρά)
{
ανυπόγραφη ακέραια στήλη.
/* Υπάρχουν 80 στήλες στη σειρά */
for(στήλη=1;στήλη<=80;στήλη++)
{
gotoxy (στήλη, σειρά);
cprintf(" "); /* Διαγραφή με " " */
}
}
Σχόλια κωδικοποίησης:
Η λειτουργία χρησιμοποιείται για την εκκαθάριση της καθορισμένης γραμμής στην οθόνη . Η συνάρτηση καλείται με τον αριθμό γραμμής που πρέπει να διαγραφεί από την οθόνη.