我写了一个目录信息实用程序,(因为我和我为此收集和使用老式硬件而写的人)使它兼容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函数,用户无权访问它们,如果它们执行启动命令提示等...
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |