Получение большой информации о структуре диска в DOS 7.x

Я написал справочную информацию утилиты и (потому что я, и люди, которых я написал это для сбора & использовать устаревшее аппаратное обеспечение), сделав его совместимым с DOS и Windows 9x, а также с 64-битной Windows XP / Vista / 7/8 (потому что мы их также используем). Проблема, с которой я столкнулся, была с дисками Windows 9x и FAT32. Мне удалось заставить его работать до тех пор, пока Windows 9x была фактически загружена, но если я загружаюсь только из командной строки или перезагружаюсь в режиме MS-DOS, я теряю доступ к API Windows, что позволило мне получить большие данные с диска и его по умолчанию вернулось к программе DOS, которую я имею. Они ограничены процедурами ограничения 2 ГБ. Изучая, как программы 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;
}

Последний раз я пытался понять, что происходит не так. Я получал странные результаты и не мог понять схему. Первоначально я не беспокоился об очистке буфера, поскольку вызов INT должен был заполнить его собственными значениями (за исключением первых 2 байтов, которые должны быть заполнены размером буфера данных EDB.) После получения так много, очевидно, случайные результаты, которые я добавил в начале цикла, чтобы заполнить буфер нулями, а затем добавить размер буфера. В этот момент результаты перестали быть случайными, они всегда были равны нулю, что означает, что вызов INT не заполняет буфер. С помощью множества тестов я подтвердил, что он & hdi правильно назначается сегмент и смещение адреса буфера. Я тоже пробовал & di к адресу указателя вместо адреса буфера. Я не думал, что это сработает, потому что все, что я прочитал, говорит, чтобы установить его по адресу, а не по указателю, но я пробовал все, что мог придумать. Во всех случаях буфер не заполняется чем-либо.

Как вы, вероятно, можете сказать, это всего лишь тестовая программа, которую я пишу, чтобы выяснить точную процедуру перед ее добавлением в мою основную программу (которая прекрасно работает, за исключением этой проблемы). Строки FP_ — это просто макросы, которые могут быть указано как (без знака долго) (х & 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, к которым у пользователя не будет доступа, если они загружаются из командной строки и т. Д.

5

Решение

Ух ты, используя DOS, это старая школа! Не такая старая школа, как использование перфокарт, но все же …

По-видимому, FreeDOS имеет Поддержка FAT 32. Вы можете попытаться установить его на тех компьютерах, на которых даже не установлена ​​Windows 95.

1

Другие решения

Для вашего винтажного хобби вы должны вооружиться LBA а также FAT32 технические характеристики, Википедия: Таблица размещения файлов кажется, есть хорошие ссылки.

Вы можете узнать одну вещь: эти устаревшие системы (и программное обеспечение, написанное для них) не могли обрабатывать большие диски (размер диска> 2 ^(32-1)Изящно

Другие материалы, я думаю, также были бы очень важны:

«Лучший способ», который должен работать для вас во всех случаях, состоит в том, чтобы использовать вызовы BIOS, чтобы выяснить все основы, а затем воспроизвести алгоритмы для расчета размеров и т. Д. В вашем собственном коде. В старые времена DOS не было легко повторно используемого API, доступного для программ не от Microsoft. Программы, которые должны были делать продвинутые вещи, должны были знать, как сделать это самостоятельно.

1

По вопросам рекламы [email protected]