以下是代码:
#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;
}
最后一个步骤是我试图找出问题所在。我得到了奇怪的结果,无法找出规律。最初,我不担心清除缓冲区,因为INT调用应该用它自己的值填充它(除了前两个字节,应该用EDB数据缓冲区大小填充)。在得到如此多的随机结果之后,我在开头添加了一个循环来用零填充缓冲区,然后加入缓冲区大小。结果从那时起停止了随机变化,它们始终都是零,这意味着INT调用未填充缓冲区。通过各种测试,我已经确认hes和hdi正确地被赋予了缓冲区地址的段和偏移量。我还尝试将es和di设置为指针地址而不是缓冲区地址。我认为这不会起作用,因为我读到的所有内容都说要将其设置为地址而不是指针,但我尝试了我能想到的一切。在所有情况下,缓冲区都没有被填充。
正如你可能已经注意到的,这只是我编写的一个测试程序,以便在将其添加到我的主要程序中之前找出确切的过程(我的主要程序工作得非常好,除了这个问题)。FP_行只是可以表示为(unsigned long)(x&0xffff0000)> 16的段和(unsigned 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函数,而如果用户进行引导到命令提示符等操作,则无法访问这些函数...