C++ 在DOS 7.x中获取大型驱动器结构信息
我编写了一个目录信息实用程序(因为我和我为collect&use vintage hardware编写的人)使其与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或更高版本,我只会运行一个快速组装路由,以获得驱动器结构,并以此方式计算总的可用空间。只是,例程(尽管它没有返回错误)没有用任何东西填充我的缓冲区 代码如下:C++ 在DOS 7.x中获取大型驱动器结构信息,c++,assembly,dos,C++,Assembly,Dos,我编写了一个目录信息实用程序(因为我和我为collect&use vintage hardware编写的人)使其与DOS和Windows 9x以及Windows XP/Vista/7/8 64位兼容(因为我们也使用这些)。我遇到的问题是Windows 9x和FAT32驱动器。只要Windows 9x实际加载,我就设法让它工作,但如果我只启动到命令提示符,或在MS-DOS模式下重新启动,我将无法访问允许我获取大驱动器数据的Windows API,它将默认返回到我拥有的DOS例程。这些限制仅限于2G
#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;
}
那么,我错过了什么?像chkdsk一样,我在调用之前锁定驱动器,在调用之后解锁驱动器(尽管我不确定是否有必要)。如何才能使其正常工作?或者,是否有比使用INT 21h更好的方法获得驱动器结构(集群、每个集群的扇区、每个扇区的字节数)?我在搜索中找到的所有东西都只指向Windows API函数,如果用户执行引导到命令提示符等操作,他们将无法访问这些函数。哇,使用DOS,这是老生常谈!不像使用打孔卡那样老派,但仍然
很明显,他有。您可以尝试将其安装在那些甚至没有安装Windows 95的机器上。对于您的传统爱好,您应该为自己配备
LBA
和FAT32
规范,这些规范似乎有很好的链接
您可能会发现,这些遗留系统(以及为它们编写的软件)无法正常处理大型磁盘(磁盘大小>2^(32-1))
我认为其他材料也非常重要:
- 拉尔夫·布朗的中断列表-
- Flamboux软件的技术帮助!-李>
- 彼得·诺顿的诺顿指南-
- Bochs x86仿真器的BIOS源代码-
在任何情况下,对您都有效的“更好的方法”是使用BIOS调用找出所有的基础知识,然后在您自己的代码中复制用于计算大小等的算法。在旧的DOS时代,没有可用于非Microsoft程序的易于重用的API。需要做高级工作的程序必须知道如何独立完成。构建老式系统的人倾向于使用当时使用的操作系统。我的小程序可以在DOS 3+上运行(实际上,这是我打算安装和测试的最早版本,可能还要追溯到更远的版本)。它也可以在现代系统上运行(例如,我的Windows 7 64位)。唯一的问题是DOS 7(Windows 9x引导到命令提示符)。这就是我现在正在尝试的工作,DOS 7。仅供参考,当他们发明键盘时,我真的很高兴,穿孔卡片是一个真正的PITA。哇,你绝对应该在CP/M上检查这个!我读错你的代码了吗?看起来,如果成功锁定驱动器,则跳过代码读取数据。否则,可能1)将SI设置为0xF1A6。2) 将dl设置为0x80。3) 使用更大的缓冲区(256?)。事实上,你没有:/我错过了。。。。现在重新编译。。。过了一会儿,唉,是的,我跳过了成功的代码,而不是失败的代码。将jnc操作码更改为jc,并添加了一个新标签(以适当地更改good/bad标志)。好吧,我现在得到了数据,尽管数字似乎不准确。现在我要做更多的测试:)谢谢,我实际上得到了大部分正确的数字。如果使用7303而不是7302,则所有字节值都是正确的。如果我使用7302,那么空闲集群的所有字节值“除外”都是正确的。(自由簇回来了FF FF。)我现在面临的是,由于某种原因,我无法理解,转换为无符号long的数学方法不起作用。在路试中完全正确的5E F5 1F 00(l-h变为0x001FF55E)变为0x0000F65E。我没发现我的数学有什么问题,是吗?好吧,我又犯了一个愚蠢的错误。在printf命令中使用了%u说明符,但没有长时间添加“l”:(啊…问题解决了,很抱歉打扰您。我不想使用7303例程,因为据报道它在CD-ROM上有问题。我将不得不对此进行调查。我不想再编写另一个例程:(我现在正在使用BIOS调用,这就是我遇到问题的原因:(我已经阅读了LBA和FAT32。我在第一次编写这个小实用程序时就做了这些。正如你在上面看到的,我的问题都是我自己创造的。对不起,我不是一个专业程序员,只是一个业余爱好者。我现在已经基本修复了它。一个需要跟踪的小错误(在实际的实用程序代码中,)我和CD-ROM的解决方案应该完成了。
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