Kapitel – 10
Wiederherstellen von Daten von einer beschädigten Festplatte
Wiederherstellen von Daten von einer beschädigten Diskette
Eine Diskette ist eine der unzuverlässigsten Quellen zur Datenspeicherung. Wenn Sie eine Organisation aufsuchen, die Computersysteme verwendet, und deren Mitarbeiter nach Problemen fragen, die durch Disketten verursacht werden, werden Sie sehr oft hören, dass das Problem darin besteht, dass ein Mitarbeiter der Organisation wichtige Daten auf seiner Diskette hatte und diese nun vom Computer nicht mehr gelesen werden kann und auf dem Bildschirm eine Meldung ähnlich der folgenden erscheint:
„Disk kann nicht gelesen werden“
„Fehlerhafter Track 0“
„Ungültige Disk oder Kapazität“
„Disk nicht formatiert.“ Möchten Sie es jetzt formatieren?
Dies ist ein alltägliches Problem für Organisationen, die Computersysteme und Disketten verwenden. Das Problem wird kritisch, wenn Sie feststellen, dass für die scheinbar verlorenen Daten auf der beschädigten Diskette keine Sicherungskopie erstellt wurde oder keine Sicherungskopie verfügbar ist.
Das größte Problem tritt auf, wenn Sie wichtige Informationen auf einer Diskette sichern, Disketten mit Antivirenprogrammen wiederherstellen, um einen Virenangriff zu verhindern, oder Boot-Records oder andere Sicherungen (hierfür gibt es möglicherweise mehrere Möglichkeiten) auf einer Diskette speichern und ein Lesefehler auftritt, wenn Sie die Sicherung von der Diskette wiederverwenden möchten.
In einem solchen Fall besteht die Gefahr, dass wichtige Informationen und Daten verloren gehen. In manchen Fällen, wenn Sicherungs- und Wiederherstellungsprogramme für die Startinformationen Ihres Computers oder Rettungsprogramme für Virenangriffe usw. fehlen, kann es zu einem erheblichen Datenverlust in Form eines Betriebssystemausfalls kommen, da auf der Diskette gespeicherte Informationen fehlen und vom Computer momentan nicht gelesen werden können.
In solchen Fällen besteht die wichtigste Anforderung darin, Daten von einer Diskette wiederherzustellen , die Ihr Computersystem als fehlerhaft erkannt hat.
Warum ist die Diskette nicht lesbar?
Das am häufigsten auftretende Problem, das zu derartigen Fehlermeldungen auf einer Diskette führt, ist eine Beschädigung des DOS Boot Record (DBR) der Diskette, der dem Computer dabei hilft, die logische Identität der Diskette zu erkennen.
Der DBR ist ein kleines Programm, das auf Spur 0, Kopf 0 und Sektor 1 gespeichert ist und wichtige Informationen über die Diskette enthält, beispielsweise:
- Anzahl der Bytes pro Sektor
- Sektor pro Cluster
- Anzahl der FAT
- Maximale Anzahl an Stammverzeichnissen usw.
Da die Diskette kein logisches Partitionssystem hat, gibt es auf der Diskette keinen MBR. Der erste Sektor der Diskette enthält den DBR. Dies ist auch der Hauptunterschied, wenn man die logische Struktur einer Festplatte mit der einer Diskette vergleicht.
Wenn wir die Bootsektorinformationen der Diskette mit einem beliebigen Diskettenbearbeitungsprogramm lesen, werden Informationen wie die im Bild unten gezeigten angezeigt.
Die folgende Abbildung zeigt 512 Byte DBR-Informationen auf einer 1,44 MB großen 3½-Zoll-Diskette.

