在DOS 7.x中获取大型驱动器结构信息

use*_*848 5 c++ assembly dos

我写了一个目录信息实用程序,(因为我和我为此收集和使用老式硬件而写的人)使它兼容DOS和Windows 9x以及Windows XP/Vista/7/8 64位(因为我们也使用那些.)我遇到的问题是Windows 9x和FAT32驱动器.只要Windows 9x实际加载,我设法让它工作,但如果我只启动到命令提示符,或者在MS-DOS模式下重新启动,我将失去对Windows API的访问权限,这使我能够获取大型驱动器数据并且它违反了我的DOS惯例.这些仅限于2GB限制例程.检查DOS 7.x程序(主要是chkdsk)如何处理这个(因为它们报告正确的驱动器大小没有问题),它们似乎使用DOS中断(主要是INT 21h,)来做到这一点.思考,没问题,我会做一个快速版本检查,如果它是DOS 7或更高版本,我将只运行快速装配路由以获得驱动器结构并计算总的和可用空间.只是,例程(虽然它没有返回错误)不会填充我的缓冲区.

这是代码:

#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] = "0123456789ABCDEF";
    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;
}
Run Code Online (Sandbox Code Playgroud)

最后一点是我试图弄清楚出了什么问题.我得到了奇怪的结果,无法弄清楚一个模式.最初,我并不担心清除缓冲区,因为INT调用应该用它自己的值填充它(前2个字节除外,它应该用EDB数据缓冲区大小填充.)显然有这么多随机结果,我在开始的循环中添加了用零填充缓冲区,然后添加缓冲区大小.结果在那一点上停止了随机,它们总是全为零,这意味着INT调用没有填充缓冲区.通过各种测试,我已经确认hes&hdi被正确地分配了缓冲区地址的段和偏移量.我也尝试了es&di到指针地址而不是缓冲区地址.我不认为它会起作用,因为我读到的所有东西都把它设置为地址而不是指针,但我正在尝试我能想到的一切.在所有情况下,缓冲区都没有充满任何东西.

你可能会说,这只是一个测试程序,我正在编写,以确定在将其添加到我的主程序之前的确切程序(除了这一个问题之外它工作正常.)FP_行只是宏可以是陈述为(无符号长整数)(x&0xffff0000)>> 16代表段和(无符号长整数)(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 
Run Code Online (Sandbox Code Playgroud)

那么,我错过了什么?CHKDSK一样,我之前锁定驱动器和呼叫后解锁它(虽然我不知道必要性.)我怎样才能得到这个工作吗?或者,是否有更好的方法来获得驱动器结构(集群,每个集群的扇区,每个扇区的字节数),而不是使用INT 21h?我在搜索中找到的所有东西都只指向Windows API函数,用户无权访问它们,如果它们执行启动命令提示等...

zmb*_*mbq 1

哇,使用 DOS,那是老派了!不像使用打孔卡那样老式,但仍然......

显然,FreeDOS支持FAT 32。您可能会尝试在那些甚至没有安装 Windows 95 的计算机上安装它。

  • 构建老式系统的人们倾向于坚持使用当时使用的操作系统。我的小程序可以在 DOS 3+ 上运行(实际上这是我想要安装和测试的最早版本,可能会更早。)它也可以在现代系统上运行(例如我的 Windows 7 64 位)。 ,是 DOS 7(Windows 9x 启动到命令提示符。)这就是我现在正在尝试的工作,DOS 7。仅供参考,当他们发明键盘时我真的很高兴,打孔卡是真正的 PITA。 (3认同)