Ho scritto un programma di utilità per le informazioni della directory e (poiché io e le persone che ho scritto per raccogliere & utilizzano hardware vintage), reso compatibile con DOS e Windows 9x e Windows XP/Vista/7/8 64-bit (perché li usiamo anche noi.) Il problema che ho avuto è stato con le unità Windows 9x e FAT32. Sono riuscito a farlo funzionare fino a quando Windows 9x è stato effettivamente caricato, ma se avvio solo il prompt dei comandi, o riavvio in modalità MS-DOS, perdo l'accesso all'API di Windows che mi ha permesso di ottenere i dati di unità di grandi dimensioni e è tornato di default alla routine DOS che ho. Questi sono limitati alle routine limite da 2 GB. Esaminando come i programmi DOS 7.x (principalmente chkdsk) gestiscono questo (poiché non hanno problemi nel riportare le dimensioni corrette dell'unità), sembra che utilizzino gli interrupt DOS (principalmente INT 21h) per farlo. Pensando, nessun problema, farò un rapido controllo della versione, e se è DOS 7 o superiore eseguirò semplicemente un rapido instradamento dell'assemblaggio per ottenere la struttura dell'azionamento e calcolare il totale dello spazio libero & in questo modo. Solo, la routine (anche se non restituisce un errore) non riempie il mio buffer di nulla.Ottenere grandi informazioni sulla struttura dell'unità in DOS 7.x
Ecco il codice:
#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] = "ABCDEF";
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;
}
che l'ultimo pezzo mi stava cercando di capire che cosa stava andando male. Stavo ottenendo risultati strani, e non riuscivo a capire un modello. Originariamente, non ero preoccupato di cancellare il buffer poiché la chiamata INT avrebbe dovuto riempirlo con i propri valori (tranne i primi 2 byte, che dovrebbero essere riempiti con la dimensione del buffer dei dati EDB.) Dopo aver ricevuto così tanti apparentemente risultati casuali, ho aggiunto il ciclo all'inizio per riempire il buffer con gli zeri, quindi aggiungere la dimensione del buffer. I risultati hanno smesso di essere casuali in quel momento, erano invariabilmente tutti zero, il che significa che la chiamata INT non riempie il buffer. Con una serie di test, ho confermato che ai hes & hdi viene assegnato correttamente il segmento e l'offset dell'indirizzo del buffer. Ho anche provato es & di all'indirizzo dell'indicatore invece dell'indirizzo del buffer. Non pensavo che avrebbe funzionato come tutto quello che ho letto ha detto di impostare l'indirizzo e non un puntatore, ma stavo cercando tutto quello che potevo pensare. In tutti i casi, il buffer non si riempie di nulla.
Come si può probabilmente dire, questo è solo un programma di prova che sto scrivendo per capire la procedura esatta prima di aggiungerlo al mio programma principale (che funziona bene tranne per questo problema.) Le linee FP_ sono solo macro che possono essere indicati come (senza firma lunga) (x & 0xffff0000) >> 16 per il segmento e (senza segno lungo) (x & 0x0000ffff) per lo scostamento. Normalmente si passa il puntatore (& drivedata), ma drivedata è già un puntatore.
L'uscita effettiva:
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
Allora, che cosa mi manca? Come chkdsk, sto bloccando l'unità prima e sbloccandola dopo la chiamata (anche se non sono sicuro della necessità). Come posso farlo funzionare correttamente? In alternativa, esiste un modo migliore per ottenere la struttura dell'unità (cluster, settori per cluster, byte per settore) rispetto all'utilizzo di INT 21h? Tutto ciò che trovo nelle ricerche mi indica solo le funzioni API di Windows, a cui l'utente non può accedere, se eseguono un avvio al prompt dei comandi ecc ...
Sto leggendo il tuo codice sbagliato? Sembra che se riesci a bloccare l'unità, salti il codice per leggere i dati. In caso contrario, forse 1) Impostazione SI a 0xF1A6. 2) Impostazione di dl su 0x80. 3) Utilizzo di un buffer più grande (256?). –
In realtà, non lo sei:/Mi sono perso ... Ricompilazione ora ... Indietro in un sec. – user3399848
*** sigh *** Sì, stavo saltando il mio codice sul successo, invece di saltare sul fallimento. Modificato l'opcode jnc su jc e aggiunto in una nuova etichetta (per cambiare in modo appropriato la flag good/bad). Il mio male. Bene, ora sto ricevendo dati, anche se i numeri sembrano spenti. Sto per fare qualche altro test ora :) Grazie – user3399848