Wenn diese Informationen irgendwie beschädigt oder unlesbar werden, erzeugt die Diskette diese Lesefehlermeldungen. Die Ursache hierfür kann ein physischer oder logischer Schaden am ersten Sektor der Festplatte sein.
Zu den logischen Beschädigungen zählen Fälle, in denen die Informationen im ersten Sektor der Diskette geändert werden, ein logisch beschädigter Sektor vorliegt oder der DBR der Diskette aus einem anderen Grund beschädigt ist.
Ein physischer Schaden wird angenommen, wenn der erste Sektor der Diskette physisch fehlerhafte Sektoren aufweist (d. h. Sektor 1 ist physisch beschädigt). Das Problem wird schwerwiegender, wenn Sie feststellen, dass die Diskette mehr als einen fehlerhaften Sektor auf Spur 0 aufweist.
So erholen Sie sich
Da wir nun beide Schadensursachen kennengelernt haben, hoffe ich, dass Sie nun das Problem verstehen können. Es ist nicht allzu schwierig, Daten nach einer logischen Beschädigung wiederherzustellen, die Wiederherstellung nach einer physischen Beschädigung erfordert jedoch etwas mehr Aufwand.
Methode – 1
Speichern Sie ein bootfähiges Image einer beliebigen neuen Diskette.
Wenn das Problem logisch ist, wissen wir jetzt, wie wir die Daten wiederherstellen können . Wir müssen lediglich den entsprechenden Boot-Datensatz von einer anderen Diskette mit gleicher Größe und Kapazität holen und ihn in den ersten Sektor der nicht lesbaren Diskette einfügen. Obwohl das Problem durch den fehlerhaften Boot-Datensatz verursacht wurde , sollte es jetzt funktionieren.
Dieses Verfahren umfasst zwei Schritte, mit denen wir unsere Daten von einer nicht lesbaren Diskette wiederherstellen:
- Erstellen des Images des DOS-Boot-Records einer funktionierenden Diskette
- Einfügen des Boot-Images in den ersten Sektor einer nicht lesbaren Diskette
Erstellen des Images des DOS-Boot-Records einer funktionierenden Diskette
Um das Image des Boot-Records einer neuen Diskette zu speichern, muss das Programm die folgenden drei Aufgaben ausführen:
- Liest genau die ersten 512 Bytes der guten Diskette
- Prüfen Sie, ob der Lesevorgang erfolgreich war (am wichtigsten)
- Speichern Sie diese 512 Bytes unter dem angegebenen Dateinamen und Zielpfad
Der Sektor der Diskette ist 512 Byte groß und es ist notwendig, das genaue Abbild des Sektors zu kopieren. Dies ist der wichtigste und notwendigste Schritt bei jeder Art von Operation auf der Diskette, um zu überprüfen, ob die Operation erfolgreich war oder nicht.
Auch bei einer einwandfreien und neuen Diskette kann es zu Initialisierungsproblemen kommen. Deshalb wird in den meisten Fällen, wenn der Vorgang auf Disketten ausgeführt wird, zunächst die Initialisierung der Diskette bei der Programmierung mit dem Vorgang zum Zurücksetzen der Diskette (Funktion 00 H von INT 13H) durchgeführt.
Wenn auch nach der Initialisierung die kürzlich eingelegte oder gewechselte Diskette einen Lesefehler verursacht , wird Ihnen empfohlen, das Programm erneut auszuführen, höchstwahrscheinlich funktioniert es dieses Mal.
Das folgende Programm soll diese angegebenen Aufgaben ausführen. Sehen wir uns an, wie es vorgeht:
/* Das Boot-Image von einer neuen Diskette in eine Datei speichern */
#include <bios.h>
#include <stdio.h>
int Haupt(void)
{
Struktur diskinfo_t dinfo;
Gewerkschaftsvorschriften;
int Ergebnis;
int-Anzahl=0, i;
char fname[80];
statisches Zeichen dbuf[512];
DATEI *fp;
dinfo.drive = 0x00; /* Laufwerksnummer für A: */
dinfo.head = 0; /* Festplattenkopfnummer */
dinfo.track = 0; /* Titelnummer */
dinfo.sector = 1; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
clrscr();
gotoxy(10,3);cprintf("Geben Sie den Dateinamen und den Pfad ein zu
Boot-Image speichern");
gotoxy(5,5);
bekommt(fname);
fp=fopen(fname,"wb");
wenn((fp=fopen(fname,"wb"))==NULL)
{
hochvideo();
gotoxy(10,10);cprintf("Datei konnte nicht erstellt werden");
getch();
Ausfahrt (0);
}
gotoxy(10,9);
cprintf("Versuch, vom Diskettenlaufwerk zu lesen :\n");
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
Ergebnis = _bios_disk(_DISK_READ, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
während(Anzahl<512)
{
fprintf(fp,"%c",dbuf[Anzahl] & 0xff );
zählen++;
}
fschließen(fp);
gotoxy(10,14);cprintf("Diskette vom Diskettenlaufwerk lesen
: erfolgreich.\n");
}
anders
{
gotoxy(10,14);
cprintf("Laufwerk A kann nicht gelesen werden, Status = 0x%02x\n", Ergebnis);
Schalter(Ergebnis)
{
Fall 0x00:
cprintf("\n\n STATUS: Kein Fehler!! ");
brechen;
Fall 0x01:
cprintf("\n\n STATUS: Ungültiger Befehl ");
brechen;
Fall 0x02:
cprintf("\n\n STATUS: Adressmarkierung nicht gefunden ");
brechen;
Fall 0x03:
cprintf("\n\n STATUS: Versuch, auf schreibgeschützte Festplatte zu schreiben ");
brechen;
Fall 0x04:
cprintf("\n\n STATUS: Sektor nicht gefunden ");
brechen;
Fall 0x06:
cprintf("\n\n STATUS: Datenträger seit dem letzten Vorgang geändert ");
brechen;
Fall 0x08:
cprintf("\n\n STATUS: Überlauf beim direkten Speicherzugriff (DMA) ");
brechen;
Fall 0x09:
cprintf("\n\n STATUS: Versuch, DMA über die 64K-Grenze durchzuführen ");
brechen;
Fall 0x0C:
cprintf("\n\n STATUS: Medientyp nicht gefunden ");
brechen;
Fall 0x10:
cprintf("\n\n STATUS: Falscher CRC/ECC beim Lesen der Festplatte ");
brechen;
Fall 0x20:
cprintf("\n\n STATUS: Controller ist ausgefallen ");
brechen;
Fall 0x31:
cprintf("\n\n STATUS: Kein Medium im Laufwerk (IBM/MS INT 13H-Erweiterungen) ");
brechen;
Fall 0x32:
cprintf("\n\n STATUS: Falscher Laufwerkstyp im CMOS gespeichert (Compaq) ");
brechen;
Fall 0x40:
cprintf("\n\n STATUS: Suchvorgang fehlgeschlagen ");
brechen;
Fall 0x80:
cprintf("\n\n STATUS: Anhang konnte nicht antworten (Datenträger-Zeitüberschreitung) ");
brechen;
Fall 0xB0:
cprintf("\n\n STATUS: Datenträger im Laufwerk nicht gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB1:
cprintf("\n\n STATUS: Datenträger im Laufwerk gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB2:
cprintf("\n\n STATUS: Datenträger nicht entfernbar (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB3:
cprintf("\n\n STATUS: Datenträger wird verwendet (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB4:
cprintf("\n\n STATUS: Anzahl der Sperren überschritten (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB5:
cprintf("\n\n STATUS: Gültige Auswurfanforderung fehlgeschlagen (INT 13H-Erweiterungen) ");
brechen;
Standard: cprintf("\n\n STATUS: UNBEKANNTER Statuscode für Diskettenfehler ");
}
}
gebe 0 zurück;
}
Kommentare zur Programmcodierung:
In der zuvor angegebenen Programmcodierung führen wir grundsätzlich die folgenden Aufgaben Schritt für Schritt aus:
- dinfo verweist auf die Struktur diskinfo_t, die die Informationen zu den Parametern enthält, die für den von der Funktion _bios_disk ausgeführten Vorgang erforderlich sind.
- Da wir den ersten Sektor der Festplatte lesen möchten, ist die Position des Sektors wie folgt:
Parameter |
Was es bedeutet |
dinfo.drive = 0x00 |
Es zeigt das Laufwerk 0 an , das ein Diskettenlaufwerk ist ( a: ) |
dinfo.head = 0 |
Es zeigt auf Kopf Nummer 0 |
dinfo.track = 0 |
Es zeigt auf Spur 0 |
dinfo.sektor = 1 |
Erster Sektor der Diskette, also Sektor 1 |
dinfo.sektor = 1 |
Anzahl der für den Lesevorgang zu berücksichtigenden Sektoren = 1 |
dinfo.buffer = dbuf |
Datenpuffer für die Operation |
- Öffnen Sie einen Dateistream mit benutzerdefiniertem Dateinamen und Pfad, um die Boot-Image-Informationen von genau 512 Bytes zu speichern. Der Dateiname und der Pfad werden im Zeichenarray fname gespeichert.
- Initialisieren Sie das Plattensystem mit dem Interrupt 13H (Funktion 00h), wobei regs.h.ah = 0x00 auf die Funktion 00 H verweist und regs.h.dl = 0x00 für eine Diskette verwendet wird. Und int86(0x13, ®s, ®s) ruft den MS-DOS-Interruptdienst INT 13 H auf.
- _bios_disk(_DISK_READ, &dinfo) liest den angegebenen Sektor der Diskette.
- Der zurückgegebene Status wird im Ergebnis gespeichert und dient dazu, die Meldung für den erfolgreichen Vorgang anzuzeigen oder, falls ein Fehler auftritt, eine Fehlermeldung auf dem Bildschirm anzuzeigen.

Einfügen des Boot-Images in den ersten Sektor einer nicht lesbaren Diskette
Um das Boot-Image aus der Datei in den ersten Sektor der nicht lesbaren Diskette einzufügen, müssen wir in unserem Programm die folgenden drei Hauptaufgaben ausführen:
- Lesen Sie die genauen 512 Byte Informationen des Boot-Datensatzes einer neuen Diskette aus einer zuvor gespeicherten Datei.
- Schreiben Sie diese Informationen in den ersten Sektor der Diskette, der derzeit nicht lesbar ist.
- Überprüfen Sie, ob der Schreibvorgang erfolgreich abgeschlossen wurde (am wichtigsten).
Da der Sektor der Diskette 512 Byte groß ist, muss das genaue Boot-Image in den Sektor eingefügt werden. Bei jeder Art von Operation auf der Diskette ist dies der wichtigste und notwendigste Schritt, um zu überprüfen, ob die Operation erfolgreich war oder nicht.
Während des Vorgangs kann es zu Initialisierungsproblemen mit der Diskette kommen. Deshalb müssen Sie die Diskette durch Zurücksetzen des Diskettensystems (mithilfe der Funktion 00H von INT 13H) initialisieren.
Wenn auch nach der Initialisierung die kürzlich eingelegte oder gewechselte Diskette einen Lesefehler verursacht , wird Ihnen empfohlen, das Programm erneut auszuführen, höchstwahrscheinlich funktioniert es dieses Mal.
Das folgende Programm soll diese angegebenen Aufgaben ausführen. Sehen wir uns an, wie es vorgeht:
/* Boot-Image auf die nicht lesbare Diskette laden */
#include <bios.h>
#include <stdio.h>
int Haupt(void)
{
Struktur diskinfo_t dinfo;
Gewerkschaftsvorschriften;
int Ergebnis;
int-Anzahl=0, i;
char fname[80];
char dbuf[512];
DATEI *fp;
clrscr();
gotoxy(5,3);cprintf("Geben Sie den Dateinamen und den Pfad ein, in dem das Boot-Image der Diskette gespeichert ist");
gotoxy(5,5);
bekommt(fname);
fp=fopen(fname,"rb");
wenn((fp=fopen(fname,"rb"))==NULL)
{
hochvideo();
gotoxy(10,10);cprintf("Datei konnte nicht geöffnet werden");
getch();
Ausfahrt (0);
}
gotoxy(10,9);
cprintf("Versuch, Diskettenlaufwerk :\n wiederherzustellen");
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
während(Anzahl<512)
{
fscanf(fp,"%c",&dbuf[Anzahl]);
zählen++;
}
dinfo.drive = 0x00; /* Laufwerksnummer für A: */
dinfo.head = 0; /* Festplattenkopfnummer */
dinfo.track = 0; /* Titelnummer */
dinfo.sector = 1; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
Ergebnis = _bios_disk(_DISK_WRITE, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
fschließen(fp);
gotoxy(10,14);cprintf("Erfolgreich!!! Ich hoffe, Floppy kann
Jetzt arbeiten.\n");
}
anders
{
gotoxy(10,14);
cprintf("Laufwerk A kann nicht gelesen werden, Status = 0x%02x\n", Ergebnis);
gotoxy(10,16);
Schalter(Ergebnis)
{
Fall 0x00:
cprintf("\n\n STATUS: Kein Fehler!! ");
brechen;
Fall 0x01:
cprintf("\n\n STATUS: Ungültiger Befehl ");
brechen;
Fall 0x02:
cprintf("\n\n STATUS: Adressmarkierung nicht gefunden ");
brechen;
Fall 0x03:
cprintf("\n\n STATUS: Versuch, auf schreibgeschützte Festplatte zu schreiben ");
brechen;
Fall 0x04:
cprintf("\n\n STATUS: Sektor nicht gefunden ");
brechen;
Fall 0x06:
cprintf("\n\n STATUS: Datenträger seit dem letzten Vorgang geändert ");
brechen;
Fall 0x08:
cprintf("\n\n STATUS: Überlauf beim direkten Speicherzugriff (DMA) ");
brechen;
Fall 0x09:
cprintf("\n\n STATUS: Versuch, DMA über die 64K-Grenze durchzuführen ");
brechen;
Fall 0x0C:
cprintf("\n\n STATUS: Medientyp nicht gefunden ");
brechen;
Fall 0x10:
cprintf("\n\n STATUS: Falscher CRC/ECC beim Lesen der Festplatte ");
brechen;
Fall 0x20:
cprintf("\n\n STATUS: Controller ist ausgefallen ");
brechen;
Fall 0x31:
cprintf("\n\n STATUS: Kein Medium im Laufwerk (IBM/MS INT 13H-Erweiterungen) ");
brechen;
Fall 0x32:
cprintf("\n\n STATUS: Falscher Laufwerkstyp im CMOS gespeichert (Compaq) ");
brechen;
Fall 0x40:
cprintf("\n\n STATUS: Suchvorgang fehlgeschlagen ");
brechen;
Fall 0x80:
cprintf("\n\n STATUS: Anhang konnte nicht antworten (Datenträger-Zeitüberschreitung) ");
brechen;
Fall 0xB0:
cprintf("\n\n STATUS: Datenträger im Laufwerk nicht gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB1:
cprintf("\n\n STATUS: Datenträger im Laufwerk gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB2:
cprintf("\n\n STATUS: Datenträger nicht entfernbar (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB3:
cprintf("\n\n STATUS: Datenträger wird verwendet (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB4:
cprintf("\n\n STATUS: Anzahl der Sperren überschritten (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB5:
cprintf("\n\n STATUS: Gültige Auswurfanforderung fehlgeschlagen (INT 13H-Erweiterungen) ");
brechen;
Standard: cprintf("\n\n STATUS: UNBEKANNTER Statuscode für Diskettenfehler ");
}
}
gebe 0 zurück;
}
Kommentare zur Programmcodierung:
In der zuvor angegebenen Programmcodierung führen wir grundsätzlich die folgenden Aufgaben Schritt für Schritt aus:
- dinfo verweist auf die Struktur diskinfo_t, die die Informationen zu den Parametern enthält, die für den von der Funktion _bios_disk ausgeführten Vorgang erforderlich sind.
- Da wir die Informationen in den ersten Sektor der Festplatte schreiben, ist die Position des Sektors wie folgt:
- Öffnen Sie die Datei, in der die Boot-Image-Informationen von 512 Bytes einer neuen Diskette vom vorherigen Programm gespeichert wurden. Der Dateiname und der Pfad sind im Zeichenarray fname gespeichert.
- Initialisieren Sie das Plattensystem mit dem Interrupt 13H (Funktion 00h), wobei regs.h.ah = 0x00 auf die Funktion 00 H verweist und regs.h.dl = 0x00 für eine Diskette verwendet wird. Und int86(0x13, ®s, ®s) ruft den MS-DOS-Interruptdienst INT 13 H auf.
- _bios_disk(_DISK_WRITE, &dinfo) schreibt die Boot-Informationen aus der angegebenen Datei in den ersten (angegebenen) Sektor der Diskette.
- Der zurückgegebene Status wird im Ergebnis gespeichert und dient dazu, die Meldung für den erfolgreichen Vorgang anzuzeigen oder, falls ein Fehler auftritt, eine Fehlermeldung auf dem Bildschirm anzuzeigen.
Parameter |
Was es bedeutet |
dinfo.drive = 0x00 |
Es zeigt das Laufwerk 0 an , das ein Diskettenlaufwerk ist ( a: ) |
dinfo.head = 0 |
Es zeigt auf Kopf Nummer 0 |
dinfo.track = 0 |
Es zeigt auf Spur 0 |
dinfo.sektor = 1 |
Erster Sektor der Diskette, also Sektor 1 |
dinfo.sektor = 1 |
Anzahl der für den Schreibvorgang zu berücksichtigenden Sektoren = 1 |
dinfo.buffer = dbuf |
Datenpuffer für die Operation |
Lassen Sie es uns mit einem einzigen Programm machen
Ich hoffe, Sie haben jetzt das Konzept hinter dieser Art der Datenwiederherstellung von der Diskette verstanden . Stellen wir uns nun ein einzelnes Programm vor, das dieselben Ergebnisse liefert, die wir mit Hilfe der beiden zuvor besprochenen Programme erzielt haben.
Mit den zuletzt besprochenen Programmen haben wir folgende Aufgaben bearbeitet:
- Speichern Sie die Boot-Informationen einer funktionierenden Diskette in einer Datei
- Fügen Sie diese Informationen in den ersten Sektor der derzeit nicht lesbaren Diskette ein. Die Datei, die wir zum Speichern des Boot-Images verwendeten, fungierte als Zwischenbrücke, um die Vorgänge beider Programme zu verbinden. Wenn wir diese Boot-Informationen jedoch in unserem Programmcode selbst definieren, müssen wir weder eine Datei erstellen, noch müssen wir die Boot-Informationen der Diskette aus der Datei lesen.
In unserem nächsten Programm teilen wir unserem Programm mit, was es in den ersten Sektor der nicht lesbaren Diskette schreiben soll. Auf diese Weise können wir vermeiden, dass zwei verschiedene Programme dieselbe Aufgabe ausführen, und wir können unsere Daten auf die gleiche Weise wie zuvor aus dem neuen einzelnen Programm wiederherstellen.
Das Programm wird dadurch mit weniger Codierung einfacher und wir können die Wahrscheinlichkeit des Auftretens von Fehlern beim Lesen, Schreiben oder Erstellen von Dateien verringern . Wir führen in diesem Programm die folgenden vier wichtigen Aufgaben aus:
Denken Sie nicht, dass das Programm schwer zu schreiben und zu verstehen ist, wenn man die 512 Byte hexadezimale Information von dbuf[512] sieht. Später besprechen wir, wie Sie diese Information einfach für Ihren Programmcode schreiben können.
- Definieren Sie die DOS-Bootdatensatzinformationen im Hexadezimalsystem, die in den ersten Sektor der derzeit nicht lesbaren Diskette geschrieben werden sollen.
- Setzen Sie das Festplattensystem zurück, um die Diskette zu initialisieren (INT 13H, Funktion 00H).
- Schreiben Sie den DOS-Boot-Record in den ersten Sektor der Diskette
- Überprüfen Sie, ob der Vorgang erfolgreich abgeschlossen wurde und welche Fehler ggf. aufgetreten sind.
Lassen Sie uns das Programm untersuchen:
/* Einzelnes Programm zum Laden des Standard-Boot-Image auf eine nicht lesbare Diskette */
#include <bios.h>
#include <stdio.h>
int Haupt(void)
{
Struktur diskinfo_t dinfo;
Gewerkschaftsreglemente:
int-Ergebnis, i;
/* Boot-Image, das in das Diskettenlaufwerk geladen werden soll */
statisches Zeichen 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; /* Laufwerksnummer für A: */
dinfo.head = 0; /* Festplattenkopfnummer */
dinfo.track = 0; /* Titelnummer */
dinfo.sector = 1; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
gotoxy(10,9);
cprintf("Versuch, vom Diskettenlaufwerk zu lesen :\n");
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
Ergebnis = _bios_disk(_DISK_WRITE, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Datenträger-Schreibstatus: erfolgreich.\n");
}
anders
{
gotoxy(10,14);
cprintf("Laufwerk A kann nicht gelesen werden, Status = 0x%02x\n",
Ergebnis);
gotoxy(10,16);
Schalter(Ergebnis)
{
Fall 0x00:
cprintf("\n\n STATUS: Kein Fehler!! ");
brechen;
Fall 0x01:
cprintf("\n\n STATUS: Ungültiger Befehl ");
brechen;
Fall 0x02:
cprintf("\n\n STATUS: Adressmarkierung nicht gefunden ");
brechen;
Fall 0x03:
cprintf("\n\n STATUS: Versuch, in write- zu schreiben.
geschützte Festplatte ");
brechen;
Fall 0x04:
cprintf("\n\n STATUS: Sektor nicht gefunden ");
brechen;
Fall 0x06:
cprintf("\n\n STATUS: Datenträger seit dem letzten Vorgang geändert ");
brechen;
Fall 0x08:
cprintf("\n\n STATUS: Überlauf beim direkten Speicherzugriff (DMA) ");
brechen;
Fall 0x09:
cprintf("\n\n STATUS: Versuch, DMA über die 64K-Grenze durchzuführen ");
brechen;
Fall 0x0C:
cprintf("\n\n STATUS: Medientyp nicht gefunden ");
brechen;
Fall 0x10:
cprintf("\n\n STATUS: Falscher CRC/ECC beim Lesen der Festplatte ");
brechen;
Fall 0x20:
cprintf("\n\n STATUS: Controller ist ausgefallen ");
brechen;
Fall 0x31:
cprintf("\n\n STATUS: Kein Medium im Laufwerk (IBM/MS INT 13H-Erweiterungen) ");
brechen;
Fall 0x32:
cprintf("\n\n STATUS: Falscher Laufwerkstyp im CMOS gespeichert (Compaq) ");
brechen;
Fall 0x40:
cprintf("\n\n STATUS: Suchvorgang fehlgeschlagen ");
brechen;
Fall 0x80:
cprintf("\n\n STATUS: Anhang konnte nicht antworten (Datenträger-Zeitüberschreitung) ");
brechen;
Fall 0xB0:
cprintf("\n\n STATUS: Datenträger im Laufwerk nicht gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB1:
cprintf("\n\n STATUS: Datenträger im Laufwerk gesperrt (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB2:
cprintf("\n\n STATUS: Datenträger nicht entfernbar (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB3:
cprintf("\n\n STATUS: Datenträger wird verwendet (INT 13-Erweiterungen) ");
brechen;
Fall 0xB4:
cprintf("\n\n STATUS: Anzahl der Sperren überschritten (INT 13H-Erweiterungen) ");
brechen;
Fall 0xB5:
cprintf("\n\n STATUS: Gültige Auswurfanforderung fehlgeschlagen (INT 13H-Erweiterungen) ");
brechen;
Standard: cprintf("\n\n STATUS: UNBEKANNTER Statuscode für Diskettenfehler ");
}
}
gebe 0 zurück;
}
Bei dieser Programmcodierung führen wir grundsätzlich die folgenden Aufgaben Schritt für Schritt aus:
- Der statische Zeichendatenpuffer dbuf[512] liefert die Informationen von 512 Bytes im Hexadezimalsystem, die in den ersten Sektor der nicht lesbaren Diskette geschrieben werden sollen. dbuf[512] teilt dem Computer während des Vorgangs mit, welche Informationen in den ersten Sektor der Diskette geschrieben werden sollen. (Siehe nächstes Programm)
- dinfo verweist auf die Struktur diskinfo_t, die die Informationen zu den Parametern enthält, die für den von der Funktion _bios_disk ausgeführten Vorgang erforderlich sind.
- Da wir die Informationen in den ersten Sektor der Festplatte schreiben, ist die Position des Sektors wie folgt:
Parameter |
Was es bedeutet |
dinfo.drive = 0x00 |
Es zeigt das Laufwerk 0 an , das ein Diskettenlaufwerk ist ( a: ) |
dinfo.head = 0 |
Es zeigt auf Kopf Nummer 0 |
dinfo.track = 0 |
Es zeigt auf Spur 0 |
dinfo.sektor = 1 |
Erster Sektor der Diskette, also Sektor 1 |
dinfo.sektor = 1 |
Anzahl der für den Schreibvorgang zu berücksichtigenden Sektoren = 1 |
dinfo.buffer = dbuf |
Datenpuffer für die Operation |
- Initialisieren Sie das Plattensystem mit dem Interrupt 13H (Funktion 00h), wobei regs.h.ah = 0x00 auf die Funktion 00 H verweist und regs.h.dl = 0x00 für eine Diskette verwendet wird. Und int86(0x13, ®s, ®s) ruft den MS-DOS-Interruptdienst INT 13 H auf.
- _bios_disk(_DISK_WRITE, &dinfo) schreibt die Boot-Informationen aus der angegebenen Datei in den ersten (angegebenen) Sektor der Diskette.
Der zurückgegebene Status wird im Ergebnis gespeichert und dient dazu, die Meldung für den erfolgreichen Vorgang anzuzeigen oder, falls ein Fehler auftritt, eine Fehlermeldung auf dem Bildschirm anzuzeigen.
Speichern des Boot-Image in HEXADEZIMALEN Zeichen zur Verwendung in unserem vorherigen Programm
Es wird eine sehr schwierige Aufgabe sein, alle 512 Zeichen des DOS-Boot-Records der Diskette manuell im Hexadezimalsystem zu schreiben, ohne dass in dem Programm, das wir gerade besprochen haben, Fehler auftreten. Selbst wenn wir es genau schreiben können, wird es eine schwierige und zeitaufwändige Aufgabe sein. Lassen Sie uns etwas tricksen, um die Daten für den Datenpuffer dbuf[512] in einer Datei zu speichern.
Wir wissen, dass in der C-Programmierung die hexadezimalen Zeichen mit 0x dargestellt werden, sodass wir, wenn das hexadezimale Zeichen A9 H ist, dies in unserem C-Programm als 0xA9 schreiben. Unser nächstes Programm macht dasselbe. Es speichert die Daten, die wir in unserem vorherigen Programm schreiben mussten, als Daten des Datenpuffers dbuf[512].
Sie müssen lediglich eine neue Diskette nehmen, um ein Image ihres DBR zu erstellen, die Ausgabe dieses Programms aus der angegebenen Zieldatei zu kopieren und diese Daten in Ihr Programm einzufügen. Nehmen Sie bei Bedarf eine Formatierung vor. Sehen wir uns an, wie es funktioniert:
/* Programm zum Erstellen des Boot-Image der Diskette in HEX-Zeichen */
#include <bios.h>
#include <stdio.h>
int Haupt(void)
{
Struktur diskinfo_t dinfo;
Gewerkschaftsvorschriften;
int Ergebnis,i;
int-Anzahl=0;
char fname[80];
statisches Zeichen dbuf[512];
DATEI *fp;
dinfo.drive = 0x00; /* Laufwerksnummer für A: */
dinfo.head = 0; /* Festplattenkopfnummer */
dinfo.track = 0; /* Titelnummer */
dinfo.sector = 1; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
clrscr();
gotoxy(10,3);cprintf("Geben Sie den Dateinamen und den Pfad ein zu
Speichern Sie das Boot-Image im HEX-System");
gotoxy(5,5);
bekommt(fname);
fp=fopen(fname,"wb");
wenn((fp=fopen(fname,"wb"))==NULL)
{
hochvideo();
gotoxy(10,10);cprintf("Datei konnte nicht erstellt werden");
getch();
Ausfahrt (0);
}
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("Versuch, von Diskette zu lesen
Diskettenlaufwerk :\n");
Ergebnis = _bios_disk(_DISK_READ, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Diskette vom Diskettenlaufwerk lesen:
erfolgreich.\n");
während(Anzahl<512)
{
fprintf(fp,"0x%X, ",dbuf[Anzahl] & 0xff );
zählen++;
}
fschließen(fp);
}
anders
{
gotoxy(10,14);
cprintf("Laufwerk A kann nicht gelesen werden, Status = 0x%02x\n",
Ergebnis);
}
gebe 0 zurück;
}
Kommentare zur Codierung des Programms:
Damit sind die Daten in der angegebenen Datei gespeichert. Kopieren Sie die Daten einfach in Ihr Programm und nehmen Sie die erforderlichen Formatierungen vor. Folgende Tipps sollten Sie bei der Vorgehensweise nie vergessen:
- Stellen Sie sicher, dass das Programm erfolgreich ausgeführt wurde und die in der Zieldatei gespeicherten Daten korrekt sind.
- Sie sollten den Vorgang gründlich auf das Auftreten erwarteter Fehler überprüfen.
- Sie müssen die Diskette mit dem Programm initialisieren, bevor Sie den Bootsektor lesen. Sie können zu diesem Zweck die Funktion 00H von INT 13H verwenden.
Methode – 2
Was tun, wenn Methode 1 nicht funktioniert?
Wenn Methode 1 nicht funktioniert und die nicht lesbare Diskette es dem Programm nicht erlaubt, die Startinformationen in ihrem ersten Sektor neu zu schreiben, sollten Sie diese zweite Methode ausprobieren. Der Grund für das Scheitern der ersten Methode kann eine physische Beschädigung des ersten Sektors der Diskette sein.
Bei dieser zweiten Methode kopieren wir alle Daten von der Oberfläche der nicht lesbaren Diskette vorübergehend in eine einzige Datei und fügen dieses Image dann direkt auf der Oberfläche einer anderen funktionierenden Diskette ein.
Das Verfahren umfasst die folgenden zwei wichtigen Schritte:
- Sektor-für-Sektor: Kopiert vorübergehend alle Daten von der Oberfläche des Diskettenmediums in eine einzige Datei.
- Fügen Sie die zuvor in der Datei gespeicherten Daten unverändert in denselben Sektoren auf einer neuen, frischen Diskette ein.
Alle Daten der Medienoberfläche in eine einzige Datei kopieren
Um alle Daten auf der Oberfläche des Diskettenmediums zu speichern, muss das Programm die folgenden drei Aufgaben ausführen:
- Initialisieren Sie die Festplatte ordnungsgemäß mithilfe der Funktion 00H von INT 13H.
- Lesen Sie die Sektor-für-Sektor-Informationen der Oberfläche und speichern Sie sie in einer einzigen Datei.
- Prüfen Sie, ob der Lesevorgang erfolgreich war (am wichtigsten)
Bei einer Diskette kommt es häufig zu Initialisierungsproblemen, die zu vielen fehlgeschlagenen Lesemeldungen führen. Deshalb muss die Diskette vor dem Lese-/Schreibvorgang mithilfe einer Programmierung initialisiert werden.
Bei jeder Art von Operation auf einer Diskette ist es der wichtigste und notwendige Schritt, zu prüfen, ob die Operation erfolgreich war oder nicht.
Wenn auch nach der Initialisierung die kürzlich eingelegte oder gewechselte Diskette einen Lesefehler verursacht, wird Ihnen empfohlen, das Programm erneut auszuführen, höchstwahrscheinlich funktioniert es dieses Mal.
Das folgende Programm soll diese angegebenen Aufgaben ausführen. Sehen wir uns an, wie es vorgeht:
/* Programm zum Speichern der Daten der physischen Oberfläche der Diskette in einer Datei */
#include <bios.h>
#include <stdio.h>
Leere Haupt(Leere)
{
int Kopf, Spur;
Gewerkschaftsvorschriften;
int Ergebnis,i,Sektor;
char Dateiname[80];
Struktur diskinfo_t dinfo;
statisches Zeichen dbuf[512];
DATEI *tt;
clrscr();
printf("\n Geben Sie den Namen der Datei mit dem Pfad zum Speichern ein.
Daten vorübergehend\n");
bekommt(Dateiname);
wenn((tt=fopen(Dateiname,"wb"))==NULL)
{
printf("Die Datei konnte nicht erstellt werden,
Zum Beenden eine beliebige Taste drücken");
getch();
Ausfahrt (0);
}
printf("\n Initialisierung des Diskettensystems...\n");
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
für (Spur=0;Spur<=79;Spur++)
{
für (Kopf=0;Kopf<=1;Kopf++)
{
für (Sektor = 1; Sektor <= 18; Sektor ++)
{
dinfo.drive = 0; /* Laufwerksnummer für A: */
dinfo.head = head; /* Festplattenkopfnummer */
dinfo.track = Titel; /* Titelnummer */
dinfo.sector = Sektor; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
Ergebnis = _bios_disk(_DISK_READ, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
für (i = 0; i < 512; i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
anders
{
printf("Laufwerk A kann nicht gelesen werden, Status =
0x%02x\t%d\t%d\t%d\n", Ergebnis, Kopf, Spur, Sektor);
}
printf("Lesespur= %d Kopf= %d Sektor= %d\n",
Spur, Kopf, Sektor);
}
}
}
}
Kommentare zur Programmcodierung:
In der zuvor angegebenen Programmcodierung führen wir grundsätzlich die folgenden Aufgaben Schritt für Schritt aus:
- Das Zeichenarray filename[80] speichert den benutzerdefinierten Pfad und Dateinamen der Datei, in der wir die Daten vorübergehend speichern werden.
- dinfo verweist auf die Struktur diskinfo_t, die die Informationen zu den Parametern enthält, die für den von der Funktion _bios_disk ausgeführten Vorgang erforderlich sind.
- Initialisieren Sie das Plattensystem mit dem Interrupt 13H (Funktion 00h), wobei regs.h.ah = 0x00 auf die Funktion 00 H verweist und regs.h.dl = 0x00 für eine Diskette verwendet wird. Und int86(0x13, ®s, ®s) ruft den MS-DOS-Interruptdienst INT 13 H auf.
- Da wir alle Informationen von der Festplattenoberfläche lesen werden, lauten die Parameter von _bios_disk wie folgt:
Parameter |
Was es bedeutet |
dinfo.drive = 0x00 |
Es zeigt das Laufwerk 0 an , das ein Diskettenlaufwerk ist ( a: ) |
dinfo.head = Kopf |
Es zeigt auf Kopfnummer 0 und 1, da die Diskette zwei Seiten (zwei Köpfe) hat. |
dinfo.track = Spur |
Es zeigt auf die Spuren 0 bis 79, da sich auf jeder Seite der Diskette 80 Spuren befinden . |
dinfo.sector = Sektor |
Es zeigt auf die Sektoren 1 bis 18, da jede Spur 18 Sektoren enthält . |
dinfo.sektor = 1 |
Anzahl der für den Lesevorgang zu berücksichtigenden Sektoren = 1 |
dinfo.buffer = dbuf |
Datenpuffer für die Operation |
- _bios_disk(_DISK_READ, &dinfo) liest die Daten von der physischen Oberfläche der Diskette aus dem durch dinfo angegebenen Sektor.
- Der zurückgegebene Status wird im Ergebnis gespeichert und dient dazu, die Meldung für den erfolgreichen Vorgang anzuzeigen oder, falls ein Fehler auftritt, eine Fehlermeldung auf dem Bildschirm anzuzeigen.
Denken Sie immer daran, dass die Größe der Datei, die das Abbild der Daten der Diskette enthält, genau 1.474.560 Bytes betragen muss, da die Diskette 80 Spuren (0 bis 79), 2 Seiten oder Köpfe (Kopf 0 und Kopf 1) hat, jede Spur 18 Sektoren enthält und jeder Sektor 512 Bytes Daten enthält, also
Gesamtbytes = (Anzahl der Spuren) * (Anzahl der Köpfe) *
(Anzahl der Sektoren pro Spur) * 512
= 80*2*18*512
= 1.474.560 Bytes
Wenn also beim Lesen eines beliebigen Sektors der Diskette ein Fehler auftritt, ändert sich die Größe der Datei von 1.474.560 Bytes, wodurch die gesamten Informationen für die Zieldiskette, auf die wir das Disk-Image aus dieser Datei Sektor für Sektor schreiben, ganz oder teilweise unbrauchbar werden.
Dies liegt daran, dass der Computer die Informationen jeder Datei auf der Oberfläche des Diskettenmediums innerhalb des Sektorbereichs liest, der in seiner Zuordnungseinheit zugewiesen wurde. Wenn nun die Sektoren der Daten der Dateien geändert werden, werden die gesamten Dateiinformationen geändert.
Überlegen Sie, wie Sie den Lesefehler eines Sektors beheben können.
Bei einer fehlerhaften oder nicht lesbaren Diskette ist es möglich, dass die Oberfläche der Diskette so fehlerhafte Bereiche aufweist, dass wir die Informationen von der Oberfläche der Diskette nicht lesen können.
In diesem Fall werden die Informationen dieses Sektors (dieser Sektoren) übersprungen und das Image der Diskette wird auch für die anderen Sektoren verzerrt, da die Größe der Image-Datei in diesem Fall von 1.474.560 Bytes abweicht.
Um die Größe der Image-Datei beizubehalten und die restlichen Informationen an den genauen Sektorpositionen auf der Zielfestplatte einzufügen, schreiben wir einige andere Informationen anstelle der Originaldaten von 512 Bytes. Auf diese Weise sind wir in der Lage, die restlichen Informationen zu speichern. In einem solchen Fall kann die Wiederherstellung jedoch eine teilweise Wiederherstellung sein.
Wenn Ihr System auch den ersten Sektor der Quelldiskette nicht lesen kann, sollten Sie nach dem Einfügen des Images auf die Zieldiskette das zuvor beschriebene Programm ausführen, um den DOS-Boot-Record der Diskette neu zu schreiben.
Sehen wir uns an, wie wir dies programmieren können:
#include <bios.h>
#include <stdio.h>
Leere Haupt(Leere)
{
int Kopf, Spur;
Gewerkschaftsvorschriften;
int Ergebnis,i,Sektor;
char Dateiname[80];
Struktur diskinfo_t dinfo;
statisches Zeichen dbuf[512];
/* Informationen zu 512 Bytes zum Auffüllen des Speicherplatzes des fehlerhaften Sektors */
/// Ich habe 512 Nullen verwendet, um den Platz von 512 Bytes zu füllen \\\
statisches Zeichen dbuf2[512] =
„00000000000000000000000000000000“ „0000000000000000000000000000000“ „0000000000000000000000“ „00000000000000000000000000000000“ „0000000000000000000000000000000“ „0000000000000000000000“ „00000000000000000000000000000000“ „00000000000000000000000000000000“ „0000000000000000000000000000000“ „0000000000000000000000“ „00000000000000000000000000000000“ „0000000000000000000000000000000“ „0000000000000000000000“ „00000000000000000000000000000000“ „0000000000000000000000000000000“ „00000000000000000000000000000000“;
DATEI *tt;
clrscr();
printf("\n Geben Sie den Namen der Datei mit dem Pfad zum Speichern ein.
Daten vorübergehend\n");
bekommt(Dateiname);
wenn((tt=fopen(Dateiname,"wb"))==NULL)
{
printf("Die Datei konnte nicht erstellt werden. Drücken Sie eine beliebige Taste, um
AUSFAHRT");
getch();
Ausfahrt (0);
}
printf("\n Initialisierung des Diskettensystems...\n");
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
für (Spur=0;Spur<=79;Spur++)
{
für (Kopf=0;Kopf<=1;Kopf++)
{
für (Sektor = 1; Sektor <= 18; Sektor ++)
{
dinfo.drive = 0; /* Laufwerksnummer für A: */
dinfo.head = head; /* Festplattenkopfnummer */
dinfo.track = Titel; /* Titelnummer */
dinfo.sector = Sektor; /* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
Ergebnis = _bios_disk(_DISK_READ, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
{
für (i = 0; i < 512; i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
anders
{
printf("Laufwerk A kann nicht gelesen werden, Status =
0x%02x\t%d\t%d\t%d\n", Ergebnis, Kopf, Spur, Sektor);
/* Wenn der Sektor nicht lesbar ist, belege 512 Bytes mit dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Lesespur= %d Kopf= %d Sektor= %d\n",
Spur, Kopf, Sektor);
}
}
}
}
Kommentare zur Programmcodierung:
Bei der Codierung des Programms ist jeder Schritt derselbe wie im vorherigen Programm, mit Ausnahme des Datenpuffers dbuf2[512], den wir verwenden, um den durch fehlerhafte Sektoren während des Lesevorgangs auf der Festplatte verursachten Fehler zu verarbeiten und die Größe der Image-Datei beizubehalten.
Auf diese Weise füllen wir den Speicherplatz mit den Informationen, die wir aus dem fehlerhaften Sektor nicht lesen konnten , und schreiben nun die Pseudoinformationen von 512 Bytes, damit wir die Genauigkeit des Disk-Images beibehalten können.
Fügen Sie die Daten aus der Datei auf die physische Oberfläche einer neuen Diskette ein:
In diesem Schritt fügen wir die vom vorherigen Programm in der Datei gespeicherten Daten Sektor für Sektor auf die physische Oberfläche der neuen Diskette ein, und zwar auf die gleiche Weise, wie wir sie in die Datei kopiert haben.
Das Programm läuft in den folgenden Hauptschritten ab:
- Öffnen Sie die Datei, in der wir die Oberflächendaten der nicht lesbaren Diskette vorübergehend gespeichert haben.
- Initialisieren Sie das Festplattensystem ordnungsgemäß durch die Rücksetzfunktion 00H von INT 13H.
- Schreiben Sie die Informationen aus der Datei in die Sektoren der neuen Diskette.
- Zeigen Sie gleichzeitig den Schreibstatus an, um das Auftreten von Fehlern zu erkennen oder zu vermeiden.
Der Quellcode des Programms ist unten aufgeführt. Sehen wir uns an, wie es funktioniert:
/* Programm zum Schreiben der Daten auf die Sektoren der Oberfläche einer neuen Diskette aus der vom vorherigen Programm erstellten Datei */
#include <bios.h>
#include <stdio.h>
Leere Haupt(Leere)
{
int Kopf, Spur;
Gewerkschaftsvorschriften;
int Ergebnis,i,Sektor;
int-Anzahl =0;
char Dateiname[80];
Struktur diskinfo_t dinfo;
statisches Zeichen dbuf[512];
DATEI *fp;
clrscr();
printf("\n Geben Sie den Namen der Datei mit dem Pfad zum Speichern ein.
Daten vorübergehend\n");
bekommt(Dateiname);
wenn((fp=fopen(Dateiname,"rb"))==NULL)
{
printf("Die Datei konnte nicht erstellt werden. Drücken Sie eine beliebige Taste, um
AUSFAHRT");
getch();
Ausgang (1);
}
/// Initialisieren Sie das Festplattensystem \\\
für (i = 0; i < 3; i++)
{
regs.h.ah = 0x00; /* Festplattensystem zurücksetzen */
regs.h.dl = 0x00; /* Diskette a: */
int86(0x13, ®s, ®s);
}
für (Spur=0;Spur<=79;Spur++)
{
für (Kopf=0;Kopf<=1;Kopf++)
{
für (Sektor = 1; Sektor <= 18; Sektor ++)
{
Anzahl =0;
während(Anzahl<512)
{
fscanf(fp,"%c",&dbuf[Anzahl]);
zählen++;
}
dinfo.drive = 0x00; /* Laufwerksnummer für A: */
dinfo.head = head; /* Festplattenkopfnummer */
dinfo.track = Titel; /* Titelnummer */
dinfo.sector = Sektor;/* Sektornummer */
dinfo.nsectors = 1; /* Sektorenanzahl */
dinfo.buffer = dbuf; /* Datenpuffer */
Ergebnis= _bios_disk(_DISK_WRITE, &dinfo);
wenn ((Ergebnis & 0xff00) == 0)
printf("Erfolgreiches Schreiben auf Track = %d, Head = %d,
Sektor = %d.\n", Spur, Kopf, Sektor);
anders
printf("Laufwerk A kann nicht gelesen werden, Status = 0x%02x\n",
Ergebnis);
}
}
}
}
Kommentare zur Programmcodierung:
In der zuvor angegebenen Programmcodierung führen wir grundsätzlich die folgenden Aufgaben Schritt für Schritt aus:
- Das Zeichenarray filename[80] enthält den Pfad und Dateinamen der Datei, in der wir die Daten von der Oberfläche der nicht lesbaren Diskette vorübergehend gespeichert haben.
- dinfo verweist auf die Struktur diskinfo_t, die die Informationen zu den Parametern enthält, die für den von der Funktion _bios_disk ausgeführten Vorgang erforderlich sind.
- Initialisieren Sie das Plattensystem mit dem Interrupt 13H (Funktion 00h), wobei regs.h.ah = 0x00 auf die Funktion 00 H verweist und regs.h.dl = 0x00 für eine Diskette verwendet wird. Und int86(0x13, ®s, ®s) ruft den MS-DOS-Interruptdienst INT 13 H auf.
- Da wir die Informationen direkt in Sektoren auf der Festplattenoberfläche schreiben , lauten die Parameter von _bios_disk wie folgt:
Parameter |
Was es bedeutet |
dinfo.drive = 0x00 |
Es zeigt das Laufwerk 0 an , das ein Diskettenlaufwerk ist ( a: ) |
dinfo.head = Kopf |
Es zeigt auf Kopfnummer 0 und 1, da die Diskette zwei Seiten (zwei Köpfe) hat. |
dinfo.track = Spur |
Es zeigt auf die Spuren 0 bis 79, da sich auf jeder Seite der Diskette 80 Spuren befinden . |
dinfo.sector = Sektor |
Es zeigt auf die Sektoren 1 bis 18, da jede Spur 18 Sektoren enthält . |
dinfo.sektor = 1 |
Anzahl der für den Schreibvorgang zu berücksichtigenden Sektoren = 1 |
dinfo.buffer = dbuf |
Datenpuffer für die Operation |
- _bios_disk(_DISK_WRITE, &dinfo) schreibt die Daten in die durch dinfo angegebenen Sektoren der physischen Oberfläche der Diskette.
- Der zurückgegebene Status wird im Ergebnis gespeichert und dient dazu, die Meldung für den erfolgreichen Vorgang anzuzeigen oder, falls ein Fehler auftritt, eine Fehlermeldung auf dem Bildschirm anzuzeigen.
Wenn Ihre neue Diskette nach Methode 2 nicht funktioniert, können Sie Methode 1 auf Ihrer neuen Diskette anwenden, die Sie während Methode 2 als Zieldiskette verwendet haben.
Darüber hinaus kann die Anzahl der Treffer und Versuche je nach Beschädigung der Festplatte variieren. Sie müssen sich jedoch keine Sorgen machen, wenn Sie auch danach keine zufriedenstellenden Ergebnisse erzielen.
Sie können die Wiederherstellung Datei für Datei versuchen oder viele weitere Tipps ausprobieren, die Sie im Folgenden erfahren werden. Hier werden wir die Idee, die Dateiinformationen aus Stammverzeichnissen zu sammeln, in unsere Programmierung zur Wiederherstellung der Daten implementieren.
Überlegungen zur logischen Wiederherstellung gelöschter oder verlorener Daten:
In allen bisherigen Fällen der Wiederherstellung, die wir in diesem Kapitel besprochen haben, ging es um die Wiederherstellung der Daten in Fällen, in denen wir erwarteten, dass nur der DBR beschädigt ist und die Sektoren in Spur 0 mit FAT1, FAT2 und den Stammverzeichnissen lesbar sind .
Wenn das Problem jedoch auf eine Beschädigung der FAT-Datei zurückzuführen ist oder die Daten von der Festplatte gelöscht wurden oder Sie die Daten direkt durch Lesen der Informationen aus dem Stammverzeichnis wiederherstellen möchten , müssen wir Informationen wie Dateiname , Startcluster , Dateigröße , Attribute usw. aus dem Stammverzeichniseintrag lesen .
Wie wir bereits in früheren Kapiteln über das Stammverzeichnis besprochen haben , gibt es für jede Datei oder jedes Verzeichnis 32 Bytes an Informationen. Diese 32 Bytes sind wie folgt aufgeteilt:
Anzahl der Bytes |
Informationsbeschreibung |
8 Bytes |
Dateiname |
3 Bytes |
Verlängerung |
1 Byte |
Attribut |
10 Bytes |
Reserviert |
2 Bytes |
Uhrzeit, Erstellungsdatum oder letzte Aktualisierung |
2 Bytes |
Datum, erstellt oder zuletzt aktualisiert |
2 Bytes |
Cluster wird gestartet |
4 Bytes |
Dateigröße |
Wir stellen die Daten wieder her, indem wir die Informationen der Datei(en) aus dem Stammverzeichnis lesen , die Datei dann in den Zielpfad integrieren und die Datei wiederherstellen. Unser nächstes Programm führt die folgenden Schritte aus, um die Daten wiederherzustellen:
- Lesen Sie die Stammverzeichniseinträge und zeigen Sie sie mit allen Informationen wie Datei-/Verzeichnisname, Dateierweiterung und anfänglicher Clustergröße der Dateien in Bytes auf dem Bildschirm an.
- Lesen Sie die Datei- und Verzeichnisinformationen in den Unterverzeichnissen und zeigen Sie sie bei Bedarf an.
- Bestätigen Sie den wiederherzustellenden Dateinamen und fahren Sie mit der Wiederherstellung fort.
- Berechnen Sie die CHS-Informationen (Zylinder, Kopf und Sektor) für die angegebene wiederherzustellende Datei.
- Integrieren Sie die Daten der Datei aus dem Datenbereich der Festplatte und speichern Sie die wiederhergestellte Datei unter dem angegebenen Zieldateinamen im angegebenen Pfad.
Dieses Programm kümmert sich nicht darum, ob die Boot-Informationen der Diskette lesbar sind oder nicht. Daher können Sie auch gelöschte Daten von der beschädigten Diskette wiederherstellen . Sehen wir uns den Code des Programms an:
/* Programm zum Wiederherstellen der Daten von der Diskette durch Lesen der Dateiinformationen aus dem Stammverzeichnis */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
vorzeichenlose Ganzzahl);
vorzeichenlose Ganzzahl Spur=0, Kopf=1, Sektor=2;
Display_Information(Spur, Kopf, Sektor);
} /*Ende des Hauptteils */
void Display_Information(unsigned int track,
vorzeichenloser int-Kopf,
unsignierter int-Sektor)
{
void wiederherstellen(unsigned int *,unsigned int);
char buf[512]; // Puffer von 512 Bytes
verkohlen ch;
struct diskinfo_t finfo; //Struktur, wird von _bios_disk verwendet
unsigned int result,i,j, count=0; /* Vorzeichenlose Ganzzahlen
Definiert */
unsigned int Dateinummer; /* Ganzzahl ohne Vorzeichen
für Dateinummer */
Struktur
{
unsigned int name[8],ext[3]; /* Dateiname für DOS in 8.3
(Acht Punkt Drei) Format */
unsigned int attribute; // Datei-/Verzeichnisattribut
unsigned int start; // Startcluster der Datei
long unsigned int size; // Größe der Datei in Bytes
}root[32]; /* 32 Bytes Informationen über
Datei/Verzeichnis im Stammverzeichnis
Verzeichnis */
clrscr();
Tun
{
Dateinr.=0;
finfo.drive = 0x00; /* Laufwerksnummer für A: */
finfo.head = head; /* Festplattenkopfnummer */
finfo.track = Titel; /* Titelnummer */
finfo.sector= Sektor; /* Sektornummer */
finfo.nsectors=1; /* Sektorenanzahl */
finfo.buffer = buf; /* Datenpuffer */
Ergebnis = _bios_disk(_DISK_READ, &finfo); /* Lesen Sie die
Sektor */
if( (result & 0xff00) != 0) /* Wenn Lesefehler, Anzeige
Fehlermeldung und Beenden*/
{
printf("Lesefehler");
getch();
exit(0); // Zurück zu DOS
}
/// Informationsanzeige-Bildschirmformat \\\
clrscr();
gotoxy(9,1);
cprintf("ANZEIGEZYLINDER: %u, KOPF: %u, SEKTOR: %u",
Spur, Kopf, Sektor);
gotoxy(9,2);
cprintf("FNO NAME EXT ATTRIBUT STARTGRÖSSE");
gotoxy(7,3);
cprintf("-------------------------------------");
/* Immer nur ein Sektor. Jeder Datei-/DIR-Eintrag benötigt 32 Byte */
für (i=0;i<512;i+=32)
{
für (j=0;j<8;j++)
{
/// Suchen Sie den Datei-/Verzeichnisnamen \\\
root[Dateinr.].name[j]=buf[j+i];
}
für (j=8;j<11;j++)
{
/// Suche die Erweiterung \\\
root[Dateinr.].ext[j-8]=buf[i+j];
}
j = 11;
root[Dateinummer].attribute=buf[i+j]; /// Attribut
/// Cluster wird gestartet \\\
root[Dateinr.].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Größe berechnen \\\
root[Dateinummer].Größe =(long unsigned int)(0xff &
buf[31+i])*16*16*16*16*16*16*16*16;
root[Dateinummer].size+=(long unsigned int)(0xff &
buf[30+i])*16*16*16*16;
root[Dateinummer].size+=(long unsigned int)(0xff &
buf[29+i])*16*16;
root[Dateinummer].size+=(long unsigned int)(0xff &
buf[28+i]);
if((root[Dateinr.].start == 0) ||
(root[Dateinr.].attribute == 15))
weitermachen;
anders
{
gotoxy(8,i/32+4);
cprintf("%2u",file_no); /* Datei anzeigen
Nummer */
für (j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Datei anzeigen
Name */
}
für (j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Anzeige
Verlängerung */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Anzeige
Attribut */
wenn(root[Dateinr.].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Anzeigen, wenn Verzeichnisattribut */
}
anders
{
gotoxy(33,i/32+4);
cprintf("<DATEI>"); /* Der Eintrag ist von einer Datei */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Anzeige
Cluster wird gestartet */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* Größe der
Datei */
}
Dateinr.++;
}
gotoxy(10,
cprintf("Drücken Sie 'M': Um eine Liste weiterer Dateien anzuzeigen &quo
gotoxy(10,
cprintf("Drücken Sie 'R': Um eine Datei aus dem obigen
Liste&quo
ch=getc
Denken Sie daran, dass der Dateiname, der mit s (E5H) beginnt, bedeutet, dass die Datei gelöscht wurde und daher das erste Zeichen des Dateinamens durch s ersetzt wurde (siehe die Beschreibung des Stammverzeichnisses in den früheren Kapiteln).
Und die Ausgabe des Programms wird folgendermaßen angezeigt:
ANZEIGE ZYLINDER: 0, KOPF: 1, SEKTOR: 2
FNO NAME EXT ATTRIBUT STARTGRÖSSE
--------------------------------------------------------------------------
0 WE 32 <DATEI> 15 1800
1 s2_INFO C 32 <DATEI> 5 4700
2 THELP CFG 32 <DATEI> 2 22
3 THELP COM 32 <DATEI> 3 11072
4 TIMEIT CPP 32 <DATEI> 39 1186
5 TOUCH COM 32 <DATEI> 42 5124
6 TRY1 CPP 32 <DATEI> 53 1581
7 TURBOC CFG 32 <DATEI> 57 30
8 AA CPP 32 <DATEI> 58 260
9 ABC CPP 32 <DATEI> 59 1036
10 ASSIGN1 CPP 32 <DATEI> 62 4257
11 CH24_2 CPP 32 <DATEI> 71 834
12 sBSDISK1 C 32 <DATEI> 73 911
13 sH24_25 C 32 <DATEI> 75 594
14 sBSDISK C 32 <DATEI> 77 840
Drücken Sie „M“: Um eine Liste weiterer Dateien anzuzeigen.
Drücken Sie „R“: Um eine Datei aus der obigen Liste wiederherzustellen. R
|
ANZEIGE ZYLINDER: 0, KOPF: 1, SEKTOR: 2
FNO NAME EXT ATTRIBUT STARTGRÖSSE
---------------------------------------------------------------------------
0 WE 32 <DATEI> 15 1800
1 s2_INFO C 32 <DATEI> 5 4700
2 THELP CFG 32 <DATEI> 2 22
3 THELP COM 32 <DATEI> 3 11072
4 TIMEIT CPP 32 <DATEI> 39 1186
5 TOUCH COM 32 <DATEI> 42 5124
6 TRY1 CPP 32 <DATEI> 53 1581
7 TURBOC CFG 32 <DATEI> 57 30
8 AA CPP 32 <DATEI> 58 260
9 ABC CPP 32 <DATEI> 59 1036
10 ASSIGN1 CPP 32 <DATEI> 62 4257
11 CH24_2 CPP 32 <DATEI> 71 834
12 sBSDISK1 C 32 <DATEI> 73 911
13 sH24_25 C 32 <DATEI> 75 594
14 sBSDISK C 32 <DATEI> 77 840
Geben Sie die FNO der Datei ein, die Sie wiederherstellen möchten. 1
Sie möchten _2_INFO .C wiederherstellen.
Zylinder = 1, Kopf = 0, Sektor = 1. Integrieren........
Geben Sie Pfad und Dateinamen ein, um die Datei wiederherzustellen: c:\windows\desktop\H2_INFO.C.
Wiederherstellung abgeschlossen!!!
|
Anmerkungen zur Kodierung:
Die Funktion Display_Information dient zum Lesen der Datei- und Verzeichnisinformationen und des Stammverzeichnisses. In der Struktur lesen wir die 32 Bytes Informationen für jede Datei oder jedes Verzeichnis mit root[32].
Die vorzeichenlosen Integer-Arrays name[8] und ext[3] dienen für Datei- oder Verzeichnisnamen für DOS im Format 8.3 (Acht Punkt Drei). Ebenso dient ein Byte für das Attribut und zwei Byte für den Startcluster. long unsigned int size; dient zum Speichern der Dateigröße von vier Byte.
Die Funktion _bios_disk liest den Sektor, der durch die Struktur finfo angegeben ist, und der Status des Vorgangs wird im Ergebnis gespeichert.
Aus allen 512 Bytes, die von der Funktion _bios_disk gelesen werden , bis zum Ende des Stammverzeichnisbereichs , sammeln wir die Informationen zu den auf der Festplatte gespeicherten Dateien und Verzeichnissen und zeigen sie auf dem Bildschirm an.
Die Ganzzahl „file_no“ speichert die Nummer der Datei oder des Verzeichnisses in der Liste, beginnend bei 0. Im Allgemeinen beträgt die Größe des Stammverzeichnisses 14 Sektoren und das Stammverzeichnis beginnt bei 1,44 MB und einer 3½-Diskette im Allgemeinen mit Zylinder = 0, Kopf = 0 und Sektor = 2.
Wenn der Benutzer das Zeichen „M“ oder „m“ als Eingabe eingibt, werden die Informationen zum nächsten Sektor angezeigt. Wenn die Auswahl des Benutzers „R“ oder „r“ lautet, werden die Wiederherstellungsfunktionen aufgerufen. Die Codierung der Funktion recover() ist unten angegeben:
/* Funktion zum Starten der Wiederherstellung für die angegebene Datei */
void wiederherstellen(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Funktion zum Löschen einer Zeile auf dem Bildschirm */
/* Funktion zum Integrieren der angegebenen Datei */
void integrieren(lange unsigned int,unsigned int,
vorzeichenlose Ganzzahl, vorzeichenlose Ganzzahl);
vorzeichenlose int Dateinr.,i;
verkohlen ch;
vorzeichenlose Ganzzahl *loc;
vorzeichenloser int Zylinder, Kopf, Sektor;
vorzeichenloser int-Start;
lange vorzeichenlose Ganzzahlgröße;
clear_the_line(21); /* Lösche die Zeile Nummer 21 */
clear_the_line(22); /* Lösche die Zeile Nummer 22 */
clear_the_line(23); /* Lösche die Zeile Nummer 23 */
clear_the_line(24); /* Lösche die Zeile Nummer 24 */
gotoxy(10,21);
cprintf("Geben Sie die FNO der Datei ein, die Sie wiederherstellen möchten");
scanf("%u",&file_no); /* Die zu scannende Dateinummer ermitteln
Wiederhergestellt */
loc=(root+(Länge*Dateinr./2));
/* Bestätigen Sie den Namen der wiederherzustellenden Datei */
gotoxy(10,22);
cprintf("Sie möchten wiederherstellen");
für (i = 0; i < 8; i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* Dateiname */
}
gotoxy(38,22);
cprintf(".");
für (i = 0; i < 3; i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* Dateierweiterung */
}
start=*(loc+12);
/// Entschuldigung, Sie haben ein Verzeichnis ausgewählt \\\
wenn(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Ist ein Verzeichnis. Möchten Sie die
Inhalt dieses Verzeichnisses J/N");
ch=getch();
wenn(ch==27)
hauptsächlich();
wenn(ch=='y' || ch=='Y')
{
/* Geometrie berechnen */
berechnen(Start,&Zylinder,&Kopf,&Sektor);
/* Verzeichnisinhalt anzeigen */
Display_Information (Zylinder, Kopf, Sektor);
}
anders
/* Erneut nach Datei A fragen und Wiederherstellung fortsetzen */
wiederherstellen (Wurzel, Länge);
}
anders
{
Größe=*(loc+13);
/* Für CHS-Informationen berechnen */
berechnen(Start,&Zylinder,&Kopf,&Sektor);
/* Datei integrieren */
integrieren (Größe, Zylinder, Kopf, Sektor);
}
}
Anmerkungen zur Kodierung:
Die Funktion recover() dient zum Abrufen der Benutzereingabe zum Starten der Wiederherstellung. Die vom Benutzer zur Wiederherstellung der Datei eingegebene Dateinummer wird in file_no gespeichert.
Wenn die eingegebene Nummer für den Verzeichniseintrag gilt, zeigt Display_Information() den Inhalt dieses Verzeichnisses an, andernfalls werden der Dateiname und die Erweiterung der Dateinummer file_no auf dem Bildschirm angezeigt, um die wiederherzustellende Datei zu bestätigen.
Um die angegebene Datei wiederherzustellen , werden innerhalb der Funktion die Funktionen calculate() und integrate() aufgerufen. Die Codierung der Funktion calculate() ist unten angegeben:
/* Funktion zum Berechnen der CHS-Geometrie für die Wiederherstellung */
void berechnen(unsigned int start,unsigned int *Zylinder,
unsigned int *Kopf, unsigned int *Sektor)
{
vorzeichenlose int-Temp;
*Zylinder=0;
*Kopf=1;
*Sektor=14;
wenn(Start<5)
*Sektor=14+Start;
anders
{
temp= (Start-4)/18;
wenn(temp>0)
{
wenn(temp%2==0)
*Kopf=0;
anders
*Kopf=1;
*Zylinder+=1+Temperatur/2;
}
anders
{
*Kopf=0;
*Zylinder=1;
}
*Sektor=(Start-4)%18;
}
/// CHS der wiederherzustellenden Datei anzeigen \\\
gotoxy(10,23);
cprintf("Zylinder = %u, Kopf = %u, Sektor = %u",
*Zylinder,*Kopf,*Sektor);
}
Anmerkungen zur Kodierung:
Die Funktion calculate() berechnet die Zylinder-, Kopf- und Sektorinformationen für die wiederherzustellende Datei. Nach der Berechnung werden die Zylinder-, Kopf- und Sektornummern auf dem Bildschirm angezeigt.
Der Code für die Funktion integrate() ist unten angegeben:
/* Datei integrieren und die wiederhergestellte Datei im angegebenen Pfad und Dateinamen speichern */
void integrieren (lange unsignierte int Größe,
vorzeichenloser int-Zylinder,
vorzeichenloser int-Kopf,
unsignierter int-Sektor)
{
void lösche_die_zeile(unsigned int);
/* Funktion zum Überprüfen des Sektors auf Fehler */
int verifiziere_den_Sektor(unsigniertes int, unsigniertes int,
vorzeichenlose Ganzzahl);
int-Status;
char buf[512],*Dateiname_mit_Pfad;
Struktur diskinfo_t dinfo;
vorzeichenloses int-Ergebnis;
DATEI *fp;
vorzeichenlose Ganzzahl links, i;
vorzeichenlose Ganzzahl Sek.;
/* Geben Sie den Zielpfad und den Dateinamen zum Speichern der wiederhergestellten Datei ein */
gotoxy(2,24);
cprintf("Geben Sie Pfad und Dateinamen ein, um die Datei wiederherzustellen: ");
fflush(stdin);
bekommt(Dateiname_mit_Pfad);
fp=fopen(Dateiname_mit_Pfad,"wb");
/* Bei einem Fehler Fehlermeldung anzeigen und Eingabepfad und Dateinamen erneut abrufen */
wenn(fp==NULL)
{
gotoxy(5,25);
cprintf("Fehler beim Öffnen der Datei");
getch();
lösche_die_Leitung(24);
gotoxy(0,25);
cprintf(" ");
integrieren(Größe,Zylinder,Kopf,Sektor); /* Geben Sie die
Wieder Ziel */
}
/* Wenn alles in Ordnung ist, integrieren und schreiben */
gotoxy(50,23);
cprintf("Integrieren........");
links= Größe%512;
Sek. = Größe/512;
Sek++;
während (Sek. > 0)
{
dinfo.drive = 0x00; /* Laufwerksnummer für A: */
dinfo.head = head; /* Festplattenkopfnummer */
dinfo.track = Zylinder; /* Spurnummer */
dinfo.sector= Sektor; /* Sektornummer */
dinfo.nsectors=1; /* Sektorenanzahl */
dinfo.buffer = buf; /* Datenpuffer */
Ergebnis = _bios_disk(_DISK_READ, &dinfo);
/* Wenn beim Lesen eines Sektors ein Fehler auftritt */
wenn( (Ergebnis & 0xff00) != 0)
{
gotoxy(5,25);
cprintf("Lesefehler Zylinder %u, Kopf %u, Sektor %u",
Zylinder, Kopf, Sektor);
}
anders
{
wenn(sec==1)
{
für (i = 0; i < links; i++)
fputc(buf[i],fp); /* Schreibe das integrierte
Informationen zur Datei */
}
anders
{
fwrite(buf,512,1,fp);
}
Anmerkungen zur Kodierung:
Die Funktion integrate() ist das eigentliche Modul zur Wiederherstellung der vom Benutzer angegebenen Datei in diesem Wiederherstellungsprogramm .
Der Dateiname mit dem Zielpfad zum Speichern der wiederhergestellten Datei wird im Zeichenzeiger *Dateiname_mit_Pfad gespeichert. Wenn beim Öffnen der Zieldatei ein Fehler auftritt, wird eine Fehlermeldung angezeigt und der Benutzer wird erneut aufgefordert, das Ziel einzugeben.
Die Funktion _bios_disk(_DISK_READ, &dinfo); liest die Daten der Datei Sektor für Sektor aus dem durch die Struktur dinfo spezifizierten und im Datenpuffer buf gespeicherten Datenbereich der Platte. Diese 512 Byte großen Daten werden in die Zieldatei geschrieben. Dies wird so lange wiederholt, bis die komplette Datei integriert ist.
Die Funktion status=verify_the_sector (Zylinder, Kopf, Sektor); überprüft den zu lesenden Sektor. Wenn der Status = 10 ist, handelt es sich um einen fehlerhaften (0xA) Sektor. Die Kodierung der Funktion ist wie folgt:
/// Sektor überprüfen. (Hier werden keine Daten übertragen) \\\
int verifiziere_den_Sektor(unsigniertes int c,unsigniertes int h,unsigniertes int s)
{
int-Status;
char *buf;
Gewerkschaftsreglemente rein, raus;
Struktur SREGS sg;
in.h.ah = 0x04; /* Funktionsnummer */
in.h.al = 1; /* Anzahl der zu überprüfenden Sektoren*/
in.h.dl = 0x00; /* Datenträgernummer für A: */
in.h.ch = c; /* Zylindernummer */
Zoll.h.dh = h; /* Kopfnummer */
in.h.cl = s; /* Sektornummer */
in.x.bx = FP_OFF(buf);/* Versatz */
sg.es = FP_SEG(buf); /* Segment */
int86x(0x13,&in,&out,&sg); /* Funktion 4H aufrufen
ab INT 13H */
wenn(out.x.cflag)
{
Status=aus.h.ah;
}
Rückkehr(Status);
}
Kodierungskommentare:
Die Funktion „verify_the_sector()“ überprüft den Sektor, der von der Funktion „_bios_disk()“ gelesen wird, und gibt den Status des Vorgangs zurück. Die Funktion verwendet INT 13H und Funktion 4H, um den Sektor zu überprüfen.
*buf – Datenpuffer, 0x04 – Funktionsnummer angegeben durch in.h.ah = 0x04; und in.h.al = 1; gibt an, dass immer nur ein Sektor geprüft werden soll. in.h.dl = 0x00; wird für das Diskettenlaufwerk Nummer A: verwendet, c, h und s sind Zylinder-, Kopf- und Sektornummern .
Die Funktion int86x() wird verwendet, um INT 13H (Funktion 4H) mit Segmentregisterwerten aufzurufen . Der Vorgangsstatus wird als ganzzahliger Status zurückgegeben.
Die Funktion clear_the_line() löscht die angegebene Zeile auf dem Bildschirm. Die Funktionskodierung ist wie folgt:
/* Funktion zum Löschen einer Zeile auf dem Bildschirm für die angegebene Zeilennummer */
void clear_the_line(Zeichenfolge mit vorzeichenloser Ganzzahl)
{
Spalte mit vorzeichenlosen Ganzzahlen;
/* Es gibt 80 Spalten in einer Zeile */
für (Spalte = 1; Spalte <= 80; Spalte ++)
{
gotoxy(Spalte,Zeile);
cprintf(" "); /* Löschen mit " " */
}
}
Kodierungskommentare:
Die Funktion wird verwendet, um die angegebene Zeile auf dem Bildschirm zu löschen . Die Funktion wird mit der Zeilennummer aufgerufen, die vom Bildschirm gelöscht werden soll.