장 - 10
손상된 디스크에서 데이터 복구
손상된 플로피 디스크에서 데이터 복구
플로피 디스크는 가장 신뢰할 수 없는 데이터 저장 장치 중 하나입니다. 컴퓨터 시스템을 사용하는 조직에 가서 직원들에게 플로피 디스크로 인한 문제에 대해 물어보면, 조직의 직원이 플로피 디스크에 중요한 데이터를 보관하고 있어서 컴퓨터에서 플로피 디스크를 읽을 수 없고 다음과 비슷한 메시지가 화면에 나타난다는 문제를 자주 들을 수 있을 것입니다.
"디스크를 읽을 수 없습니다."
"잘못된 트랙 0"
"잘못된 디스크 또는 용량입니다."
"디스크가 포맷되지 않았습니다. 지금 포맷하시겠습니까?
이는 컴퓨터 시스템과 플로피 디스크를 사용하는 조직에서는 일상적인 문제입니다. 손상된 플로피 디스크에서 손실된 것으로 보이는 데이터에 대한 백업이 만들어지지 않았거나 백업이 존재하지 않는다는 사실을 알게 되면 문제는 심각해집니다.
가장 큰 문제는 중요한 정보를 플로피 디스크에 백업하거나, 바이러스 공격을 극복하기 위해 바이러스 백신 프로그램 디스크를 복원하거나, 부트 레코드나 기타 백업(여러 옵션이 있을 수 있음)을 플로피 디스크에 저장한 후, 플로피 디스크에서 백업을 재사용하려고 할 때 읽기 오류가 발생하는 것입니다.
이런 경우 중요한 정보와 데이터를 잃을 위험이 있으며, 어떤 경우에는 컴퓨터 부팅 정보를 위한 백업 및 복구 프로그램 , 바이러스 공격 복구 프로그램 등이 부족하다고 느낄 때, 현재 컴퓨터에서 플로피 디스크를 읽을 수 없는 상태로, 플로피 디스크에 저장된 정보가 부족하여 OS 오류의 형태로 주요 데이터 손실을 겪을 수도 있습니다.
이런 경우, 가장 중요한 요구사항은 컴퓨터 시스템에서 오류가 있는 것으로 인식한 플로피 디스크에서 데이터를 복구하는 것 입니다.
플로피 디스크를 읽을 수 없는 이유는 무엇인가?
플로피 디스크에서 이와 같은 오류 메시지가 나타나는 가장 흔한 문제는 플로피 디스크의 DOS 부트 레코드(DBR)가 손상되었기 때문입니다. DBR은 컴퓨터가 플로피 디스크의 논리적 ID를 알 수 있도록 도와줍니다.
DBR은 플로피 디스크에 대한 중요 정보를 담고 있는 트랙 0, 헤드 0, 섹터 1에 저장되는 작은 프로그램입니다 .
- 섹터당 바이트 수
- 클러스터당 섹터
- FAT의 수
- 루트 디렉토리의 최대 개수 등
플로피 디스크에는 논리적 파티션 시스템이 없으므로 플로피 디스크에는 MBR이 없습니다. 플로피 디스크의 첫 번째 섹터에는 DBR이 들어 있습니다. 이는 하드 디스크와 플로피 디스크의 논리적 구조를 비교할 때 가장 큰 차이점입니다.
디스크 편집 프로그램을 사용하여 플로피 디스크의 부트 섹터 정보를 읽으면 아래 이미지에 표시된 것과 같은 정보가 표시됩니다.
다음 그림은 1.44MB, 3½인치 플로피 디스크에 있는 512바이트의 DBR 정보를 보여줍니다.

만약 이 정보가 손상되거나 읽을 수 없게 되면 플로피 디스크는 이러한 읽기 오류 메시지를 생성하게 됩니다. 이는 디스크의 첫 번째 섹터에 물리적 또는 논리적 손상이 발생했기 때문일 수 있습니다.
논리적 손상에는 디스켓의 첫 번째 섹터에 있는 정보가 변경되거나, 논리적으로 손상된 섹터가 있거나 , 디스켓의 DBR이 다른 이유로 손상된 경우가 포함됩니다.
플로피 디스크의 첫 번째 섹터에 물리적으로 불량 섹터가 있는 경우(즉, 섹터 1이 물리적으로 손상된 경우) 물리적 손상이 발생한 것으로 간주됩니다. 플로피 디스크의 트랙 0에 두 개 이상의 불량 섹터가 있는 경우 문제는 더욱 심각해집니다.
복구 방법
두 가지 손상 원인을 모두 알게 되었으니 이제 문제를 이해하셨기를 바랍니다. 논리적 손상에서 데이터를 복구하는 것은 그렇게 어렵지 않지만 , 물리적 손상에서 복구하려면 좀 더 많은 노력이 필요합니다.
방법 - 1
새 플로피 디스크의 부팅 가능한 이미지를 저장합니다.
문제가 논리적이라면 이제 데이터를 복구하는 방법을 알게 되었습니다. 우리가 해야 할 일은 같은 크기와 용량의 다른 플로피에서 적절한 부트 레코드를 가져와 읽을 수 없는 플로피의 첫 번째 섹터에 붙여 넣는 것입니다. 문제는 나쁜 부트 레코드 로 인해 발생했지만 지금은 작동해야 합니다.
읽을 수 없는 플로피 디스크에서 데이터를 복구하는 이 절차에는 두 단계가 포함됩니다 .
- 좋은 플로피의 DOS 부트 레코드 이미지 만들기
- 읽을 수 없는 플로피의 첫 번째 섹터에 부팅 이미지 붙여넣기
좋은 플로피의 DOS 부트 레코드 이미지 만들기
새 플로피 디스크의 부트 레코드 이미지를 저장하려면 프로그램이 다음 세 가지 작업을 수행해야 합니다.
- 좋은 플로피의 처음 512바이트를 정확히 읽습니다.
- 성공적인 읽기 작업 확인(가장 중요)
- 이 512바이트를 지정된 파일 이름과 대상 경로에 저장합니다.
플로피의 섹터는 512바이트이고 섹터의 정확한 이미지를 복사해야 합니다. 플로피에 적용된 모든 유형의 작업의 경우 작업이 성공했는지 여부를 확인하는 것이 가장 중요하고 필요한 단계입니다.
좋은 플로피 디스크와 새 플로피 디스크에도 초기화 문제가 있을 수 있습니다. 그래서 대부분의 경우 플로피 디스크에서 작업을 수행할 때 플로피 디스크의 초기화는 리셋 디스크 작업 (INT 13H의 함수 00 H)으로 프로그래밍하여 수행됩니다.
최근에 삽입한 플로피 디스크나 교체한 플로피 디스크를 초기화한 후에도 읽기 오류가 발생하면 프로그램을 다시 실행해 보세요. 이번에는 작동할 가능성이 높습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 어떻게 진행되는지 살펴보겠습니다.
/* 새 플로피 디스크에서 부트 이미지를 파일로 저장 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 diskinfo_t dinfo;
노동조합 REGS 규정;
int 결과;
int 개수=0, i;
char fname[80];
정적 char dbuf[512];
파일 *fp;
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = 0; /* 디스크 헤드 번호 */
dinfo.track = 0; /* 트랙 번호 */
dinfo.sector = 1; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
영어: clrscr();
gotoxy(10,3);cprintf("파일 이름과 경로를 입력하세요
부트 이미지 저장");
고톡시(5,5);
(이름)을 가져옵니다.
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
하이비디오();
gotoxy(10,10);cprintf("파일을 만들 수 없습니다");
getch();
종료(0);
}
고톡시(10,9);
cprintf("플로피 디스크 드라이브에서 읽기를 시도 중입니다 :\n");
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
결과 = _bios_disk(_DISK_READ, &dinfo);
if ((결과 & 0xff00) == 0)
{
while(개수<512)
{
fprintf(fp, "%c",dbuf[개수] & 0xff);
카운트++;
}
fp를 닫습니다.
gotoxy(10,14);cprintf("플로피 디스크 드라이브에서 디스크 읽기
: 성공.\n");
}
또 다른
{
고톡시(10,14);
cprintf("드라이브 A를 읽을 수 없습니다. 상태 = 0x%02x\n", result);
스위치(결과)
{
케이스 0x00:
cprintf("\n\n 상태: 오류 없음!! ");
부서지다;
케이스 0x01:
cprintf("\n\n 상태: 잘못된 명령 ");
부서지다;
케이스 0x02:
cprintf("\n\n 상태: 주소 표시를 찾을 수 없습니다 ");
부서지다;
케이스 0x03:
cprintf("\n\n 상태: 쓰기 보호된 디스크에 쓰려고 시도했습니다 . ");
부서지다;
케이스 0x04:
cprintf("\n\n 상태: 섹터를 찾을 수 없습니다 ");
부서지다;
케이스 0x06:
cprintf("\n\n 상태: 마지막 작업 이후 디스크가 변경되었습니다 ");
부서지다;
케이스 0x08:
cprintf("\n\n 상태: 직접 메모리 액세스(DMA) 오버런 ");
부서지다;
케이스 0x09:
cprintf("\n\n 상태: 64K 경계를 넘어 DMA를 수행하려고 시도했습니다 ");
부서지다;
케이스 0x0C:
cprintf("\n\n 상태: 미디어 유형을 찾을 수 없습니다 ");
부서지다;
케이스 0x10:
cprintf("\n\n 상태: 디스크 읽기의 CRC/ECC가 잘못되었습니다 ");
부서지다;
케이스 0x20:
cprintf("\n\n 상태: 컨트롤러가 실패했습니다 ");
부서지다;
케이스 0x31:
cprintf("\n\n 상태: 드라이브에 미디어가 없습니다(IBM/MS INT 13H 확장) ");
부서지다;
케이스 0x32:
cprintf("\n\n 상태: CMOS(Compaq)에 잘못된 드라이브 유형이 저장되었습니다 ");
부서지다;
케이스 0x40:
cprintf("\n\n 상태: 검색 작업이 실패했습니다 ");
부서지다;
케이스 0x80:
cprintf("\n\n 상태: 첨부 파일이 응답하지 못했습니다(디스크 시간 초과) ");
부서지다;
케이스 0xB0:
cprintf("\n\n 상태: 볼륨이 드라이브에 잠기지 않았습니다(INT 13H 확장) ");
부서지다;
케이스 0xB1:
cprintf("\n\n 상태: 드라이브의 볼륨이 잠겼습니다(INT 13H 확장자) ");
부서지다;
케이스 0xB2:
cprintf("\n\n 상태: 볼륨을 제거할 수 없습니다(INT 13H 확장) ");
부서지다;
케이스 0xB3:
cprintf("\n\n 상태: 볼륨이 사용 중입니다(INT 13H 확장) ");
부서지다;
케이스 0xB4:
cprintf("\n\n 상태: 잠금 횟수 초과(INT 13H 확장) ");
부서지다;
케이스 0xB5:
cprintf("\n\n 상태: 유효한 꺼내기 요청이 실패했습니다(INT 13H 확장) ");
부서지다;
기본값: cprintf("\n\n 상태: 플로피 오류에 대한 알 수 없는 상태 코드 ");
}
}
0을 반환합니다.
}
프로그램 코딩에 대한 의견:
이전에 제시한 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 디스크의 첫 번째 섹터를 읽고 싶으므로 섹터의 위치는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x00 |
플로피 디스크 드라이브( a:) 인 드라이브 0을 나타냅니다 . |
dinfo.헤드 = 0 |
0 번 헤드를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
읽기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- 사용자가 지정한 파일 이름과 경로의 파일 스트림을 열어 정확히 512바이트의 부팅 이미지 정보를 저장합니다. 파일 이름과 경로는 문자 배열 fname에 저장됩니다.
- 인터럽트 13H(함수 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 함수 00 H를 가리키고 regs.h.dl = 0x00은 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)는 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_READ, &dinfo)는 플로피 디스크의 지정된 섹터를 읽습니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.

