디렉토리 정보 유틸리티를 작성 했으므로 (나는이 컴퓨터를 & 빈티지 하드웨어를 사용하여 수집했기 때문에) DOS와 Windows 9x 및 Windows와 호환 가능하도록 만들었습니다. XP/Vista/7/8 64-bit (우리는 그것도 사용했기 때문에). 문제는 Windows 9x 및 FAT32 드라이브에서 발생했습니다. 필자는 Windows 9x가 실제로로드 된 상태에서 작동하도록했습니다. 그러나 명령 프롬프트로만 부팅하거나 MS-DOS 모드로 다시 시작하면 큰 드라이브 데이터를 가져올 수있는 Windows API에 대한 액세스 권한을 잃게됩니다. 내가 갖고있는 DOS 루틴으로 다시 돌아왔다. 이는 2GB 제한 루틴으로 제한됩니다. DOS 7.x 프로그램 (chkdsk 주로)이 (올바른 드라이브 크기를보고하는 데 아무런 문제가 없으므로)이 문제를 처리하는 방법을 살펴보면 DOS 인터럽트 (주로 INT 21h)를 사용하는 것으로 보입니다. 생각해도 괜찮습니다. 빠른 버전 확인을 할 것입니다. DOS 7 이상이면 빠른 어셈블리 라우팅을 실행하여 드라이브 구조를 가져 와서 총 여유 공간을 계산합니다 (예 : &). 루틴 (오류는 반환되지 않지만) 만 버퍼에 아무 것도 채우지 않습니다. 마지막 비트는 오해 무슨 일이 있었는지 알아 내려고 노력했다DOS 7.x에서 큰 드라이브 구조 정보 얻기
#include <stdio.h>
#include <dos.h>
void main(void) {
unsigned short hes,hdi,sectors,bytes;
unsigned long tclusters,fclusters;
unsigned char far *drivedata;
char test = '\0';
char display[17] = "ABCDEF";
int count;
drivedata = new unsigned char [63];
for (count = 0; count < 63; count++) drivedata[count] = '\0';
drivedata[0] = '\x3d';
drivedata[1] = '\x00';
hes = FP_SEG(drivedata);
hdi = FP_OFF(drivedata);
asm {
push ax
push es
push di
push ds
push dx
push cx
mov ax,0x440d
mov bx,0x0003
mov cx,0x484a
int 21h
jnc _GOOD
mov ax,0x7302
mov es,[hes]
mov di,[hdi]
mov dx,0x0003
mov cx,0x003f
int 21h
jnc _GOOD
}
test = '\1';
_GOOD:
asm {
mov ax,0x440d
mov bl,0x03
mov cx,0x486a
int 21h
pop cx
pop dx
pop ds
pop di
pop es
pop ax
}
if (test == '\1') {
printf("There was an error.\r\n");
return;
}
tclusters = (unsigned long) drivedata[48];
tclusters = (tclusters * 256) + (unsigned long)drivedata[47];
tclusters = (tclusters * 256) + (unsigned long)drivedata[46];
tclusters = (tclusters * 256) + (unsigned long)drivedata[45];
++tclusters;
fclusters = (unsigned long)drivedata[36];
fclusters = (fclusters * 256) + (unsigned long)drivedata[35];
fclusters = (fclusters * 256) + (unsigned long)drivedata[34];
fclusters = (fclusters * 257) + (unsigned long)drivedata[33];
bytes = (unsigned int)drivedata[5];
bytes = (bytes * 256) + (unsigned int)drivedata[4];
sectors = (unsigned long)drivedata[6];
++sectors;
printf("Drive C has:\r\n");
printf(" Total Clusters: %u\r\n",tclusters);
printf(" Free Clusters: %u\r\n",fclusters);
printf(" Sectors: %u\r\n",sectors);
printf(" Bytes: %u\r\n",bytes);
printf("\r\n");
printf(" | 0 1 2 3 4 5 6 7 8 9 A B C D E F\r\n");
printf("---------------------------------------------------------------------");
for (count = 0; count < 63; count++) {
if ((count % 16) == 0) printf("\r\n %c | ",display[(count/16)]);
printf("%03u ",drivedata[count]);
}
printf("\r\n");
return;
}
: 여기
는 코드입니다. 나는 이상한 결과를 얻고 있었고 패턴을 이해할 수 없었다. 원래, INT 버퍼가 자신의 값으로 채워 져야했기 때문에 버퍼를 지우는 것에 대해 걱정하지 않았습니다 (EDB 데이터 버퍼 크기로 채워지는 처음 2 바이트 제외). 무작위 결과, 처음에 버퍼에 0을 채우기 위해 루프에 추가 한 다음 버퍼 크기를 추가합니다. 그 시점에서 결과는 무작위로 멈추었습니다. 항상 INT 0이 버퍼를 채우지 못하고 있다는 것을 의미합니다. 다양한 테스트를 통해 heshdi에 버퍼 주소의 세그먼트와 오프셋이 올바르게 할당되었음을 확인했습니다. 또한 버퍼 주소 대신 포인터 주소에 es & di를 시도했습니다. 나는 내가 읽은 모든 것이 그것이 포인터가 아니라 주소로 설정되었다고 생각할 때 그것이 효과가있을 것이라고 생각하지 않았지만, 나는 내가 생각할 수있는 모든 것을 시도하고 있었다. 모든 경우에 버퍼가 아무것도 채워지지 않습니다.당신이 아마 말할 수 있듯이, 이것은 주 프로그램에 추가하기 전에 정확한 절차를 알아 내려고하는 시험 프로그램입니다. (이 문제를 제외하면 잘 작동합니다.) FP_ 라인은 단지 세그먼트에 대해 (부호없는 long) (x & 0xffff0000) >> 16 및 오프셋에 대해 (부호가없는 long) (x & 0x0000ffff)로 명시 될 수있는 매크로. 일반적으로 포인터 (& drivedata)를 전달하지만 drivedata는 이미 포인터입니다.
실제 출력은 :
Drive C has:
Total Clusters: 1
Free Clusters: 0
Sectors: 1
Bytes: 0
| 0 1 2 3 4 5 6 7 8 9 A B C D E F
---------------------------------------------------------------------
0 | 061 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
1 | 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
2 | 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
3 | 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
그래서, 내가 뭘 놓친 거지? chkdsk와 마찬가지로, 전에 드라이브를 잠그고 호출 후 잠금을 해제합니다 (필자는 필요성을 확신하지 못합니다.) 어떻게이 작업을 올바르게 수행 할 수 있습니까? 또는 INT 21h를 사용하는 것보다 드라이브 구조 (클러스터, 섹터 당 바이트 수, 섹터 당 바이트 수)를 얻는 더 좋은 방법이 있습니까? 검색에서 찾은 모든 것은 사용자가 명령 프롬프트로 부팅하는 등의 경우에 액세스 할 수없는 Windows API 함수를 가리 킵니다.
코드를 잘못 읽었습니까? 드라이브 잠금에 성공하면 코드를 건너 뛰고 데이터를 읽는 것처럼 보입니다. 그것을 실패하면, 아마 1) SI를 0xF1A6으로 설정하십시오. 2) dl을 0x80으로 설정하십시오. 3) 더 큰 버퍼 사용 (256?). –
사실, 당신은 그렇지 않습니다 :/나는 그것을 놓쳤습니다 .... 지금 다시 컴파일 ... 잠깐. – user3399848
*** sigh *** 그래, 실패시 건너 뛰는 대신 성공에 관한 코드를 건너 뛰었습니다. jnc opcode를 jc로 변경하고 새 레이블에 추가 (적절하게 양호/나쁜 플래그를 변경). 글쎄, 지금은 수치가 나오기는하지만 데이터를 얻고 있습니다. 이제 더 많은 테스트를 할 예정입니다. 감사합니다. – user3399848