2014-09-08 4 views
5

디렉토리 정보 유틸리티를 작성 했으므로 (나는이 컴퓨터를 & 빈티지 하드웨어를 사용하여 수집했기 때문에) 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

코드를 잘못 읽었습니까? 드라이브 잠금에 성공하면 코드를 건너 뛰고 데이터를 읽는 것처럼 보입니다. 그것을 실패하면, 아마 1) SI를 0xF1A6으로 설정하십시오. 2) dl을 0x80으로 설정하십시오. 3) 더 큰 버퍼 사용 (256?). –

+1

사실, 당신은 그렇지 않습니다 :/나는 그것을 놓쳤습니다 .... 지금 다시 컴파일 ... 잠깐. – user3399848

+1

*** sigh *** 그래, 실패시 건너 뛰는 대신 성공에 관한 코드를 건너 뛰었습니다. jnc opcode를 jc로 변경하고 새 레이블에 추가 (적절하게 양호/나쁜 플래그를 변경). 글쎄, 지금은 수치가 나오기는하지만 데이터를 얻고 있습니다. 이제 더 많은 테스트를 할 예정입니다. 감사합니다. – user3399848

답변

1

와우, DOS를 사용하는 것은 구식입니다! 펀치 카드를 사용하는 것과 같이 구식이 아닌 ...

분명히 FreeDOSFAT 32 support입니다. Windows 95가 설치되어 있지 않은 시스템에도 설치하려고 할 수 있습니다.

+3

빈티지 시스템을 만드는 사람들은 당시 사용하던 OS를 고수하는 경향이있다. 내 작은 프로그램은 DOS 3에서 작동한다. + (설치 및 테스트를 위해 내가 망설였던 것만 큼 멀었습니다.) 또한 현대 시스템에서 작동합니다 (예 : Windows 7 64 비트). DOS 7 (Windows 9x 명령 프롬프트로 부팅했습니다.) 그게 내가 도스 7을 작동시키려는 것입니다. 키보드를 발명했을 때 정말 기뻤습니다. 펀치 카드는 진짜 피타였습니다. – user3399848

+0

와우, 꼭 확인해야합니다. 이 CP/M! – zmbq

1

빈티지 취미의 경우 LBAFAT32 사양을 착용해야하며 Wikipedia: File Allocation Table은 좋은 링크가있는 것 같습니다.

당신이 알 수있는 한 가지 사실은 기존 시스템 (및 그에 대해 작성된 소프트웨어)이 정상적으로 디스크 크기 (디스크 크기> 2^(32-1))를 정상적으로 처리하지 못했다는 것입니다. 내가 생각

다른 재료도 매우 중요 할 것입니다 :

BIOS를 사용하는 것 모든 경우에 당신을 위해 일해야하는 "더 좋은 방법은"찾아 호출 모든 기본 사항을 적용한 다음 자신의 코드에서 크기 등을 계산하기위한 알고리즘을 복제합니다. 이전 DOS 시대에는 타사 프로그램에 사용할 수있는 API를 쉽게 재사용 할 수 없었습니다. 고급 기능을 수행해야하는 프로그램은 자체적으로 베어 본 방법을 알아야했습니다.

+1

지금 BIOS 호출을 사용하고 있습니다. 문제가 발생했습니다. 나는 LBA와 FAT32에 대해 읽었습니다. 제가 처음으로 작은 유틸리티를 쓸 때 나는 그 모든 것을했습니다. 위에서 볼 수 있듯이 내 문제는 내 자신의 모든 창조물이었습니다. 미안 해요, 전 전문 프로그래머가 아니에요, 그냥 아마추어예요. 나는 지금 대부분 고쳐 졌어. (실제 유틸리티 코드에서) 추적 할 수있는 사소한 버그와 CD-ROM에 대한 해결책이 완성되었습니다. – user3399848