읽을 수 없는 플로피의 첫 번째 섹터에 부팅 이미지 붙여넣기
읽을 수 없는 플로피 디스크의 첫 번째 섹터에 파일의 부트 이미지를 붙여넣으려면 프로그램에서 다음 세 가지 주요 작업을 수행해야 합니다.
- 이전에 저장된 파일에서 새 플로피 디스크의 부트 레코드의 정확한 512바이트 정보를 읽습니다.
- 현재 읽을 수 없는 플로피의 첫 번째 섹터에 이 정보를 기록하세요.
- 쓰기 작업이 성공적으로 완료되었는지 확인합니다(가장 중요).
플로피의 섹터는 512바이트이고 정확한 부트 이미지를 섹터에 붙여넣어야 합니다. 플로피에 어떤 유형의 작업이 적용되는 경우 작업이 성공했는지 여부를 확인하는 것이 가장 중요하고 필요한 단계입니다.
작업 중에 플로피 디스크에 초기화 문제가 있을 수 있으므로 디스크 시스템을 재설정 하여 디스크를 초기화해야 합니다 (INT 13H의 00H 기능 사용).
최근에 삽입한 플로피 디스크나 교체한 플로피 디스크를 초기화한 후에도 읽기 오류가 발생하면 프로그램을 다시 실행해 보세요. 이번에는 작동할 가능성이 높습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 어떻게 진행되는지 살펴보겠습니다.
/* 읽을 수 없는 플로피에 부트 이미지 로드 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 diskinfo_t dinfo;
노동조합 REGS 규정;
int 결과;
int 개수=0, i;
char fname[80];
문자 dbuf[512];
파일 *fp;
영어: clrscr();
gotoxy(5,3);cprintf("플로피 부팅 이미지가 저장되는 파일 이름과 경로를 입력하세요");
고톡시(5,5);
(이름)을 가져옵니다.
fp=fopen(fname,"rb");
if((fp=fopen(fname,"rb"))==NULL)
{
하이비디오();
gotoxy(10,10);cprintf("파일을 열 수 없습니다");
getch();
종료(0);
}
고톡시(10,9);
cprintf("플로피 디스크 드라이브를 복구하려고 시도합니다:\n");
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
while(개수<512)
{
fscanf(fp, "%c", &dbuf[개수]);
카운트++;
}
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = 0; /* 디스크 헤드 번호 */
dinfo.track = 0; /* 트랙 번호 */
dinfo.sector = 1; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
결과 = _bios_disk(_DISK_WRITE, &dinfo);
if ((결과 & 0xff00) == 0)
{
fp를 닫습니다.
gotoxy(10,14);cprintf("성공!!! 플로피가
지금 일하세요.\n");
}
또 다른
{
고톡시(10,14);
cprintf("드라이브 A를 읽을 수 없습니다. 상태 = 0x%02x\n", result);
고톡시(10,16);
스위치(결과)
{
케이스 0x00:
cprintf("\n\n 상태: 오류 없음!! ");
부서지다;
케이스 0x01:
cprintf("\n\n 상태: 잘못된 명령 ");
부서지다;
케이스 0x02:
cprintf("\n\n 상태: 주소 표시를 찾을 수 없습니다 ");
부서지다;
케이스 0x03:
cprintf("\n\n 상태: 쓰기 보호된 디스크에 쓰려고 시도했습니다 . ");
부서지다;
케이스 0x04:
cprintf("\n\n 상태: 섹터를 찾을 수 없습니다 ");
부서지다;
케이스 0x06:
cprintf("\n\n 상태: 마지막 작업 이후 디스크가 변경되었습니다 ");
부서지다;
케이스 0x08:
cprintf("\n\n 상태: 직접 메모리 액세스(DMA) 오버런 ");
부서지다;
케이스 0x09:
cprintf("\n\n 상태: 64K 경계를 넘어 DMA를 수행하려고 시도했습니다 ");
부서지다;
케이스 0x0C:
cprintf("\n\n 상태: 미디어 유형을 찾을 수 없습니다 ");
부서지다;
케이스 0x10:
cprintf("\n\n 상태: 디스크 읽기의 CRC/ECC가 잘못되었습니다 ");
부서지다;
케이스 0x20:
cprintf("\n\n 상태: 컨트롤러가 실패했습니다 ");
부서지다;
케이스 0x31:
cprintf("\n\n 상태: 드라이브에 미디어가 없습니다(IBM/MS INT 13H 확장) ");
부서지다;
케이스 0x32:
cprintf("\n\n 상태: CMOS(Compaq)에 잘못된 드라이브 유형이 저장되었습니다 ");
부서지다;
케이스 0x40:
cprintf("\n\n 상태: 검색 작업이 실패했습니다 ");
부서지다;
케이스 0x80:
cprintf("\n\n 상태: 첨부 파일이 응답하지 못했습니다(디스크 시간 초과) ");
부서지다;
케이스 0xB0:
cprintf("\n\n 상태: 볼륨이 드라이브에 잠기지 않았습니다(INT 13H 확장) ");
부서지다;
케이스 0xB1:
cprintf("\n\n 상태: 드라이브의 볼륨이 잠겼습니다(INT 13H 확장자) ");
부서지다;
케이스 0xB2:
cprintf("\n\n 상태: 볼륨을 제거할 수 없습니다(INT 13H 확장) ");
부서지다;
케이스 0xB3:
cprintf("\n\n 상태: 볼륨이 사용 중입니다(INT 13H 확장) ");
부서지다;
케이스 0xB4:
cprintf("\n\n 상태: 잠금 횟수 초과(INT 13H 확장) ");
부서지다;
케이스 0xB5:
cprintf("\n\n 상태: 유효한 꺼내기 요청이 실패했습니다(INT 13H 확장) ");
부서지다;
기본값: cprintf("\n\n 상태: 플로피 오류에 대한 알 수 없는 상태 코드 ");
}
}
0을 반환합니다.
}
프로그램 코딩에 대한 의견:
이전에 제시한 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 따라서 디스크의 첫 번째 섹터에 정보를 기록하므로 해당 섹터의 위치는 다음과 같습니다.
- 이전 프로그램에서 새 플로피의 512바이트 부트 이미지 정보가 저장된 파일을 엽니다. 파일 이름과 경로는 문자 배열 fname에 저장됩니다.
- 인터럽트 13H(함수 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 함수 00 H를 가리키고 regs.h.dl = 0x00은 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)는 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_WRITE, &dinfo)는 지정된 파일의 부팅 정보를 플로피 디스크의 첫 번째(지정된) 섹터에 씁니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x00 |
플로피 디스크 드라이브( a:) 인 드라이브 0을 나타냅니다 . |
dinfo.헤드 = 0 |
0 번 헤드를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
쓰기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
단일 프로그램으로 해보자
이제 플로피 디스크에서 이런 유형의 데이터 복구의 개념을 이해하셨기를 바랍니다 . 그 후에 이전에 논의한 두 프로그램의 도움으로 얻은 것과 동일한 결과를 제공하는 단일 프로그램을 상상해 보겠습니다.
우리는 최근 논의된 프로그램으로 다음 작업을 수행했습니다.
- 좋은 플로피 디스크에서 부팅 정보를 파일로 저장
- 이 정보를 현재 읽을 수 없는 플로피의 첫 번째 섹터에 붙여넣습니다. 부트 이미지를 저장하는 데 사용하던 파일은 두 프로그램의 작업을 연결하는 중간 브리지 역할을 했습니다. 하지만 프로그램 코딩 자체에서 이 부트 정보를 정의하면 파일을 만들 필요가 없고 파일에서 플로피의 부트 정보를 읽을 필요도 없습니다.
다음 프로그램에서는 읽을 수 없는 플로피 디스크의 첫 번째 섹터에 무엇을 써야 하는지 프로그램에 알려줌으로써 서로 다른 두 프로그램이 동일한 작업을 수행하는 것을 방지하고 이전과 같은 방식으로 새로운 단일 프로그램에서 데이터를 복구 할 수 있습니다.
따라서 프로그램은 코딩이 줄어들면서 간단해지고 파일 읽기, 쓰기 또는 생성 오류 의 발생 확률을 줄일 수 있습니다 . 이 프로그램에서는 다음의 네 가지 중요한 작업을 수행합니다.
dbuf[512] 의 512바이트 16진수 정보를 보면 프로그램을 작성하고 이해하기 어렵다고 생각하지 마십시오 . 나중에 프로그램 코딩을 위해 이 정보를 쉽게 작성하는 방법에 대해 논의하겠습니다.
- 현재 읽을 수 없는 플로피의 첫 번째 섹터에 기록될 DOS 부트 레코드 정보를 16진수 시스템으로 정의합니다.
- 플로피 디스크를 초기화하려면 디스크 시스템을 재설정합니다(INT 13H, 기능 00H).
- 플로피의 첫 번째 섹터에 DOS 부트 레코드를 씁니다.
- 작업이 성공적으로 완료되었는지 확인하고, 오류가 발생한 경우 이를 확인합니다.
프로그램을 살펴보겠습니다.
/* 기본 부팅 이미지를 읽을 수 없는 플로피 디스크에 로드하는 단일 프로그램 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 diskinfo_t dinfo;
노동조합 REGS 규정:
int 결과, i;
/* 플로피 디스크 드라이브에 로드될 부팅 이미지 */
정적 문자 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,0x0,0x0,0x29, 0x24,0x3B,0xDB, 0x16,0x4E, 0x4F, 0x20, 0x4E,0x41,0x4D,0x45,
0x20, 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, 0x72, 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, 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x20, 0x20,
0x20, 0x53, 0x59, 0x53, 0x80, 0x1, 0x0, 0x57, 0x49, 0x4E, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x53, 0x59
,0x53,0x0,0x0,0x55,0xAA};
영어: clrscr();
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = 0; /* 디스크 헤드 번호 */
dinfo.track = 0; /* 트랙 번호 */
dinfo.sector = 1; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
고톡시(10,9);
cprintf("플로피 디스크 드라이브에서 읽기를 시도 중입니다 :\n");
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
결과 = _bios_disk(_DISK_WRITE, &dinfo);
if ((결과 & 0xff00) == 0)
{
고톡시(10,14);
cprintf("디스크 쓰기 상태 : 성공.\n");
}
또 다른
{
고톡시(10,14);
cprintf("드라이브 A를 읽을 수 없습니다, 상태 = 0x%02x\n",
결과);
고톡시(10,16);
스위치(결과)
{
케이스 0x00:
cprintf("\n\n 상태: 오류 없음!! ");
부서지다;
케이스 0x01:
cprintf("\n\n 상태: 잘못된 명령 ");
부서지다;
케이스 0x02:
cprintf("\n\n 상태: 주소 표시를 찾을 수 없습니다 ");
부서지다;
케이스 0x03:
cprintf("\n\n 상태: 쓰기를 시도합니다.
보호된 디스크 ");
부서지다;
케이스 0x04:
cprintf("\n\n 상태: 섹터를 찾을 수 없습니다 ");
부서지다;
케이스 0x06:
cprintf("\n\n 상태: 마지막 작업 이후 디스크가 변경되었습니다 ");
부서지다;
케이스 0x08:
cprintf("\n\n 상태: 직접 메모리 액세스(DMA) 오버런 ");
부서지다;
케이스 0x09:
cprintf("\n\n 상태: 64K 경계를 넘어 DMA를 수행하려고 시도했습니다 ");
부서지다;
케이스 0x0C:
cprintf("\n\n 상태: 미디어 유형을 찾을 수 없습니다 ");
부서지다;
케이스 0x10:
cprintf("\n\n 상태: 디스크 읽기의 CRC/ECC가 잘못되었습니다 ");
부서지다;
케이스 0x20:
cprintf("\n\n 상태: 컨트롤러가 실패했습니다 ");
부서지다;
케이스 0x31:
cprintf("\n\n 상태: 드라이브에 미디어가 없습니다(IBM/MS INT 13H 확장) ");
부서지다;
케이스 0x32:
cprintf("\n\n 상태: CMOS(Compaq)에 잘못된 드라이브 유형이 저장되었습니다 ");
부서지다;
케이스 0x40:
cprintf("\n\n 상태: 검색 작업이 실패했습니다 ");
부서지다;
케이스 0x80:
cprintf("\n\n 상태: 첨부 파일이 응답하지 못했습니다(디스크 시간 초과) ");
부서지다;
케이스 0xB0:
cprintf("\n\n 상태: 볼륨이 드라이브에 잠기지 않았습니다(INT 13H 확장) ");
부서지다;
케이스 0xB1:
cprintf("\n\n 상태: 드라이브의 볼륨이 잠겼습니다(INT 13H 확장자) ");
부서지다;
케이스 0xB2:
cprintf("\n\n 상태: 볼륨을 제거할 수 없습니다(INT 13H 확장) ");
부서지다;
케이스 0xB3:
cprintf("\n\n 상태: 볼륨이 사용 중입니다(INT 13 확장) ");
부서지다;
케이스 0xB4:
cprintf("\n\n 상태: 잠금 횟수 초과(INT 13H 확장) ");
부서지다;
케이스 0xB5:
cprintf("\n\n 상태: 유효한 꺼내기 요청이 실패했습니다(INT 13H 확장) ");
부서지다;
기본값: cprintf("\n\n 상태: 플로피 오류에 대한 알 수 없는 상태 코드 ");
}
}
0을 반환합니다.
}
이 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- 정적 문자 데이터 버퍼 dbuf[512]는 읽을 수 없는 플로피의 첫 번째 섹터에 쓰여질 16진법의 512바이트 정보를 제공합니다. dbuf[512]는 작업 중에 컴퓨터에 플로피의 첫 번째 섹터에 어떤 정보를 써야 하는지 알려줍니다. (다음 프로그램 참조)
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 따라서 디스크의 첫 번째 섹터에 정보를 기록하므로 해당 섹터의 위치는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x00 |
플로피 디스크 드라이브( a:) 인 드라이브 0을 나타냅니다 . |
dinfo.헤드 = 0 |
0 번 헤드를 가리킨다 |
dinfo.트랙 = 0 |
0 번 트랙을 가리킵니다 |
dinfo.섹터 = 1 |
플로피의 첫 번째 섹터는 섹터 1 입니다. |
dinfo.섹터 = 1 |
쓰기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- 인터럽트 13H(함수 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 함수 00 H를 가리키고 regs.h.dl = 0x00은 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)는 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- _bios_disk(_DISK_WRITE, &dinfo)는 지정된 파일의 부팅 정보를 플로피 디스크의 첫 번째(지정된) 섹터에 씁니다.
반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
이전 프로그램에서 사용할 16진수 문자로 부팅 이미지 저장
우리가 최근에 논의한 프로그램에서 오류 없이 플로피의 DOS 부트 레코드의 512개 문자를 모두 16진법으로 수동으로 작성하는 것은 매우 어려운 작업이 될 것입니다. 우리가 그것을 정확하게 작성할 수 있다 하더라도 이를 수행하는 것은 어렵고 시간이 많이 걸리는 작업이 될 것입니다. 까다로운 마음을 사용하여 데이터 버퍼 dbuf[512]의 데이터를 파일에 저장해 보겠습니다.
C 프로그래밍에서 16진수 문자는 0x로 표현되며 16진수 문자가 A9 H인 경우 C 프로그램에서 이를 0xA9로 작성해야 한다는 것을 알고 있습니다. 다음 프로그램도 마찬가지입니다. 이전 프로그램에서 작성해야 했던 데이터를 데이터 버퍼 dbuf[512]의 데이터로 저장합니다.
당신이 해야 할 일은 새롭고 신선한 플로피를 가져와서 DBR 이미지를 만들고 지정된 대상 파일에서 이 프로그램의 출력을 복사하여 이 데이터를 프로그램에 붙여넣는 것입니다. 필요한 경우 약간의 서식을 지정하세요. 어떻게 작동하는지 살펴보겠습니다.
/* 플로피 디스크의 부팅 이미지를 16진수 문자로 만드는 프로그램 */
#include <bios.h>
#include <stdio.h>
int 메인(공백)
{
구조체 diskinfo_t dinfo;
노동조합 REGS 규정;
int 결과, i;
int 개수=0;
char fname[80];
정적 char dbuf[512];
파일 *fp;
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = 0; /* 디스크 헤드 번호 */
dinfo.track = 0; /* 트랙 번호 */
dinfo.sector = 1; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
영어: clrscr();
gotoxy(10,3);cprintf("파일 이름과 경로를 입력하세요
부팅 이미지를 HEX 시스템으로 저장합니다");
고톡시(5,5);
(이름)을 가져옵니다.
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
하이비디오();
gotoxy(10,10);cprintf("파일을 만들 수 없습니다");
getch();
종료(0);
}
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("플로피에서 읽으려고 시도 중입니다.
디스크 드라이브 :\n");
결과 = _bios_disk(_DISK_READ, &dinfo);
if ((결과 & 0xff00) == 0)
{
고톡시(10,14);
cprintf("플로피 디스크 드라이브에서 읽은 디스크 :
성공했습니다.\n");
while(개수<512)
{
fprintf(fp, "0x%X, ",dbuf[count] & 0xff);
카운트++;
}
fp를 닫습니다.
}
또 다른
{
고톡시(10,14);
cprintf("드라이브 A를 읽을 수 없습니다, 상태 = 0x%02x\n",
결과);
}
0을 반환합니다.
}
프로그램 코딩에 대한 의견:
따라서 데이터는 지정된 파일에 저장됩니다. 데이터를 프로그램에 복사하고 필요한 서식을 지정하기만 하면 됩니다. 절차 전반에 걸쳐 다음 팁을 절대 잊지 마세요.
- 프로그램 작동이 성공적으로 이루어졌는지, 대상 파일에 저장된 데이터가 적절한지 확인하세요.
- 예상되는 오류가 발생하는지 전체적으로 작업을 확인해야 합니다.
- 부트 섹터를 읽기 전에 플로피 디스크를 프로그램으로 초기화해야 합니다. 이 목적을 위해 INT 13H의 함수 00H를 사용할 수 있습니다.
방법 - 2
방법 1이 효과가 없으면 어떻게 해야 하나요?
방법 1이 작동하지 않고 읽을 수 없는 디스크가 프로그램이 첫 번째 섹터의 부팅 정보를 다시 쓸 수 없게 하는 경우 두 번째 방법을 시도해야 합니다. 첫 번째 방법이 실패한 이유는 플로피 디스크의 첫 번째 섹터가 물리적으로 손상되었기 때문일 수 있습니다.
두 번째 방법에서는 읽을 수 없는 플로피 디스크의 모든 데이터를 임시로 하나의 파일에 복사한 다음, 이 이미지를 다른 좋은 디스크의 표면에 직접 붙여 넣을 것입니다.
이 절차에는 다음의 두 가지 중요한 단계가 포함됩니다.
- 섹터별로 플로피 디스크의 표면에 있는 모든 데이터를 일시적으로 하나의 파일에 복사합니다.
- 이전에 파일에 저장된 데이터를 새 플로피 디스크의 동일한 섹터에 그대로 붙여넣습니다.
미디어 표면의 모든 데이터를 단일 파일에 복사합니다.
플로피 디스크의 표면에 있는 모든 데이터를 저장하려면 프로그램이 다음 세 가지 작업을 수행해야 합니다.
- INT 13H의 기능 00H를 이용해 디스크를 올바르게 초기화합니다.
- 표면의 섹터별 정보를 읽고 단일 파일에 저장합니다.
- 성공적인 읽기 작업 확인(가장 중요)
플로피 디스크에서 초기화 문제가 발생하는 것은 매우 흔한 일로, 이로 인해 많은 실패한 읽기 메시지가 발생합니다. 그렇기 때문에 프로그래밍의 도움을 받아 읽기 쓰기 작업 전에 디스크를 초기화해야 합니다.
플로피에 어떤 종류의 작업이 적용되었을 때 작업이 성공적이었는지 여부를 확인하는 것은 가장 중요하고 필요한 단계입니다.
최근에 삽입한 플로피 디스크나 교체한 플로피 디스크를 초기화한 후에도 읽기 오류가 발생하면 프로그램을 다시 실행해 보세요. 이번에는 작동할 가능성이 높습니다.
다음 프로그램은 이러한 지정된 작업을 수행하는 것입니다. 어떻게 진행되는지 살펴보겠습니다.
/* 플로피 디스크의 물리적 표면의 데이터를 파일에 저장하는 프로그램 */
#include <bios.h>
#include <stdio.h>
void 메인(void)
{
int 헤드,트랙;
노동조합 REGS 규정;
int 결과, i, 섹터;
char 파일명[80];
구조체 diskinfo_t dinfo;
정적 char dbuf[512];
파일 *tt;
영어: clrscr();
printf("\n 파일 이름과 저장 경로를 입력하세요.
데이터 일시적으로\n");
gets(파일 이름);
if((tt=fopen(파일명,"wb"))==NULL)
{
printf("파일을 만들 수 없습니다,
아무 키나 눌러 종료하세요");
getch();
종료(0);
}
printf("\n 플로피 디스크 시스템 초기화 중...\n");
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
트랙=0;트랙<=79;트랙++)
{
for(머리=0;머리<=1;머리++)
{
섹터=1;섹터<=18;섹터++)
{
dinfo.drive = 0; /* A에 대한 드라이브 번호 */
dinfo.head = head; /* 디스크 헤드 번호 */
dinfo.track = track; /* 트랙 번호 */
dinfo.sector = sector; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
결과 = _bios_disk(_DISK_READ, &dinfo);
if ((결과 & 0xff00) == 0)
{
i=0;i<512;i++에 대하여
fprintf(tt, "%c",dbuf[i] & 0xff);
}
또 다른
{
printf("드라이브 A를 읽을 수 없습니다, 상태 =
0x%02x\t%d\t%d\t%d\n", 결과, 헤드, 트랙, 섹터);
}
printf("읽기 트랙 = %d 헤드 = %d 섹터 = %d\n",
트랙, 헤드, 섹터);
}
}
}
}
프로그램 코딩에 대한 의견:
이전에 제시한 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- 문자 배열 filename[80]은 우리가 일시적으로 데이터를 저장할 파일의 사용자 정의 경로와 파일 이름을 저장합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 인터럽트 13H(함수 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 함수 00 H를 가리키고 regs.h.dl = 0x00은 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)는 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- 디스크 표면의 모든 정보를 읽을 것이므로 _bios_disk의 매개변수는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x00 |
플로피 디스크 드라이브( a:) 인 드라이브 0을 나타냅니다 . |
dinfo.head = 머리 |
플로피에는 두 면(두 개의 헤드)이 있으므로 헤드 번호 0과 1을 가리킵니다. |
dinfo.track = 트랙 |
플로피 디스크의 각 면에 80개의 트랙이 있으므로 0~79번 트랙을 가리킵니다 . |
dinfo.sector = 섹터 |
각 트랙에 18개의 섹터가 있으므로 1~18 섹터를 가리킵니다 . |
dinfo.섹터 = 1 |
읽기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- _bios_disk(_DISK_READ, &dinfo)는 dinfo에서 지정한 섹터의 플로피 디스크의 물리적 표면에서 데이터를 읽습니다 .
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
플로피 디스크의 데이터 이미지를 보관하는 파일의 크기는 항상 정확히 1,474,560바이트여야 합니다. 플로피 디스크에는 80개의 트랙(0~79), 2개의 면 또는 헤드(헤드 0 및 헤드 1)가 있으며 각 트랙에는 18개의 섹터가 있고 각 섹터에는 512바이트의 데이터가 보관되기 때문입니다.
총 바이트 = (트랙 수) * (헤드 수) *
(트랙당 섹터 수) * 512
= 80*2*18*512
= 1,474,560바이트
따라서 플로피 디스크의 어느 섹터를 읽는 중 오류가 발생하면 파일 크기가 1,474,560바이트에서 변경되고, 이로 인해 이 파일의 섹터별로 디스크 이미지를 쓰려는 대상 디스크에 대한 전체 정보가 전혀 또는 부분적으로 쓸모 없게 됩니다.
이는 컴퓨터가 할당 단위에 할당된 섹터 범위 내에서 플로피 디스크 미디어 표면에 있는 모든 파일의 정보를 읽기 때문입니다. 이제 파일 데이터의 섹터가 변경되면 전체 파일 정보가 변경됩니다.
섹터(들) 읽기 오류 해결을 위한 생각
불량이거나 읽을 수 없는 플로피 디스크의 경우 디스크 표면에 너무 많은 불량 부분이 있어서 디스크 표면의 정보를 읽을 수 없는 경우도 있습니다.
이런 상태에서는 해당 섹터의 정보가 건너뛰어지고 플로피 디스크의 이미지가 다른 섹터에서도 왜곡됩니다. 이 경우 이미지 파일의 크기가 1,474,560바이트가 아니기 때문입니다.
이미지 파일의 크기를 유지하고 나머지 정보를 대상 디스크의 정확한 섹터 위치에 붙여넣기 위해 512바이트의 원본 데이터 대신 다른 정보를 씁니다. 이런 방식으로 나머지 정보를 저장할 수 있지만 이 경우 복구는 부분 복구일 수 있습니다.
시스템이 소스 플로피의 첫 번째 섹터를 읽지 못하는 경우, 대상 플로피에 이미지를 붙여넣은 후, 앞서 설명한 프로그램을 실행하여 플로피의 DOS 부트 레코드를 다시 써야 합니다.
프로그래밍을 통해 이를 어떻게 할 수 있는지 살펴보겠습니다.
#include <bios.h>
#include <stdio.h>
void 메인(void)
{
int 헤드,트랙;
노동조합 REGS 규정;
int 결과, i, 섹터;
char 파일명[80];
구조체 diskinfo_t dinfo;
정적 char dbuf[512];
/* 불량 섹터 공간을 채우기 위한 512바이트 정보 */
/// 512바이트 공간을 채우기 위해 512개의 0을 사용했습니다 \\\
정적 문자 dbuf2[512] =
"000000000000000000000000000000000" "000000000000000000000000000000000" "00000000000000000000000000000000" "000000000000000000000000000000000" "000000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "000000000000000000000000000000000" "000000000000000000000000000000000" "00000000000000000000000000000000" "000000000000000000000000000000000" "000000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
파일 *tt;
영어: clrscr();
printf("\n 파일 이름과 저장 경로를 입력하세요.
데이터 일시적으로\n");
gets(파일 이름);
if((tt=fopen(파일명,"wb"))==NULL)
{
printf("파일을 만들 수 없습니다. 아무 키나 누르세요.
출구");
getch();
종료(0);
}
printf("\n 플로피 디스크 시스템 초기화 중...\n");
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
트랙=0;트랙<=79;트랙++)
{
for(머리=0;머리<=1;머리++)
{
섹터=1;섹터<=18;섹터++)
{
dinfo.drive = 0; /* A에 대한 드라이브 번호 */
dinfo.head = head; /* 디스크 헤드 번호 */
dinfo.track = track; /* 트랙 번호 */
dinfo.sector = sector; /* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
결과 = _bios_disk(_DISK_READ, &dinfo);
if ((결과 & 0xff00) == 0)
{
i=0;i<512;i++에 대하여
fprintf(tt, "%c",dbuf[i] & 0xff);
}
또 다른
{
printf("드라이브 A를 읽을 수 없습니다, 상태 =
0x%02x\t%d\t%d\t%d\n", 결과, 헤드, 트랙, 섹터);
/* Sector를 읽을 수 없으면 dbuf2에서 512바이트를 차지합니다. */
fwrite(dbuf2,512,1,tt);
}
printf("읽기 트랙 = %d 헤드 = %d 섹터 = %d\n",
트랙, 헤드, 섹터);
}
}
}
}
프로그램 코딩에 대한 의견:
프로그램 코딩에서 모든 단계는 디스크 읽기 작업 중 불량 섹터로 인해 생성된 오류를 처리 하고 이미지 파일의 크기를 유지하기 위해 사용하는 데이터 버퍼 dbuf2[512]를 제외하고는 이전 프로그램과 동일합니다.
이렇게 하면, 불량 섹터 에서 읽지 못한 정보 공간을 채우고 , 이제 512바이트의 가상 정보를 써서 디스크 이미지의 정확성을 유지할 수 있습니다.
파일의 데이터를 새 플로피 디스크의 물리적 표면에 붙여넣습니다.
이 단계에서는 이전 프로그램에서 파일에 저장된 데이터를 새 플로피 디스크의 물리적 표면에 섹터별로 붙여넣습니다. 이는 파일에 복사한 것과 같은 방식입니다.
이 프로그램은 다음과 같은 주요 단계로 진행됩니다.
- 읽을 수 없는 플로피 디스크의 표면 데이터를 일시적으로 저장한 파일을 엽니다.
- INT 13H의 재설정 기능 00H를 사용하여 디스크 시스템을 올바르게 초기화하세요.
- 파일에서 새 플로피 디스크의 섹터에 대한 정보를 씁니다.
- 쓰기 상태를 동시에 표시하여 오류 발생을 찾거나 방지합니다.
프로그램 소스 코드는 아래에 나와 있습니다. 어떻게 작동하는지 살펴보겠습니다.
/* 이전 프로그램에서 생성한 파일에서 새 플로피 디스크 표면 섹터에 데이터를 쓰는 프로그램 */
#include <bios.h>
#include <stdio.h>
void 메인(void)
{
int 헤드,트랙;
노동조합 REGS 규정;
int 결과, i, 섹터;
int 카운트 = 0;
char 파일명[80];
구조체 diskinfo_t dinfo;
정적 char dbuf[512];
파일 *fp;
영어: clrscr();
printf("\n 파일 이름과 저장 경로를 입력하세요.
데이터 일시적으로\n");
gets(파일 이름);
if((fp=fopen(파일명,"rb"))==NULL)
{
printf("파일을 만들 수 없습니다. 아무 키나 누르세요.
출구");
getch();
출구(1);
}
/// 디스크 시스템 초기화 \\\
i=0; i<3; i++에 대하여
{
regs.h.ah = 0x00; /* 디스크 시스템 재설정 */
regs.h.dl = 0x00; /* 플로피 디스크 a: */
int86(0x13, ®s, ®s);
}
트랙=0;트랙<=79;트랙++)
{
for(머리=0;머리<=1;머리++)
{
섹터=1;섹터<=18;섹터++)
{
카운트 = 0;
while(count<512) (카운트<512)
{
fscanf(fp, "%c", &dbuf[개수]);
카운트++;
}
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = head; /* 디스크 헤드 번호 */
dinfo.track = track; /* 트랙 번호 */
dinfo.sector = sector;/* 섹터 번호 */
dinfo.nsectors = 1; /* 섹터 수 */
dinfo.buffer = dbuf; /* 데이터 버퍼 */
결과= _bios_disk(_DISK_WRITE, &dinfo);
if ((결과 & 0xff00) == 0)
printf("트랙 = %d, 헤드 = %d에 대한 쓰기가 성공했습니다.
섹터 = %d.\n", 트랙, 헤드, 섹터);
또 다른
printf("드라이브 A를 읽을 수 없습니다, 상태 = 0x%02x\n",
결과);
}
}
}
}
프로그램 코딩에 대한 의견:
이전에 제시한 프로그램 코딩에서는 기본적으로 다음 작업을 단계별로 수행합니다.
- 문자 배열 filename[80]은 읽을 수 없는 플로피 디스크의 표면 데이터를 일시적으로 저장한 파일의 경로와 파일 이름을 보관합니다.
- dinfo는 _bios_disk 함수가 수행하는 작업에 필요한 매개변수 정보를 포함하는 diskinfo_t 구조체를 가리킵니다.
- 인터럽트 13H(함수 00h)를 사용하여 디스크 시스템을 초기화합니다. 여기서 regs.h.ah = 0x00은 함수 00 H를 가리키고 regs.h.dl = 0x00은 플로피에 사용됩니다. 그리고 int86(0x13, ®s, ®s)는 MS-DOS 인터럽트 서비스 INT 13 H를 호출합니다.
- 디스크 표면의 섹터에 직접 정보를 기록 할 것이므로 _bios_disk 의 매개변수는 다음과 같습니다.
매개변수 |
그것이 의미하는 바 |
dinfo.드라이브 = 0x00 |
플로피 디스크 드라이브( a:) 인 드라이브 0을 나타냅니다 . |
dinfo.head = 머리 |
플로피에는 두 면(두 개의 헤드)이 있으므로 헤드 번호 0과 1을 가리킵니다. |
dinfo.track = 트랙 |
플로피 디스크의 각 면에 80개의 트랙이 있으므로 0~79번 트랙을 가리킵니다 . |
dinfo.sector = 섹터 |
각 트랙에 18개의 섹터가 있으므로 1~18 섹터를 가리킵니다 . |
dinfo.섹터 = 1 |
쓰기 작업을 위해 고려해야 할 섹터 수 = 1 |
dinfo.버퍼 = dbuf |
작업을 위한 데이터 버퍼 |
- _bios_disk(_DISK_WRITE, &dinfo)는 dinfo에서 지정한 플로피 디스크의 물리적 표면의 섹터에 데이터를 씁니다.
- 반환된 상태는 성공적인 작업에 대한 메시지를 표시하거나 오류가 발생할 경우 화면에 오류 메시지를 표시하는 데 사용되는 result에 저장됩니다.
방법 2를 시도한 후에도 새 플로피 디스크가 작동하지 않으면 방법 2를 시도할 때 대상 디스크로 사용한 새 플로피 디스크에 방법 1을 다시 적용할 수 있습니다.
이것뿐만 아니라 디스크 손상에 따라 히트와 시도 횟수도 달라질 수 있습니다. 그러나 만족스러운 결과를 얻지 못하더라도 걱정할 필요는 없습니다.
파일별로 복구를 시도하거나 다음에 배울 수 있는 더 많은 팁을 시도할 수 있습니다. 여기서 우리는 데이터를 복구하기 위한 프로그래밍에서 루트 디렉토리에서 파일 정보를 수집하는 아이디어를 구현할 것입니다.
삭제되거나 손실된 데이터에 대한 논리적 복구에 대한 생각:
이 장에서 논의했던 이전의 모든 복구 사례는 DBR만 손상되었고 FAT1, FAT2 및 루트 디렉터리가 있는 트랙 0의 섹터는 읽을 수 있다고 예상하는 경우에만 데이터를 복구하는 것이었습니다 .
하지만 문제가 FAT 손상으로 인한 것이거나 디스크에서 데이터가 삭제된 경우 또는 루트 디렉토리에서 해당 정보를 읽어 직접 데이터를 복구 하려는 경우, 루트 디렉토리 항목 에서 파일 이름 , 시작 클러스터 , 파일 크기 , 속성 등 의 정보를 읽어야 합니다 .
이전 장에서 루트 디렉토리 에 대해 이미 논의했듯이 각 파일이나 디렉토리에 대해 32바이트의 정보가 있습니다. 이 32바이트는 다음과 같이 나뉩니다.
바이트 수 |
정보 설명 |
8바이트 |
파일 이름 |
3바이트 |
확대 |
1바이트 |
기인하다 |
10바이트 |
예약된 |
2바이트 |
시간, 생성 또는 마지막 업데이트 |
2바이트 |
날짜, 생성 또는 마지막 업데이트 |
2바이트 |
클러스터 시작 |
4바이트 |
파일 크기 |
루트 디렉토리 에서 파일 정보를 읽어 데이터를 복구한 다음 파일을 대상 경로에 통합하고 파일을 복구합니다. 다음 프로그램은 다음 단계를 수행하여 데이터를 복구합니다.
- 루트 디렉토리 항목을 읽고 파일/디렉토리 이름, 파일 확장자, 파일의 시작 클러스터 크기(바이트) 등의 모든 정보와 함께 화면에 표시합니다.
- 하위 디렉토리에 있는 파일 및 디렉토리 정보를 읽고 필요한 경우 표시합니다.
- 복구할 파일 이름을 확인하고 복구를 계속하세요.
- 복구할 지정된 파일에 대한 CHS(실린더, 헤드, 섹터) 정보를 계산합니다 .
- 디스크의 데이터 영역에서 파일의 데이터를 통합하고 복구된 파일을 지정된 경로의 지정된 대상 파일 이름에 저장합니다.
이 프로그램은 플로피의 부팅 정보를 읽을 수 있는지 여부 에 상관하지 않습니다 . 따라서 손상된 플로피 디스크 에서 삭제된 데이터도 복구 할 수 있습니다 . 프로그램의 코딩을 살펴보겠습니다.
/* 루트 디렉토리에서 파일 정보를 읽어 플로피 디스크에서 데이터를 복구하는 프로그램 */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void 메인()
{
void Display_Information(unsigned int,unsigned int,
부호 없는 int);
부호 없는 int 트랙=0, 헤드=1, 섹터=2;
디스플레이_정보(트랙,헤드,섹터);
} /*메인 끝 */
void Display_Information(unsigned int track,
서명되지 않은 int 헤드,
부호 없는 int 섹터)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // 512바이트 버퍼
문자 ch;
struct diskinfo_t finfo; //구조, _bios_disk에서 사용됨
unsigned int result,i,j, count=0; /* 부호 없는 정수
정의됨 */
unsigned int file_no; /* 부호 없는 정수
파일 번호 */
구조
{
unsigned int name[8],ext[3]; /* 8.3의 DOS용 파일 이름
(8점 3점) 형식 */
unsigned int 속성; // 파일/디렉토리 속성
unsigned int start; // 파일 클러스터 시작
long unsigned int size; // 파일 크기(바이트)
}root[32]; /* 32바이트 정보
루트의 파일/디렉토리
디렉토리 */
영어: clrscr();
하다
{
파일 번호=0;
finfo.drive = 0x00; /* A에 대한 드라이브 번호 */
finfo.head = head; /* 디스크 헤드 번호 */
finfo.track = track; /* 트랙 번호 */
finfo.sector= sector; /* 섹터 번호 */
finfo.nsectors=1; /* 섹터 수 */
finfo.buffer = buf; /* 데이터 버퍼 */
result = _bios_disk(_DISK_READ, &finfo); /* 읽기
섹터 */
if( (result & 0xff00) != 0) /* 읽기 오류가 발생하면 표시
오류 메시지 및 종료*/
{
printf("읽기 오류");
getch();
exit(0); // DOS로 돌아가기
}
/// 정보 표시 화면 형식 \\\
영어: clrscr();
고톡시(9,1);
cprintf("디스플레이 실린더: %u, 헤드: %u, 섹터: %u",
트랙, 헤드, 섹터);
고톡시(9,2);
cprintf("FNO 이름 확장 속성 시작 크기");
고톡시(7,3);
cprintf("-------------------------------------");
/* 한 번에 한 섹터. 모든 파일/디렉토리 항목은 32바이트를 차지합니다. */
i=0;i<512;i+=32에 대하여
{
j=0;j<8;j++에 대하여
{
/// 파일/디렉토리 이름 찾기 \\\
root[파일_번호].이름[j]=buf[j+i];
}
j=8;j<11;j++에 대하여
{
/// 확장자 찾기 \\\
루트[파일_번호].ext[j-8]=buf[i+j];
}
j=11;
root[파일_번호].속성=buf[i+j]; /// 속성
/// 클러스터 시작 \\\
root[파일_번호].시작=(0xff & 버퍼[27+i])*16*16 + (0xff & 버퍼[26+i]);
/// 크기 계산 \\\
root[파일_번호].size =(long unsigned int)(0xff &
버퍼[31+i])*16*16*16*16*16*16*16*16;
root[파일_번호].size+=(long unsigned int)(0xff &
버퍼[30+i]*16*16*16*16;
root[파일_번호].size+=(long unsigned int)(0xff &
버퍼[29+i])*16*16;
root[파일_번호].size+=(long unsigned int)(0xff &
버퍼[28+i]);
if((root[파일_번호].시작 == 0) ||
(root[파일_번호].속성 == 15))
계속하다;
또 다른
{
고톡시(8,i/32+4);
cprintf("%2u",file_no); /* 파일 표시
숫자 */
j=0;j<8;j++에 대하여
{
고톡시(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* 파일 표시
이름 */
}
j=0;j<3;j++에 대하여
{
고톡시(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* 표시
확대 */
}
고톡시(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* 표시
기인하다 */
루트[파일_번호].속성==16인 경우
{
고톡시(33,i/32+4);
cprintf("<DIR>"); /* 디렉토리 속성이 있는지 표시 */
}
또 다른
{
고톡시(33,i/32+4);
cprintf("<FILE>"); /* 항목은 파일의 항목입니다. */
}
고톡시(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* 표시
클러스터 시작 */
고톡시(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* 파일 크기
파일 */
}
파일_번호++;
}
고톡시(10,
cprintf("더 많은 파일 목록을 보려면 'M'을 누르세요&quo
고톡시(10,
cprintf("R을 누르세요: 위의 파일을 복구하려면
목록&quo
ch=getc
s로 시작하는 파일 이름(E5H)은 파일이 삭제되었고 따라서 파일 이름의 첫 번째 문자가 s로 바뀌었음을 나타냅니다(이전 장의 루트 디렉토리 설명 참조).
그리고 프로그램의 출력은 다음과 같이 표시됩니다.
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
------------------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <파일> 5 4700
2 THELP CFG 32 <파일> 2 22
3 THELP COM 32 <파일> 3 11072
4 TIMEIT CPP 32 <파일> 39 1186
5 TOUCH COM 32 <파일> 42 5124
6 TRY1 CPP 32 <파일> 53 1581
7 TURBOC CFG 32 <파일> 57 30
8 AA CPP 32 <파일> 58 260
9 ABC CPP 32 <파일> 59 1036
10 ASSIGN1 CPP 32 <파일> 62 4257
11 CH24_2 CPP 32 <파일> 71 834
12 sBSDISK1 C 32 <파일> 73 911
13 sH24_25 C 32 <파일> 75 594
14 sBSDISK C 32 <파일> 77 840
'M'을 누르세요: 더 많은 파일 목록을 보려면
'R'을 누르세요: 위 목록에서 파일을 복구하려면 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 <파일> 5 4700
2 THELP CFG 32 <파일> 2 22
3 THELP COM 32 <파일> 3 11072
4 TIMEIT CPP 32 <파일> 39 1186
5 TOUCH COM 32 <파일> 42 5124
6 TRY1 CPP 32 <파일> 53 1581
7 TURBOC CFG 32 <파일> 57 30
8 AA CPP 32 <파일> 58 260
9 ABC CPP 32 <파일> 59 1036
10 ASSIGN1 CPP 32 <파일> 62 4257
11 CH24_2 CPP 32 <파일> 71 834
12 sBSDISK1 C 32 <파일> 73 911
13 sH24_25 C 32 <파일> 75 594
14 sBSDISK C 32 <파일> 77 840
복구하려는 파일의 FNO를 입력하세요. 1
복구하려고 합니다. _2_INFO .C
실린더 = 1, 헤드 = 0, 섹터 = 1 통합........
파일을 복구할 경로와 파일 이름을 입력하세요: c:\windows\desktop\H2_INFO.C
복구 완료!!!
|
코딩에 대한 의견:
Display_Information 함수는 루트 디렉토리에서 파일 및 디렉토리 정보를 읽는 것 입니다 . Structure에서 우리는 root[32]가 있는 모든 파일 또는 디렉토리에 대한 32바이트 정보를 읽고 있습니다.
부호 없는 정수 배열 name[8] 및 ext[3]은 DOS 8.3(Eight Dot Three) 형식의 파일 또는 디렉토리 이름용입니다. 마찬가지로 1바이트는 속성용이고 2바이트는 시작 클러스터용입니다. long unsigned int size;는 4바이트의 파일 크기를 저장합니다.
_bios_disk 함수 는 finfo 구조체로 지정된 섹터를 읽고 작업 상태는 result에 저장됩니다.
_bios_disk 함수 에서 읽은 512바이트의 모든 정보부터 루트 디렉토리 영역이 끝날 때까지 디스크에 저장된 파일과 디렉토리의 정보를 수집하여 화면에 표시해줍니다.
정수 file_no는 0부터 시작하여 목록에 있는 파일이나 디렉토리의 번호를 저장합니다. 일반적으로 루트 디렉토리의 크기는 14개 섹터이고 루트 디렉토리는 일반적으로 1.44MB 및 3½ 플로피 디스크의 경우 실린더 = 0, 헤드 = 0, 섹터 = 2에서 시작합니다.
사용자가 문자 'M' 또는 'm'을 입력으로 제공하면 사용자의 선택이 'R' 또는 'r'인 경우 다음 섹터의 정보가 표시되고 복구 함수가 호출됩니다. recover() 함수의 코딩은 다음과 같습니다.
/* 지정된 파일에 대한 복구를 시작하는 함수 */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* 화면의 행을 지우는 함수 */
/* 지정된 파일을 통합하는 함수 */
void integrated(long unsigned int, unsigned int,
부호 없는 int,부호 없는 int);
부호 없는 int 파일_번호,i;
문자 ch;
부호 없는 int *loc;
부호 없는 int 실린더, 헤드, 섹터;
부호 없는 int 시작;
긴 부호 없는 int 크기;
clear_the_line(21); /* 행 번호 21 지우기 */
clear_the_line(22); /* 행 번호 22 지우기 */
clear_the_line(23); /* 행 번호 23 지우기 */
clear_the_line(24); /* 행 번호 24 지우기 */
고톡시(10,21);
cprintf("복구하려는 파일의 FNO를 입력하세요");
scanf("%u",&file_no); /* 파일 번호를 가져옵니다.
복구됨 */
위치=(루트+(파일_번호*길이/2));
/* 복구할 파일 이름 확인 */
고톡시(10,22);
cprintf("복구를 원합니다");
i=0;i<8;i++에 대하여
{
고톡시(30+i,22);
cprintf("%c",*(loc+i)); /* 파일 이름 */
}
고톡시(38,22);
cprintf(".");
i=0;i<3;i++에 대하여
{
고톡시(39+i,22);
cprintf("%c",*(loc+8+i)); /* 파일 확장자 */
}
시작=*(위치+12);
/// 죄송합니다. 디렉토리를 선택하셨습니다 \\\
if(*(loc+11)==16)
{
고톡시(5,23);
cprintf("디렉토리입니다. 디렉토리를 보시겠습니까?
이 디렉토리의 내용 Y/N");
ch=게치();
만약(ch==27)
기본();
if(ch=='y' || ch=='Y')
{
/* 기하학 계산 */
계산(시작, 실린더, 헤드, 섹터);
/* 디렉토리 내용 표시 */
디스플레이_정보(실린더, 헤드, 섹터)
}
또 다른
/* 파일을 다시 요청하고 복구를 계속합니다. */
복구(루트, 길이);
}
또 다른
{
크기=*(위치+13);
/* CHS 정보를 계산합니다 */
계산(시작, 실린더, 헤드, 섹터);
/* 파일 통합 */
통합(크기, 실린더, 헤드, 섹터);
}
}
코딩에 대한 의견:
recover() 함수는 복구를 시작하기 위한 사용자 입력을 얻는 것입니다. 사용자가 파일을 복구하기 위해 입력한 파일 번호는 file_no에 저장됩니다.
입력한 번호가 디렉토리 항목에 대한 것이면, Display_Information()은 해당 디렉토리의 내용을 표시하고, 그렇지 않으면 복구할 파일을 확인하기 위해 파일 번호 file_no의 파일 이름과 확장자가 화면에 표시됩니다.
지정된 파일을 복구 하려면 calculate() 및 integrated() 함수가 함수 내에서 호출됩니다. calculate() 함수의 코딩은 아래와 같습니다.
/* 복구를 위한 CHS 기하학을 계산하는 함수 */
void calculate(unsigned int 시작, unsigned int *실린더,
부호 없는 int *head, 부호 없는 int *sector)
{
부호 없는 int temp;
*실린더=0;
*머리=1;
*섹터=14;
시작<5인 경우
*섹터=14+시작;
또 다른
{
온도 = (시작-4)/18;
만약(온도>0)
{
만약(온도%2==0)
*머리=0;
또 다른
*머리=1;
*실린더+=1+온도/2;
}
또 다른
{
*머리=0;
*실린더=1;
}
*섹터=(시작-4)%18;
}
/// 복구할 파일의 CHS 표시 \\\
고톡시(10,23);
cprintf("실린더 = %u, 헤드 = %u, 섹터 = %u",
*실린더, *헤드, *섹터);
}
코딩에 대한 의견:
calculate() 함수는 복구할 파일의 실린더, 헤드, 섹터 정보를 계산하는 것입니다 . 계산 후 실린더, 헤드, 섹터 번호가 화면에 표시됩니다.
integrated() 함수의 코딩은 아래와 같습니다.
/* 파일을 통합하고 복구된 파일을 지정된 경로 및 파일 이름으로 저장 */
void integrated(long unsigned int 크기,
부호 없는 int 실린더,
서명되지 않은 int 헤드,
부호 없는 int 섹터)
{
void clear_the_line(부호 없는 int);
/* 오류에 대한 섹터를 확인하는 함수 */
int verify_the_sector(unsigned int, unsigned int,
부호 없는 int);
int 상태;
char buf[512],*경로가 있는 파일 이름;
구조체 diskinfo_t dinfo;
부호 없는 int 결과;
파일 *fp;
부호 없는 int left,i;
부호 없는 int 초;
/* 복구된 파일을 저장할 대상 경로와 파일 이름을 입력하세요 */
고톡시(2,24);
cprintf("파일을 복구하려면 경로와 파일 이름을 입력하세요: ");
fflush(표준입력);
gets(파일이름과 경로)
fp=fopen(경로가 있는 파일 이름, "wb");
/* 오류가 발생하면 오류 메시지를 표시하고 입력 경로와 파일 이름을 다시 가져옵니다. */
if(fp==NULL)
{
고톡시(5,25);
cprintf("파일을 여는 중 오류가 발생했습니다.");
getch();
줄을 지우세요(24);
고톡시(0,25);
cprintf(" ");
integrated(size,cylinder,head,sector); /* 다음을 입력하세요.
다시 목적지 */
}
/* 모든 것이 괜찮다면 통합하고 작성하세요 */
고톡시(50,23);
cprintf("통합 중........");
왼쪽= size%512;
초 = 크기/512;
초++;
while(초>0)
{
dinfo.drive = 0x00; /* A에 대한 드라이브 번호 */
dinfo.head = head; /* 디스크 헤드 번호 */
dinfo.track = cylinder; /* 트랙 번호 */
dinfo.sector= sector; /* 섹터 번호 */
dinfo.nsectors=1; /* 섹터 수 */
dinfo.buffer = buf; /* 데이터 버퍼 */
결과 = _bios_disk(_DISK_READ, &dinfo);
/* 섹터를 읽는 동안 오류가 발생하는 경우 */
if((결과 & 0xff00) != 0)
{
고톡시(5,25);
cprintf("읽기 오류 실린더 %u, 헤드 %u, 섹터 %u",
실린더, 헤드, 섹터);
}
또 다른
{
만약(초==1)
{
i=0;i<left;i++에 대하여
fputc(buf[i],fp); /* 통합을 작성합니다.
파일에 대한 정보 */
}
또 다른
{
fwrite(buf,512,1,fp);
}
코딩에 대한 의견:
integrated() 함수는 이 복구 프로그램 에서 사용자가 지정한 파일의 복구를 수행하는 실제 모듈입니다 .
복구된 파일을 저장할 대상 경로가 있는 파일 이름은 문자 포인터 *Filename_with_path에 저장됩니다. 대상 파일을 여는 데 오류가 있으면 오류 메시지가 표시되고 사용자에게 대상을 입력하라는 메시지가 다시 표시됩니다.
함수 _bios_disk(_DISK_READ, &dinfo);는 구조 dinfo에 의해 지정되고 데이터 버퍼 buf에 저장된 디스크 섹터의 데이터 영역에서 섹터별로 파일의 데이터를 읽습니다. 이 512바이트 데이터는 대상 파일에 기록됩니다. 이것은 완전한 파일이 통합될 때까지 반복됩니다.
함수 status=verify_the_sector (cylinder,head,sector);는 읽을 섹터를 검증합니다. status = 10이면 불량(0xA) 섹터를 나타냅니다. 함수의 코딩은 아래와 같습니다.
/// 섹터를 확인합니다. (여기서는 데이터가 전송되지 않습니다) \\\
int verify_the_sector(unsigned int c, unsigned int h, unsigned int s)
{
int 상태;
char *buf;
union REGS in, out;
구조체 SREGS sg;
in.h.ah = 0x04; /* 함수 번호 */
in.h.al = 1; /* 검증할 섹터 수*/
in.h.dl = 0x00; /* A에 대한 디스크 번호: */
in.h.ch = c; /* 실린더 번호 */
in.h.dh = h; /* 헤드 번호 */
in.h.cl = s; /* 섹터 번호 */
in.x.bx = FP_OFF(buf);/* 오프셋 */
sg.es = FP_SEG(버프); /* 세그먼트 */
int86x(0x13,&in,&out,&sg); /* 4H 함수 호출
INT 13H부터 */
if(out.x.cflag)
{
상태=out.h.ah;
}
반환(상태);
}
코딩 주석:
verify_the_sector() 함수는 _bios_disk() 함수에서 읽을 섹터를 검증하고 작업 상태를 반환합니다. 이 함수는 INT 13H와 함수 4H를 사용하여 섹터를 확인합니다.
*buf — 데이터 버퍼, 0x04 — in.h.ah = 0x04로 지정된 함수 번호 그리고 in.h.al = 1; 한 번에 한 부문만 검사해야 함을 나타냅니다. in.h.dl = 0x00; 플로피 디스크 드라이브 번호 A:, c, h, s에 사용되는 것은 실린더, 헤드, 섹터 번호입니다 .
int86x() 함수는 세그먼트 레지스터 값 으로 INT 13H(함수 4H)를 호출하는 데 사용됩니다 . 작업 상태는 정수 상태로 반환됩니다.
clear_the_line() 함수는 화면에서 지정된 줄을 지웁니다. 함수 인코딩은 다음과 같습니다.
/* 지정된 줄 번호만큼 화면에서 줄을 지우는 함수 */
void clear_the_line(부호 없는 정수 문자열)
{
부호 없는 정수 열;
/* 행에는 80개의 열이 있습니다 */
for(열=1;열<=80;열++)
{
gotoxy(열,행);
cprintf(" "); /* " "로 지우기 */
}
}
코딩 주석:
해당 함수는 화면에서 지정된 줄을 지우는 데 사용됩니다 . 해당 함수는 화면에서 지워야 하는 줄 번호와 함께 호출됩니다.