장 – 10
손상된 플로피에서 데이터 복구
손상된 플로피에서 데이터 복구
플로피는 데이터 저장에 있어 가장 신뢰할 수 없는 소스 중 하나입니다. 컴퓨터 시스템을 사용하는 조직에 가서 플로피 디스크로 인해 발생하는 문제에 대해 직원들에게 물어보면 조직의 직원이 플로피에 몇 가지 중요한 데이터를 가지고 있었는데 지금은 플로피가 그렇지 않다는 문제를 매우 일반적으로 듣게 될 것입니다. 컴퓨터에서 읽을 수 있고 다음과 같은 메시지가 표시됩니다.
“디스크를 읽을 수 없습니다.
“트랙 0 불량”
“잘못된 드라이브 또는 용량”
“디스크가 포맷되지 않았습니다. 지금 포맷하시겠습니까?”
이것은 컴퓨터 시스템과 플로피를 사용하는 조직의 일상적인 문제입니다. 손상된 플로피 디스크에서 손실된 것으로 보이는 데이터에 대해 백업이 수행되지 않았거나 사용할 수 있는 백업이 없음을 알게 되면 문제가 심각해집니다.
가장 큰 문제는 중요한 정보를 플로피에 백업하거나 바이러스 공격을 극복하기 위한 바이러스 백신 프로그램의 복구 디스크나 부트 레코드 또는 기타 백업(여러 가능성이 있을 수 있음)을 플로피에 만들 때 발생합니다. 플로피에서 백업을 재사용하려고 할 때 읽기 오류가 발생합니다.
이러한 상태에서 중요한 정보와 데이터를 잃게 되거나 경우에 따라 컴퓨터 부팅 정보 및 바이러스 공격 구조를 위한 백업 및 복구 프로그램이 부족하다고 느끼는 경우도 있습니다. 프로그램 등, 현재 컴퓨터에서 읽을 수 없는 플로피에 저장된 정보 부족으로 인해 OS 충돌이 발생하여 데이터가 크게 손실될 수 있습니다.
이러한 경우 컴퓨터 시스템에서 불량이라고 선언한 플로피에서 데이터를 복구하는 것이 가장 중요한 요구 사항이 됩니다.
플로피를 읽을 수 없는 이유
플로피가 이러한 유형의 오류 메시지를 표시하게 하는 가장 일반적인 문제는 플로피의 DOS 부트 레코드(DBR) 손상으로 컴퓨터가 플로피의 논리적 식별을 알 수 있도록 도와줍니다.
DBR은 트랙 0, 헤드 0 및 섹터 1에 저장되고 다음과 같은 플로피에 대한 중요한 정보를 포함하는 작은 프로그램입니다.
- 섹터당 바이트 수
- 클러스터당 섹터
- FAT 수
- 최대 루트 디렉토리 수 등
플로피에는 논리 파티션 시스템이 없으므로 플로피에서 사용할 수 있는 MBR이 없습니다. Floppy의 첫 번째 섹터는 DBR을 보유합니다. 이것은 하드디스크의 논리적 구조를 플로피와 비교하는 가장 큰 차이점이기도 합니다.
디스크 편집 프로그램의 도움으로 플로피의 부트 섹터 정보를 읽으면 다음 그림과 같은 정보가 표시됩니다.
다음 그림은 1.44MB, 3½ 인치 플로피.
이 정보가 손상되거나 읽을 수 없게 되면 플로피 디스크에서 이러한 읽기 오류 메시지가 나타납니다. 디스크의 첫 번째 섹터가 물리적 또는 논리적으로 손상되었기 때문일 수 있습니다.
논리적 손상은 플로피의 첫 번째 섹터의 정보가 변경된 경우, 논리적 불량 섹터 또는 DBR이 발생하는 경우를 포함합니다. strong> 플로피가 다른 이유로 손상되었습니다.
물리적 손상은 첫 번째 섹터에 물리적 불량 섹터(섹터 1이 물리적으로 손상됨을 의미)가 있는 경우 발생합니다. 플로피 디스크. 플로피의 트랙 0에 불량 섹터가 두 개 이상 있으면 문제가 더 심각해집니다.
복구 방법
손상의 두 가지 원인을 모두 배웠으므로 이제 문제를 이해할 수 있기를 바랍니다. 논리적 손상에서 데이터를 복구하는 것은 그리 어려운 일이 아니지만 물리적 손상에서 복구하려면 약간 더 노력해야 합니다.
방법 – 1
새 플로피의 부팅 이미지 저장
문제가 논리적이라면 이제 데이터를 복구할 수 있는 방법을 알게 되었습니다. 우리가 해야 할 일은 같은 크기와 용량의 다른 플로피에서 적절한 부트 레코드를 가져와 읽을 수 없는 플로피의 첫 번째 섹터에 붙여 넣는 것입니다. 잘못된 부트 레코드로 인해 문제가 생성되었지만 지금은 작동합니다.
이 절차에는 읽을 수 없는 플로피에서 데이터를 복구하는 두 가지 단계가 있습니다.
- 좋은 플로피의 DOS 부트 레코드 이미지 만들기
- 읽을 수 없는 플로피의 첫 번째 섹터에 부팅 이미지 붙여넣기
좋은 플로피의 DOS 부트 레코드 이미지 만들기
새 플로피의 부트 레코드 이미지를 저장하려면 프로그램은 다음 세 가지 작업을 수행해야 합니다.
- 좋은 플로피의 처음 512바이트를 정확히 읽습니다.
- 성공적인 읽기 작업 확인(가장 중요)
- 이 512바이트를 지정된 파일 이름 및 대상 경로에 저장
플로피의 섹터는 512바이트로 섹터의 정확한 이미지를 복사해야 합니다. 플로피에 적용된 모든 연산의 경우 성공 여부를 확인하는 가장 중요하고 필요한 단계입니다.
올바른 새 플로피 디스크라도 초기화 문제가 있을 수 있습니다. 그렇기 때문에 대부분의 경우 플로피 디스크에서 작업을 수행할 때 디스크 초기화 작업(INT 13H의 기능 00 H)을 사용한 프로그래밍에서 우선 플로피 디스크의 초기화를 먼저 수행합니다.
초기화 후에도 최근에 삽입한 플로피 디스크나 변경된 플로피 디스크로 인해 읽기 오류가 발생하면 프로그램을 다시 실행하는 것이 좋습니다. 이번에는 대부분 작동할 수 있습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 진행 방식을 살펴보겠습니다.
/* 부팅 이미지를 새 플로피 디스크의 파일에 저장 */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store Boot Image");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
while(count<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff );
count++;
}
fclose(fp);
gotoxy(10,14);cprintf("Disk read from Floppy disk drive
: successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n", result);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
프로그램 코딩에 대한 의견:
앞에서 설명한 프로그램 코딩에서 기본적으로 다음 작업을 단계별로 진행합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보가 포함된 diskinfo_t 구조를 가리킵니다.
- 디스크의 첫 번째 섹터를 읽고 싶기 때문에 섹터의 위치는 다음과 같습니다.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- 사용자가 지정한 파일 이름과 경로의 파일 스트림을 열어 정확한 512바이트의 부팅 이미지 정보를 저장합니다. 파일 이름과 경로는 문자 배열 fname에 저장됩니다.
- 인터럽트 13H(기능 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 기능 00 H를 가리키고 regs.h.dl = 0x00은 a: 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)은 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_READ, &dinfo) 플로피 디스크의 지정된 섹터를 읽습니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생한 경우 화면에 오류 메시지를 표시하는 데 사용되는 결과에 저장됩니다.
읽을 수 없는 플로피의 첫 번째 섹터에 부팅 이미지 붙여넣기
파일의 부팅 이미지를 읽을 수 없는 플로피의 첫 번째 섹터에 붙여넣으려면 프로그램에서 다음 세 가지 주요 작업을 수행해야 합니다.
- 이전에 저장한 파일에서 새 플로피의 부트 레코드의 정확한 512바이트 정보를 읽습니다.
- 현재 읽을 수 없는 플로피의 첫 번째 섹터에 이 정보를 씁니다.
- 쓰기 작업이 성공적으로 완료되었는지 확인합니다(가장 중요).
플로피의 섹터가 512바이트이기 때문에 섹터에 정확한 부팅 이미지를 붙여넣어야 합니다. 플로피에 적용된 모든 연산의 경우 성공 여부를 확인하는 가장 중요하고 필요한 단계입니다.
작업 중 플로피 디스크에 초기화 문제가 있을 수 있으므로 디스크 시스템을 재설정하여 디스크를 초기화해야 합니다(INT 13H의 00H 기능 사용).
초기화 후에도 최근에 삽입한 플로피 디스크나 변경된 플로피 디스크로 인해 읽기 오류가 발생하면 프로그램을 다시 실행하는 것이 좋습니다. 이번에는 대부분 작동할 수 있습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 진행 방식을 살펴보겠습니다.
/* 읽을 수 없는 플로피에 부팅 이미지 로드 */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
char dbuf[512];
FILE *fp;
clrscr();
gotoxy(5,3);cprintf("Enter The File Name And Path, In Which Boot image of Floppy Is Stored");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"rb");
if((fp=fopen(fname,"rb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be Opened");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to Recover Floppy disk drive :\n");
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
while(count<512)
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Successful!!! I Hope Floppy May
Work Now.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
프로그램 코딩에 대한 의견:
앞서 주어진 프로그램 코딩에서 기본적으로 우리는 다음 작업을 단계별로 진행하고 있습니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보가 포함된 diskinfo_t 구조를 가리킵니다.
- 디스크의 첫 번째 섹터에 정보를 기록하므로 섹터의 위치는 다음과 같습니다.
- 이전 프로그램에서 새 플로피 512바이트의 부팅 이미지 정보가 저장된 파일을 엽니다. 파일 이름과 경로는 문자 배열 fname에 저장됩니다.
- 인터럽트 13H(기능 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 기능 00 H를 가리키고 regs.h.dl = 0x00은 a: 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)은 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_WRITE, &dinfo)는 지정된 파일의 부팅 정보를 플로피 디스크의 첫 번째(지정된) 섹터에 씁니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생한 경우 화면에 오류 메시지를 표시하는 데 사용되는 결과에 저장됩니다.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
단일 프로그램으로 해보자
이제 이러한 유형의 플로피 디스크에서 데이터 복구의 개념을 이해하셨기를 바랍니다. 그런 다음 이전에 논의한 두 프로그램의 도움으로 얻은 것과 동일한 결과를 제공하는 단일 프로그램을 상상해 보겠습니다.
최근 논의된 프로그램으로 다음 작업을 수행했습니다.
- 좋은 플로피 디스크의 부팅 정보를 파일로 저장
- 이 정보를 현재 읽을 수 없는 플로피 플로피의 첫 번째 섹터에 붙여넣으면 부팅 이미지를 저장하는 데 사용했던 파일이 두 프로그램의 작업을 연결하는 중간 다리 역할을 했습니다. 그러나 프로그램 코딩 자체에서 이 부팅 정보를 정의하면 파일을 만들 필요가 없고 파일에서 플로피의 부팅 정보를 읽을 필요도 없습니다.
다음 프로그램에서 읽을 수 없는 플로피 디스크의 첫 번째 섹터에 기록해야 하는 내용에 대해 프로그램에 지시하므로 동일한 작업을 수행하는 두 개의 다른 프로그램을 피할 수 있고 데이터를 복구할 수 있습니다. strong> 새로운 단일 프로그램에서 이전과 같은 방식으로
따라서 프로그램은 코딩을 줄이고 간단해지며 파일 읽기, 쓰기 또는 생성 오류가 발생할 확률을 줄일 수 있습니다. 우리는 이 프로그램에서 다음 네 가지 중요한 작업을 수행하고 있습니다.
dbuf[512]의 512바이트 16진수 정보를 보고 프로그램을 작성하고 이해하는 것이 어렵다고 생각하지 마십시오. 나중에 프로그램 코딩을 위해 이 정보를 작성하는 쉬운 방법에 대해 논의할 것입니다.
- 현재 읽을 수 없는 플로피의 첫 번째 섹터에 기록될 DOS 부트 레코드 정보를 16진수 시스템으로 정의합니다.
- 플로피 디스크를 초기화하기 위해 디스크 시스템을 재설정합니다(INT 13H, 기능 00H).
- 플로피의 첫 번째 섹터에 DOS 부트 레코드 쓰기
- 작업이 성공적으로 완료되었는지 확인하고 오류가 발생하면 오류가 발생합니다.
프로그램을 살펴보겠습니다.
/* 읽을 수 없는 플로피 디스크에 기본 부팅 이미지를 로드하는 단일 프로그램 */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* 플로피 디스크 드라이브에 로드할 부팅 이미지 */
static char dbuf[512]=
{
0xEB,0x3E,0x90,0x2B,0x29,0x6E, 0x70,0x32,0x49,0x48,0x43,0x0,0x2 ,0x1 ,0x1 ,0x0,
0x2,0xE0,0x0,0x40,0xB,0xF0,0x9,0x0,0x12, 0x0 ,0x2 ,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x29, 0x24,0x3B,0xDB, 0x16,0x4E, 0x4F, 0x20, 0x4E,0x41,0x4D,0x45,
0x20, 0x20, 0x20,0x20,0x46,0x41, 0x54,0x31, 0x32,0x20,0x20, 0x20,0xF1,0x7D, 0xFA,
0x33, 0xC9,0x8E,0xD1, 0xBC,0xFC,0x7B, 0x16,0x7 ,0xBD,0x78,0x0 ,0xC5,0x76,0x0,
0x1E,0x56,0x16,0x55, 0xBF,0x22,0x5 ,0x89,0x7E,0x0 ,0x89,0x4E,0x2 ,0xB1,0xB,0xFC,
0xF3,0xA4,0x6 ,0x1F,0xBD,0x0,0x7C ,0xC6,0x45,0xFE,0xF,0x8B, 0x46,0x18,0x88,0x45,
0xF9,0xFB,0x38,0x66, 0x24,0x7C,0x4,0xCD,0x13, 0x72,0x3C,0x8A,
0x46,0x10,0x98,0xF7,
0x66,0x16,0x3, 0x46,0x1C,0x13,0x56, 0x1E,0x3 ,0x46,0xE,0x13,
0xD1,0x50,0x52,0x89,
0x46,0xFC,0x89, 0x56,0xFE,0xB8,0x20,0x0, 0x8B,0x76,0x11,0xF7,
0xE6,0x8B,0x5E,0xB ,
0x3 ,0xC3,0x48,0xF7,0xF3,0x1,0x46,0xFC, 0x11,0x4E,0xFE,0x5A,
0x58,0xBB,0x0 ,0x7 ,
0x8B,0xFB,0xB1,0x1, 0xE8,0x94,0x0 ,0x72,0x47,0x38,0x2D,0x74, 0x19,0xB1,0xB,0x56,
0x8B,0x76,0x3E, 0xF3,0xA6,0x5E,0x74,0x4A,0x4E, 0x74,0xB,0x3 , 0xF9,0x83, 0xC7, 0x15,
0x3B, 0xFB,0x72,0xE5,0xEB,0xD7,0x2B, 0xC9,0xB8,0xD8, 0x7D, 0x87, 0x46, 0x3E,0x3C,
0xD8,0x75,0x99, 0xBE,0x80,0x7D,0xAC, 0x98,0x3,0xF0,0xAC,0x84 ,0xC0,0x74,0x17,0x3C,
0xFF,0x74,0x9 ,0xB4,0xE ,0xBB,0x7 ,0x0,0xCD,0x10,0xEB, 0xEE,0xBE,0x83,0x7D, 0xEB,
0xE5, 0xBE, 0x81,0x7D, 0xEB,0xE0, 0x33,0xC0,0xCD,0x16,0x5E,0x1F,0x8F,0x4 ,0x8F,0x44,
0x2,0xCD, 0x19,0xBE,0x82,0x7D,0x8B,0x7D,0xF, 0x83,0xFF,0x2,0 x72,0xC8, 0x8B,0xC7,0x48,
0x48,0x8A,0x4E,0xD,0xF7,0xE1,0x3 ,0x46,0xFC, 0x13,0x56,0xFE,0xBB,0x0 ,0x7 ,0x53,0xB1,0x4 ,
0xE8,0x16,0x0, 0x5B,0x72,0xC8, 0x81,0x3F,0x4D,0x5A, 0x75,0xA7,0x81,0xBF, 0x0,0x2 ,0x42,0x4A,
0x75,0x9F,0xEA,0x0 ,0x2 ,0x70,0x0,0x50,0x52, 0x51, 0x91, 0x92, 0x33, 0xD2,0xF7,0x76,0x18,0x91,
0xF7,0x76, 0x18,0x42, 0x87, 0xCA, 0xF7, 0x76,0x1A,0x8A,0xF2,0x8A,0x56, 0x24,0x8A,0xE8,
0xD0, 0xCC,0xD0,0xCC,0xA, 0xCC,0xB8,0x1,0x2, 0xCD,0x13,0x59,0x5A, 0x58, 0x72,0x9,0x40,
0x75,0x1,0x42,0x3, 0x5E,0xB,0xE2,0xCC,0xC3,0x3 ,0x18 ,0x1 ,0x27,0xD ,0xA,0x49, 0x6E,
0x76,0x61,0x6C,0x69,0x64,0x20, 0x73, 0x79, 0x73, 0x74, 0x65,0x6D,0x20,0x64,0x69,0x73,
0x6B,0xFF,0xD ,0xA,0x44,0x69, 0x73,0x6B,0x20, 0x49,0x2F, 0x4F,0x20, 0x65,0x72, 0x72,0x6F,
0x72,0xFF,0xD ,0xA,0x52, 0x65,0x70,0x6C,0x61,0x63, 0x65,0x20,
0x74,0x68, 0x65, 0x20,
0x64, 0x69,0x73, 0x6B,0x2C,0x20,0x61, 0x6E,0x64,0x20,0x74, 0x68, 0x65, 0x6E, 0x20,0x70,
0x72,0x65, 0x73,0x73, 0x20,0x61, 0x6E,0x79,0x20,0x6B,0x65,0x79,0xD,0xA, 0x0,0x49,0x4F,
0x20,0x20,0x20,0x20, 0x20,0x20,0x53,0x59,0x53,0x4D, 0x53, 0x44, 0x4F, 0x53,0x20,0x20,
0x20,0x53, 0x59,0x53, 0x80,0x1,0x0 ,0x57,0x49, 0x4E,0x42, 0x4F,0x4F,0x54,0x20,0x53, 0x59
,0x53,0x0,0x0,0x55,0xAA};
clrscr();
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk Write Status :successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-
protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13 extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
이 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 진행합니다.
- 정적 문자 데이터 버퍼 dbuf[512]는 읽을 수 없는 플로피의 첫 번째 섹터에 기록되는 512바이트의 정보를 16진법으로 제공합니다. dbuf[512]는 플로피의 첫 번째 섹터에 어떤 정보가 기록될 것인지 컴퓨터에 알려줍니다. (다음 프로그램 참조)
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보가 포함된 diskinfo_t 구조를 가리킵니다.
- 디스크의 첫 번째 섹터에 정보를 기록하므로 섹터의 위치는 다음과 같습니다.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- 인터럽트 13H(기능 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 기능 00 H를 가리키고 regs.h.dl = 0x00은 a: 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)은 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_WRITE, &dinfo)는 지정된 파일의 부팅 정보를 플로피 디스크의 첫 번째(지정된) 섹터에 씁니다.
반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생한 경우 화면에 오류 메시지를 표시하는 데 사용되는 결과에 저장됩니다.
이전 프로그램에서 사용하기 위해 부팅 이미지를 HEXADECIMAL 문자로 저장
최근에 논의한 프로그램의 오류 없이 플로피 DOS 부트 레코드의 512개 문자를 모두 16진수 시스템으로 수동으로 작성하는 것은 매우 어려운 작업이 될 것입니다. 우리가 그것을 정확하게 쓸 수 있다면 이것을 하는 것보다 어렵고 시간이 걸릴 것입니다. 데이터 버퍼 dbuf[512]에 대한 데이터를 파일에 저장하기 위해 약간 까다로운 방법을 사용합시다.
C 프로그래밍에서 16진수 문자는 0x로 표시되므로 16진수 문자가 A9 H이면 C 프로그램에서 이를 0xA9로 작성합니다. 다음 프로그램도 마찬가지입니다. 이전 프로그램에서 작성해야 하는 데이터를 데이터 버퍼 dbuf[512]의 데이터로 저장합니다.
해야 할 일은 새 플로피를 가져와서 DBR의 이미지를 만들고 지정된 대상 파일에서 이 프로그램의 출력을 복사하고 이 데이터를 프로그램에 붙여넣는 것입니다. 필요한 경우 일부 서식을 지정합니다. 작동 방식을 살펴보겠습니다.
/* 플로피 디스크의 부팅 이미지를 HEX 문자로 만드는 프로그램 */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result,i;
int count=0;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store The Boot Image in HEX System");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("Attempting to read from Floppy
disk drive :\n");
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk read from Floppy disk drive :
successful.\n");
while(count<512)
{
fprintf(fp,"0x%X, ",dbuf[count] & 0xff );
count++;
}
fclose(fp);
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
}
return 0;
}
프로그램 코딩에 대한 의견:
따라서 데이터는 지정된 파일에 저장됩니다. 데이터를 프로그램에 복사하고 필요한 서식을 지정하기만 하면 됩니다. 절차를 진행하는 동안 다음 팁을 절대 잊어서는 안 됩니다.
- 프로그램이 성공적으로 작동하고 대상 파일에 저장된 데이터가 적절한지 확인하십시오.
- 예상되는 오류가 발생하는지 작업을 통해 확인해야 합니다.
- 부트 섹터를 읽기 전에 프로그램과 함께 플로피 디스크를 초기화해야 합니다. 이를 위해 INT 13H의 기능 00H를 사용할 수 있습니다.
방법 – 2
방법 – 1이 작동하지 않습니까?
방법 – 1이 작동하지 않고 읽을 수 없는 디스크가 프로그램이 첫 번째 섹터에 부팅 정보를 다시 쓰는 것을 허용하지 않으면 이 두 번째 방법을 시도해야 합니다. First Method 실패의 원인은 플로피 디스크의 첫 번째 섹터의 물리적 손상일 수 있습니다.
이 두 번째 방법에서는 읽을 수 없는 플로피 표면의 모든 데이터를 일시적으로 단일 파일에 복사한 다음 이 이미지를 다른 양호한 디스크 표면에 직접 붙여넣을 것입니다.
절차에는 다음 두 가지 중요한 단계가 포함됩니다.
- 섹터별 플로피 미디어 표면의 모든 데이터를 하나의 파일에 임시로 복사합니다.
- 파일에 저장된 데이터를 그대로 새 플로피에 동일한 섹터에 붙여넣습니다.
미디어 표면의 모든 데이터를 단일 파일로 복사
플로피 미디어 표면의 모든 데이터를 저장하려면 프로그램은 다음 세 가지 작업을 수행해야 합니다.
- INT 13H의 00H 기능을 사용하여 디스크를 올바르게 초기화하십시오.
- 표면의 섹터별 정보를 읽고 단일 파일에 저장합니다.
- 성공적인 읽기 작업 확인(가장 중요)
플로피 디스크의 초기화 문제로 인해 읽기 실패 메시지가 많이 발생하는 것은 매우 흔한 일입니다. 그렇기 때문에 프로그래밍의 도움으로 읽기 쓰기 작업 전에 디스크를 초기화해야 합니다.
플로피에 어떤 종류의 연산을 가할 경우 성공 여부를 확인하는 가장 중요하고 필요한 단계입니다.
초기화 후에도 최근에 삽입한 플로피 디스크나 변경된 플로피 디스크로 인해 읽기 오류가 발생하면 프로그램을 다시 실행하는 것이 좋습니다. 이번에는 대부분 작동할 수 있습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 어떻게 진행되는지 봅시다:
/* 플로피 디스크의 물리적 표면 데이터를 파일로 저장하는 프로그램 */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File,
Press any Key To EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result,head,track,sector);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track,head,sector);
}
}
}
}
프로그램 코딩에 대한 의견:
앞서 주어진 프로그램 코딩에서 기본적으로 우리는 다음 작업을 단계별로 진행하고 있습니다.
- 문자 배열 파일 이름[80]은 데이터를 임시로 저장할 파일의 사용자 정의 경로와 파일 이름을 저장합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보가 포함된 diskinfo_t 구조를 가리킵니다.
- 인터럽트 13H(기능 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 기능 00 H를 가리키고 regs.h.dl = 0x00은 a: 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)은 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- 디스크 표면의 모든 정보를 읽을 것이기 때문에 _bios_disk의 매개변수는 다음과 같습니다.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_READ, &dinfo) dinfo로 지정된 섹터에서 플로피 디스크의 물리적 표면에서 데이터를 읽습니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생한 경우 화면에 오류 메시지를 표시하는 데 사용되는 결과에 저장됩니다.
플로피 디스크에 80개의 트랙(0~79), 2개의 면 또는 헤드(헤드 0 및 헤드 1), 각 트랙이 있기 때문에 플로피 디스크 데이터의 이미지를 보유하는 파일의 크기는 정확히 1,474,560바이트여야 함을 항상 기억하십시오. 18개의 섹터가 있고 각 섹터는 512바이트의 데이터를 보유하므로
Total bytes = (Number of tracks) * (Number of Heads) *
(Number of Sectors per Track) * 512
= 80*2*18*512
= 1,474,560 Bytes
따라서 플로피 디스크의 어느 섹터에서나 읽는 데 오류가 있으면 파일 크기가 1,474,560바이트에서 변경되어 전체 정보가 대상 디스크에서 완전히 또는 부분적으로 사용되지 않게 됩니다. 이 파일에서 섹터별로 디스크 이미지를 기록합니다.
할당 단위에 할당된 섹터 범위 내에서 컴퓨터가 플로피 디스크의 미디어 표면에 있는 모든 파일의 정보를 읽기 때문입니다. 이제 파일 데이터의 섹터가 변경되면 전체 파일 정보가 변경됩니다.
섹터 읽기 오류에 대한 해결책을 모색 중
불량하거나 읽을 수 없는 플로피의 경우 표면에 불량한 영역이 있어서 디스크 표면에서 정보를 읽을 수 없을 수도 있습니다.
이 경우 이미지 파일의 크기가 1,474,560바이트와 다르기 때문에 이 상태에서 이 섹터의 정보는 건너뛰고 플로피 이미지는 다른 섹터에서도 왜곡됩니다.
이미지 파일의 크기를 유지하고 대상 디스크의 정확한 섹터 위치에 대한 나머지 정보를 붙여넣기 위해 512바이트의 원본 데이터를 대신하여 몇 가지 다른 정보를 작성합니다. 나머지 정보를 저장할 수 있지만 이러한 경우 복구는 부분 복구가 될 수 있습니다.
시스템이 소스 플로피의 첫 번째 섹터를 읽지 못하는 경우 이미지를 대상 플로피에 붙여넣은 후 앞에서 설명한 프로그램을 실행하여 플로피의 DOS 부트 레코드를 다시 작성해야 합니다.
프로그래밍을 통해 이를 수행하는 방법을 살펴보겠습니다.
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
/*Bad Sector의 공간을 채우기 위한 512 바이트의 정보 */
/// 512바이트의 공간을 채우기 위해 512개의 0을 사용했습니다. \\\
static char dbuf2[512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result, head, track, sector);
/* 섹터를 읽을 수 없는 경우 dbuf2가 512바이트를 차지합니다. */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
프로그램 코딩에 대한 의견:
프로그램의 코딩은 디스크 읽기 작업 동안 불량 섹터에 의해 발생하는 오류를 처리하기 위해 사용하는 데이터 버퍼 dbuf2[512]를 제외하고 모든 단계는 이전 프로그램과 동일합니다. > 이미지 파일의 크기를 유지합니다.
이렇게 하면 불량 섹터에서 읽지 못한 정보의 공간을 채우고 이제 512바이트의 의사 정보를 쓰고 있습니다. 디스크 이미지의 정확성을 유지할 수 있습니다.
파일의 데이터를 새 플로피의 물리적 표면에 붙여넣기:
이 단계에서는 이전 프로그램에 의해 파일에 저장된 데이터를 파일에 복사한 것과 동일한 방식으로 새 플로피의 물리적 표면에 섹터별로 붙여넣습니다.
프로그램은 다음과 같은 주요 단계로 진행됩니다.
- 읽을 수 없는 플로피의 표면 데이터를 임시로 저장한 파일을 엽니다.
- INT 13H의 00H 리셋 기능으로 디스크 시스템을 올바르게 초기화합니다.
- 파일에서 새 플로피의 섹터에 대한 정보를 씁니다.
- 쓰기 상태를 동시에 표시하여 오류 발생을 찾거나 방지합니다.
프로그램 소스 코드는 아래와 같습니다. 작동 방식을 살펴보겠습니다.
/* 이전 프로그램에서 만든 파일에서 새 플로피 표면의 섹터에 데이터를 쓰는 프로그램 */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
int count =0;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *fp;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((fp=fopen(filename,"rb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(1);
}
/// 디스크 시스템 초기화 \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
count =0;
while(count<512 )
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector;/* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result= _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
printf("Successful write on Track = %d, Head = %d,
Sector = %d.\n", track, head, sector);
else
printf("Cannot read drive A, status = 0x%02x\n",
result);
}
}
}
}
프로그램 코딩에 대한 의견:
앞에서 제시한 프로그램 코딩에서 기본적으로 다음 작업을 단계별로 진행하고 있습니다.
- 문자 배열 파일 이름[80]은 읽을 수 없는 플로피 표면의 데이터를 임시로 저장한 파일의 경로와 파일 이름을 보유합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보가 포함된 diskinfo_t 구조를 가리킵니다.
- 인터럽트 13H(기능 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 기능 00 H를 가리키고 regs.h.dl = 0x00은 a: 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)은 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- 디스크 표면의 섹터에 직접 정보를 기록할 예정이므로 _bios_disk의 매개변수는 다음과 같습니다.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_WRITE, &dinfo)는 dinfo로 지정된 플로피 디스크의 물리적 표면 섹터에 데이터를 씁니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생한 경우 화면에 오류 메시지를 표시하는 데 사용되는 결과에 저장됩니다.
메소드 이후의 경우 – 2 새 플로피가 작동하지 않으면 방법을 추가로 적용할 수 있습니다. – 방법 중에 대상 디스크로 사용한 새 플로피의 1 – 2.
이뿐만 아니라 적중 횟수와 시도 횟수도 디스크 손상에 따라 달라질 수 있습니다. 하지만 만족스러운 결과를 얻지 못하더라도 걱정할 필요는 없습니다.
파일별 복구를 시도하거나 다음에 배울 더 많은 팁을 시도할 수 있습니다. 여기서 우리는 데이터를 복구하기 위한 프로그래밍에서 루트 디렉터리에서 파일 정보를 수집하는 아이디어를 구현합니다.
삭제되거나 손실된 데이터에 대한 논리적 복구 고려:
복구를 위해 이 장에서 논의한 모든 이전 사례는 DBR이 손상되고 섹터만 손상될 것으로 예상되는 경우 데이터를 복구하는 것이었습니다. 트랙 0에서 FAT1, FAT2 및 루트 디렉토리를 읽을 수 있습니다.
하지만 문제가 FAT의 손상으로 인해 발생했거나 디스크에서 데이터가 삭제된 또는 해당 정보를 읽어 직접 데이터를 복구하려는 경우 루트 디렉토리에서 파일 이름, 시작 클러스터, 파일 크기와 같은 정보를 읽어야 합니다. , 속성 등 루트 디렉토리 항목
이전 장에서 루트 디렉토리에 대해 이미 논의한 바와 같이 각 파일 또는 디렉토리에 대해 32바이트의 정보가 있습니다. 이 32바이트는 다음과 같이 나뉩니다.
Number of Bytes |
Information Description |
8 Bytes |
Filename |
3 Bytes |
Extension |
1 Byte |
Attribute |
10 Bytes |
Reserved |
2 Bytes |
Time, Created or Last Updated |
2 Bytes |
Date, Created or Last Updated |
2 Bytes |
Starting Cluster |
4 Bytes |
File Size |
루트 디렉토리에서 파일 정보를 읽어 데이터를 복구한 다음 파일을 대상 경로에 통합하고 파일을 복구합니다. 다음 프로그램은 데이터를 복구하기 위해 다음 단계를 수행합니다.
- 루트 디렉토리 항목을 읽고 파일/디렉토리 이름, 파일 확장자, 파일의 시작 클러스터 크기(바이트)와 같은 모든 정보와 함께 화면에 표시합니다.
- 하위 디렉토리의 파일 및 디렉토리 정보를 읽고 필요한 경우 표시합니다.
- 복구할 파일 이름을 확인하고 복구를 계속합니다.
- 복구할 지정된 파일에 대한 CHS(실린더, 헤드 및 섹터) 정보를 계산합니다.
- 디스크의 데이터 영역에서 파일의 데이터를 통합하고 복구된 파일을 지정된 경로의 지정된 대상 파일 이름에 저장합니다.
이 프로그램은 플로피의 부팅 정보를 읽을 수 있는지 여부에 상관하지 않습니다. 따라서 손상된 플로피 디스크에서도 삭제된 데이터를 복구할 수 있습니다. 프로그램의 코딩을 보자:
/* 루트 디렉터리에서 파일 정보를 읽어 플로피 디스크에서 데이터를 복구하는 프로그램 */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
unsigned int);
unsigned int track=0,head=1,sector=2;
Display_Information(track,head,sector);
} /*End of main */
void Display_Information(unsigned int track,
unsigned int head,
unsigned int sector)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // Buffer of 512 Bytes
char ch;
struct diskinfo_t finfo; //Structure, Used by _bios_disk
unsigned int result,i,j, count=0; /* Unsigned Integers
Defined */
unsigned int file_no; /* Unsigned Integer
for File Number */
struct
{
unsigned int name[8],ext[3]; /* File Name for DOS in 8.3
(Eight Dot Three) Format */
unsigned int attribute; // File/Directory Attribute
unsigned int start; // Starting Cluster of the File
long unsigned int size; // Size of the File in Bytes
}root[32]; /* 32 Bytes Information of
File/Directory in Root
Directory */
clrscr();
do
{
file_no=0;
finfo.drive = 0x00; /* drive number for A: */
finfo.head = head; /* disk head number */
finfo.track = track; /* track number */
finfo.sector= sector; /* sector number */
finfo.nsectors=1; /* sector count */
finfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &finfo); /* Read the
Sector */
if( (result & 0xff00) != 0) /* If Read Error, Display
Error Message and Exit*/
{
printf("Read error");
getch();
exit(0); // Go Back to DOS
}
/// 정보 표시 화면 형식 \\\
clrscr();
gotoxy(9,1);
cprintf("DISPLAY CYLN: %u, HEAD: %u, SECTOR: %u",
track, head, sector);
gotoxy(9,2);
cprintf("FNO NAME EXT ATTRIBUTE START SIZE");
gotoxy(7,3);
cprintf("--------------------------------------------");
/* 한 번에 한 섹터. 모든 파일/DIR 항목은 32바이트를 차지합니다. */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// 파일/디렉터리 이름 찾기 \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// 확장 프로그램 찾기 \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// 클러스터 시작 \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// 크기 계산 \\\
root[file_no].size =(long unsigned int)(0xff &
buf[31+i])*16*16*16*16*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[30+i])*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[29+i])*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[28+i]);
if((root[file_no].start == 0) ||
(root[file_no].attribute == 15))
continue;
else
{
gotoxy(8,i/32+4);
cprintf("%2u",file_no); /* Display File
Number */
for(j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Display File
Name */
}
for(j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Display
Extension */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Display
Attribute */
if(root[file_no].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Display if Directory Attribute */
}
else
{
gotoxy(33,i/32+4);
cprintf("<FILE>"); /* The Entry is of a file */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Display
Starting Cluster */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* size of the
File */
}
file_no++;
}
gotoxy(10,
cprintf("Press 'M' : To see list of more files &quo
gotoxy(10,
cprintf("Press 'R' :To recover a file from the above
list&quo
ch=getc
s(E5H)로 시작하는 파일 이름은 파일이 삭제되어 파일 이름의 첫 번째 문자가 s로 대체되었음을 나타냅니다(이전 장의 루트 디렉토리 설명 참조).
And the output of the program is displayed like this:
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
--------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Press 'M' : To see list of more files
Press 'R' :To recover a file from the above list R
|
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
----------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Enter FNO. of the file you want to recover 1
You want to recover _2_INFO .C
Cylinder = 1, Head = 0, Sector = 1 Integrating........
Enter Path and Filename to recover the file: c:\windows\desktop\H2_INFO.C
Recovery Done !!!
|
코딩에 대한 의견:
Display_Information 기능은 루트 디렉터리에서 파일 및 디렉터리 정보를 읽는 것입니다. 구조에서 루트[32]가 있는 모든 파일 또는 디렉토리에 대한 32바이트 정보를 읽고 있습니다.
부호 없는 정수 배열 name[8] 및 ext[3]은 8.3(Eight Dot Three) 형식의 DOS용 파일 또는 디렉토리 이름입니다. 마찬가지로 1바이트는 속성용이고 2바이트는 클러스터 시작용입니다. long unsigned int 크기; 4바이트의 파일 크기를 저장하는 것입니다.
_bios_disk 함수는 finfo 구조로 지정된 섹터를 읽고 작업 상태가 결과에 저장됩니다.
_bios_disk 함수가 읽은 512바이트의 모든 정보에서 루트 디렉토리 영역이 끝날 때까지 디스크에 저장된 파일 및 디렉토리 정보를 수집합니다. 화면에 표시합니다.
정수 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); /* Function to Clear a Row on the Screen */
/* 지정된 파일을 통합하는 기능 */
void integrate(long unsigned int,unsigned int,
unsigned int,unsigned int);
unsigned int file_no,i;
char ch;
unsigned int *loc;
unsigned int cylinder,head,sector;
unsigned int start;
long unsigned int size;
clear_the_line(21); /* Clear The Row Number 21 */
clear_the_line(22); /* Clear The Row Number 22 */
clear_the_line(23); /* Clear The Row Number 23 */
clear_the_line(24); /* Clear The Row Number 24 */
gotoxy(10,21);
cprintf("Enter FNO. of the file you want to recover");
scanf("%u",&file_no); /* Get the File No. to be
Recovered */
loc=(root+(len*file_no/2));
/* 복구할 파일 이름 확인 */
gotoxy(10,22);
cprintf("You want to recover");
for(i=0;i<8;i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* File name */
}
gotoxy(38,22);
cprintf(".");
for(i=0;i<3;i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* File Extension */
}
start=*(loc+12);
/// 죄송합니다. 디렉토리를 선택했습니다. \\\
if(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Is A directory. Do you want to see the
contents of this directory Y/N");
ch=getch();
if(ch==27)
main();
if(ch=='y' || ch=='Y')
{
/* 기하학 계산 */
calculate(start,&cylinder,&head,§or);
/* 디렉토리 내용 표시 */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* CHS 정보 계산 */
calculate(start,&cylinder,&head,§or);
/* 파일 통합 */
integrate(size,cylinder,head,sector);
}
}
코딩에 대한 의견:
recover() 함수는 사용자 입력을 받아 복구를 시작하는 것입니다. 파일을 복구하기 위해 사용자가 입력한 파일 번호는 file_no에 저장됩니다.
입력한 번호가 디렉토리 항목이면 Display_Information()은 해당 디렉토리의 내용을 표시하고, 그렇지 않으면 파일 이름과 파일 번호 file_no의 확장자를 화면에 표시하여 복구할 파일을 확인합니다.
지정된 파일을 복구하기 위해 calculate() 및 integrate() 함수가 함수 내에서 호출됩니다. 계산() 함수의 코딩은 다음과 같습니다.
/* 복구를 위한 CHS 기하학을 계산하는 기능 */
void calculate(unsigned int start,unsigned int *cylinder,
unsigned int *head,unsigned int *sector)
{
unsigned int temp;
*cylinder=0;
*head=1;
*sector=14;
if(start<5)
*sector=14+start;
else
{
temp= (start-4)/18;
if(temp>0)
{
if(temp%2==0)
*head=0;
else
*head=1;
*cylinder+=1+temp/2;
}
else
{
*head=0;
*cylinder=1;
}
*sector=(start-4)%18;
}
/// 복구할 파일의 CHS 표시 \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
코딩에 대한 의견:
calculate() 함수는 복구할 파일에 대한 실린더, 헤드 및 섹터 정보를 계산하는 것입니다. 계산 후 Cylinder, Head 및 Sector 번호가 화면에 표시됩니다.
통합() 함수에 대한 코딩은 다음과 같습니다.
/* 파일 통합 및 복구된 파일을 지정된 경로 및 파일 이름에 저장 */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* 섹터 오류 확인 기능 */
int verify_the_sector(unsigned int, unsigned int,
unsigned int);
int status;
char buf[512],*Filename_with_path;
struct diskinfo_t dinfo;
unsigned int result;
FILE *fp;
unsigned int left,i;
unsigned int sec;
/* 복구된 파일을 저장하려면 대상 경로와 파일 이름을 입력하십시오. */
gotoxy(2,24);
cprintf("Enter Path and Filename to recover the file: ");
fflush(stdin);
gets(Filename_with_path);
fp=fopen(Filename_with_path,"wb");
/* 오류가 발생하면 오류 메시지를 표시하고 입력 경로 및 파일 이름을 다시 가져옵니다 */
if(fp==NULL)
{
gotoxy(5,25);
cprintf("Error in opening the file");
getch();
clear_the_line(24);
gotoxy(0,25);
cprintf(" ");
integrate(size,cylinder,head,sector); /* Enter the
Destination Again */
}
/* 모든 것이 정상이면 통합하고 작성하십시오 */
gotoxy(50,23);
cprintf("Integrating........");
left= size%512;
sec = size/512;
sec++;
while(sec>0)
{
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = cylinder; /* track number */
dinfo.sector= sector; /* sector number */
dinfo.nsectors=1; /* sector count */
dinfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
/* If there is Error While Reading any Sector */
if( (result & 0xff00) != 0)
{
gotoxy(5,25);
cprintf("read error Cylinder %u, Head %u, Sector %u",
cylinder, head, sector);
}
else
{
if(sec==1)
{
for(i=0;i<left;i++)
fputc(buf[i],fp); /* Write The Integrated
Information to the File */
}
else
{
fwrite(buf,512,1,fp);
}
코딩에 대한 의견:
integrate() 함수는 이 복구 프로그램에서 사용자 지정 파일의 복구를 수행하는 실제 모듈입니다.
복구된 파일을 저장할 대상 경로가 있는 파일 이름은 *Filename_with_path 문자 포인터에 저장됩니다. 대상 파일을 여는 데 오류가 있는 경우 오류 메시지가 표시되고 사용자에게 대상 파일을 다시 입력하라는 메시지가 표시됩니다.
_bios_disk(_DISK_READ, &dinfo); 함수는 디스크 섹터의 데이터 영역에서 섹터별로 파일의 데이터를 읽습니다. dinfo 구조로 지정되고 데이터 버퍼 buf에 저장됩니다. . 이 512바이트의 데이터가 대상 파일에 기록됩니다. 이것은 완전한 파일이 통합될 때까지 반복됩니다.
기능 status=verify_the_sector(실린더, 헤드, 섹터); 읽을 섹터를 확인합니다. 상태 = 10이면 불량(0xA) 섹터를 나타냅니다. 함수의 코딩은 다음과 같습니다.
/// 섹터를 확인합니다. (여기에 데이터가 전송되지 않음) \\\
int verify_the_sector(unsigned int c,unsigned int h,unsigned int s)
{
int status;
char *buf;
union REGS in, out;
struct SREGS sg;
in.h.ah = 0x04; /* Function Number */
in.h.al = 1; /* Number of Sectors to Verify*/
in.h.dl = 0x00; /* Drive Number for A: */
in.h.ch = c; /* Cylinder Number */
in.h.dh = h; /* Head Number */
in.h.cl = s; /* Sector Number */
in.x.bx = FP_OFF(buf);/* Offset */
sg.es = FP_SEG(buf); /* Segment */
int86x(0x13,&in,&out,&sg); /* Call the Function 4H
of INT 13H */
if(out.x.cflag)
{
status=out.h.ah;
}
return(status);
}
코딩에 대한 의견:
verify_the_sector() 함수는 _bios_disk() 함수가 읽을 섹터를 확인하고 작업 상태를 반환합니다. 이 함수는 INT 13H 및 함수 4H를 사용하여 섹터를 확인합니다.
*buf는 데이터 버퍼, 0x04는 in.h.ah = 0x04로 지정된 함수 번호입니다. 및 in.h.al = 1; 한 번에 한 섹터를 확인하도록 지시합니다. in.h.dl = 0x00; 플로피 드라이브 A:, c,h의 드라이브 번호로 사용되며 s는 실린더, 헤드 및 섹터 번호입니다.
int86x() 함수는 세그먼트 레지스터 값으로 INT 13H(함수 4H)를 호출하는 데 사용됩니다. 작업 상태는 정수 상태로 반환됩니다.
clear_the_line() 함수는 화면에서 지정된 행을 지웁니다. 함수의 코딩은 다음과 같습니다.
/* 지정된 Row Number에 대해 화면의 Line을 지우는 기능 */
void clear_the_line(unsigned int row)
{
unsigned int column;
/* There are 80 Columns in a Row (Line) */
for(column=1;column<=80;column++)
{
gotoxy(column,row);
cprintf(" "); /* Clear With " " */
}
}
코딩에 대한 의견:
이 기능은 화면에서 지정된 행을 지우는 데 사용됩니다. 함수는 화면에서 지워질 행의 번호로 호출됩니다.