Таблица файлов MS DOS (DFT)

Ответить
Аватара пользователя
push0ret
Сообщения: 7
Зарегистрирован: Вс дек 29, 2024 2:48 pm
Поблагодарили: 7 раз
Контактная информация:

Таблица файлов MS DOS (DFT)

Сообщение push0ret »

Hello, world!
Предпоследняя статья из цикла про структуры MS DOS. В этой статье разберём таблицу файлов DOS.

DOS создает таблицу открытых файлов и записывает её адрес в векторную таблицу связи (CVT) в поле file_tab (смотреть тему: viewtopic.php?t=97). В этой таблице для каждого открытого в системе файла хранится такая информация, как число(handle, дескриптор), режим открытия файла (чтение, запись, чтение и запись), два байта информации об устройстве (диске), указатель на заголовок драйвера, обслуживающего устройство, номер последнего прочитанного кластера, информация о файле (дата, время, имя, расширение, номер первого кластера и т.д.).

Размер таблицы файлов определяется строкой FILES=XX в файле config.sys. Каждая таблица DFT (DOS File Table) содержит адрес следующей таблицы и количество управляющих блоков файлов DFCB (DOS File Control Block) в этой таблице, каждому файлу соответствует свой DFCB.

Формат этой таблицы в разных версиях DOS отличается, приведу формат таблицы для версии DOS 3.x:

(0) dd next указатель на следующую таблицу файлов
(+4) dw file_count количество файлов в этой таблице
--- Дальше идут блоки DFCB в количестве file_count штук ----
(0) dw handl_num количество файловых чисел, связанных с данным файлом (file handle)
(+2) db access_mode режим доступа к файлу, заданный при открытии файла
(+3) dw reserv1 зарезервировано
(+5) dw dev_info информация IOCTL, полученная для устройства, на котором расположен этот файл
(+7) dd driver указатель на драйвер, обслуживающий устройство, содержащее файл
(+11)dw first_clu номер первого кластера, распределенного файлу
(+13)dw time время последнего изменения файла в упакованном формате
(+15)dw date дата последнего изменения файла в упакованном формате
(+17)dd fl_size размер файла в байтах
(+21)dd offset текущее смещение внутри файла в байтах
(+25)dw reserv2 зарезервировано
(+27)dw last_clu номер только что прочитанного кластера
(+29)3 reserv3 зарезервировано
(+32)11 filename имя файла в формате FCB (имя выровнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
(+43)dw reserv4 зарезервировано
(+45)dw ownr_psp PSP программы, открывшей файл
(+47)dw reserv5 зарезервировано

Формат таблицы для DOS 4.x:

(0) dd next указатель на следующую таблицу файлов
(+4) dw file_count количество файлов в этой таблице
--- Дальше идут блоки DFCB в количестве file_count штук ----
(0) dw handl_num количество файловых чисел, связанных с данным файлом (file handle)
(+2) db access_mode режим доступа к файлу, заданный при открытии файла
(+3) dw reserv1 зарезервировано
(+5) dw dev_info информация IOCTL, полученная для устройства, на котором расположен этот файл
(+7) dd driver указатель на драйвер, обслуживающий устройство, содержащее файл
(+11)dw first_clu номер первого кластера, распределенного файлу
(+13)dw time время последнего изменения файла в упакованном формате
(+15)dw date дата последнего изменения файла в упакованном формате
(+17)dd fl_size размер файла в байтах
(+21)dd offset текущее смещение внутри файла в байтах
(+25)dw reserv2 зарезервировано
(+27)dw reserv7 зарезервировано
(+29)3 reserv3 зарезервировано
(+32)db reserv4 зарезервировано
(+33)11 filename имя файла в формате FCB (имя выравнено на левую границу поля, дополнено пробелами до 8 символов, справа к нему прилегает 3 символа расширения без точки)
(+44)dw reserv5 зарезервировано
(+46)dw ownr_psp PSP программы, открывшей файл
(+48)dw reserv6 зарезервировано
(+50)dw last_clu номер только что прочитанного кластера
(+52)dd reserv8 зарезервировано

Теперь, когда мы знаем структуру этой области памяти, можно с ней поработать, как всегда, напишу программу, которая выводит нам список всех открытых файлов на экран:

Код: Выделить всё

.model  tiny
.286
code    segment
org     100h

start:

mov ah, 52h
int 21h

mov si, offset dft_addr

mov ax, word ptr es:[bx+4]      ;
mov word ptr[si], ax            ;
				;write in variable address of DFT       
mov ax, word ptr es:[bx+6]      ;
mov word ptr[si+2], ax          ;

read_dft:

;Write DFT in DS:[SI]

mov si, offset dft_addr

push word ptr[si]
push word ptr[si+2]
pop ds
pop si

push ss
pop es
mov di, offset dft.next

mov cx, 55d
rep movsb

push es
pop ds

work_with_dft:

mov si, offset dft_addr
push word ptr[si]
push offset display.num+8
call hex_ascii

push word ptr[si+2]
push offset display.num+3
call hex_ascii

;Read address of next DFT

mov si, offset dft.next

push word ptr[si]
push offset display.num0+8
call hex_ascii

push word ptr[si+2]
push offset display.num0+3
call hex_ascii

;Read count of files

push dft.file_count
push offset display.num1+3
call hex_dec

mov ah, 9d
mov dx, offset display.ths_dft_
int 21h
 
mov cx, dft.file_count

read_dfcb:

call read_file

mov ah, 9d
mov dx, offset display.filename_
int 21h

pusha

read_next_dfcb:

mov si, offset dft_addr

mov di, word ptr[si]
push word ptr[si+2]
pop ds

add off_in_dft, 59d
add di, off_in_dft
mov si, di

mov di, offset dft.handle_num
mov cx, 49d
rep movsb

push es
pop ds

;Clear fields of display structure

mov di, offset display.time_
mov cx, 3d

clr_time:

mov word ptr[di], 3030h
add di, 3d
loop clr_time

mov di, offset display.date_

mov word ptr[di], 3030h
add di, 3d
mov word ptr[di], 3030h
add di, 3d
mov word ptr[di], 3030h
add di, 2d
mov word ptr[di], 3030h

mov di, offset display.filesize_
mov cx, 9d

null_size:

mov byte ptr[di], 0
inc di
loop null_size

mov byte ptr[di], 30h

mov display.mode_, 30h

popa

loop read_dfcb

push si
push ax
push bx

mov si, offset dft.next

mov ax, word ptr[si]
mov bx, word ptr[si+2]

mov si, offset dft_addr

mov word ptr[si], ax
mov word ptr[si+2], bx

pop bx
pop ax
pop si

mov off_in_dft, 6d

cmp word ptr dft_addr, 0FFFFh
jz exit

jmp read_dft

exit:

mov ax, 4c00h
int 21h

dft_addr        dd      ?
off_in_dft      dw      6d

display_        struc   

ths_dft_        db      0Ah, 'THIS DFT TABLE;', 9d
num             db      4d dup(0), ':', 4d dup(0), 0Ah, 0Dh
next_           db      'NEXT DFT TABLE:', 9d
num0            db      4d dup(0), ':', 4d dup(0), 0Ah, 0Dh
file_count_     db      'COUNT OF FILES:', 9d
num1            db      5d dup(0), 0Ah, 0Ah, 0Dh, 24h
filename_       db      8d dup(20), '.', 3d dup(20), 9d
time_           db      '00:00:00', 9d
date_           db      '00.00.0000', 9d
filesize_       db      9d dup(0), 30h, ' bytes', 9d
mode_		db	30h, 0Ah, 0Dh, 24h

display_        ends

display         display_        <>

dft_            struc

next            dd      ?
file_count      dw      ?
handle_num      dw      ?
access_mode     db      ?
reserv1         dw      ?
dev_info        dw      ?
driver          dd      ?
first_clu       dw      ?
time            dw      ?
date            dw      ?
fl_size         dd      ?
off_set         dd      ?
reserv2         dw      ?
last_clu        dw      ?
reserv3         db      3d dup(?)
filename        db      11d dup(?)
reserv4         dw      ?
ownr_psp        dw      ?
reserv5         dw      ?

dft_            ends

dft             dft_            <>

;---------------------------------------
;Read and write in structure file info

read_file      proc    uses ax cx dx bx di

;Read file size

mov si, offset dft.fl_size

push word ptr[si+2]
push offset display.filesize_+4
call hex_dec

push word ptr[si]
push offset display.filesize_+9
call hex_dec

;Read filename and extension

mov si, offset dft.filename
mov di, offset display.filename_
mov cl, 8d
rep movsb

mov di, offset display.filename_+9
mov cl, 3d
rep movsb

;Read access mode of file

xor ax, ax
mov al, dft.access_mode

push ax
push offset display.mode_
call hex_dec

;Read date and unpacking

mov ax, dft.date
mov bx, ax
mov cx, ax

and ax, 0000000000011111b       ;day
and bx, 0000000111100000b       ;
shr bx, 5d                      ;month
and cx, 1111111000000000b       ;
shr cx, 9d                      ;
add cx, 1980d                   ;year           

push ax
push offset display.date_+1
call hex_dec

push bx
push offset display.date_+4
call hex_dec

push cx
push offset display.date_+9
call hex_dec

;Read time and unpacking

mov ax, dft.time
mov bx, ax
mov cx, ax

and ax, 0000000000011111b       ;
shl al, 1d                      ;seconds
and bx, 0000011111100000b       ;
shr bx, 5d                      ;minutes
and cx, 1111100000000000b       ;
shr cx, 11d                     ;hours

push ax
push offset display.time_+7
call hex_dec

push bx
push offset display.time_+4
call hex_dec

push cx
push offset display.time_+1
call hex_dec

ret

read_file      endp

;------------------------------------------
;HEX IN DECIMAL ASCII PROCEDURE.
;PARAMETERS(STACK):
;- NUMBER
;- LAST BYTE IN MEMORY FOR DISPLAY

hex_dec         proc    uses ax bx di dx bp

mov bp, sp

mov ax, word ptr ss:[bp+14]
mov di, word ptr ss:[bp+12]
mov bx, 0Ah
xor dx, dx

in_decimal:

cmp ax, 0
jz stop_decimal

div bx
add dl, 30h
mov byte ptr[di], dl
xor dx, dx
dec di
jmp in_decimal

stop_decimal:

ret 4

hex_dec         endp

;---------------------------------------
;HEX NUMBER IN ASCII CODE PROCEDURE.
;PARAMETERS(STACK):
;- NUMBER
;- LAST BYTE IN ARRAY FOR DISPLAY

hex_ascii       proc    uses ax bx di cx bp

mov bp, sp
mov bx, word ptr ss:[bp+14]
mov di, word ptr ss:[bp+12]
mov cx, 4d

translate:

mov ax, bx
and ax, 0Fh

cmp al, 9d
ja letter

add al, 30h
mov byte ptr[di], al
ror bx, 4d
dec di
loop translate

jmp end_of_trans

letter:

add al, 37h
mov byte ptr[di], al
ror bx, 4d
dec di
loop translate

end_of_trans:

ret 4

hex_ascii       endp

code    ends
end     start
Результат работы программы:
adft7.PNG
adft7.PNG (109.78 КБ) 26 просмотров
Как можно заметить, наша программа это тоже открытый файл в ОС, так как она хранится на жёстком диске, то системе сначала надо открыть файл, затем прочитать его с диска и загрузить в оперативную память для выполнения.

Использовалась версия компилятора MASM 6.11 в контексте операционной системы MS DOS 6.22!

В своих статьях стараюсь максимально кратко и ёмко описать структуры MS DOS и зачем они используются, надеюсь, что у меня всё получается :D

Спасибо за внимание!
С уважением, push0ret!
Ответить

Вернуться в «Системное программирование»