|
|
|
|
Рабочая таблица файлов (JFT)
В большинстве случаев PSP будет содержать саму рабочую таблицу файлов. По умолчанию JFT позволяет открыть одновременно 20 файлов, но имеется
возможность создания альтернативной JFT для увеличения максимального количества открытых файлов. В DOS 3.3 для этого имеется специальная функция
(int 21h AH=67h). В DOS версии ниже 3.3 можно изменять адрес JFT в PSP вручную. DOS для ввода/вывода будет использовать заново определенную JFT, но
будет иметь трудности клонирования этой JFT при обработке запроса загрузки (int 21h AH=4bh).
Рабочая таблица файлов заносит описатели в качестве входов таблицы файловой системы. Каждый вход JFT занимает один байт. Если вход не использован,
он содержит 0FFh; в противном случае он содержит системный номер файла(SFN), который используется как индекс в таблице файловой системы. DOS использует
описатель файла в JFT как индекс.
Листинги 4-16 и 4-17 иллюстрируют связи между PSP, JFT, SFN и SFT. Первая подпрограмма принимает описатель в BX и возвращает соответствующий
системный номер файла (SFN) в AX. Подпрограмма использует функцию BIOS AH=62h для размещения текущего PSP, когда получает адрес JFT из PSP, и в
конечном счете использует описатель, как индекс в JFT. Макроопределения pushr и popr сохраняют и перезапоминают регистры, описанные как аргументы. Если
встретилась ошибка, то эта подпрограмма возвращает флаг переноса установленным (CY=1).
Вторая подпрограмма принимает SFN в AX и возвращает адрес соответствующего входа SFT в ES:DI. Она получает адрес "списка списков" с функцией
AH=52h и затем получает описатель списка заголовков SFT в ES:DI. Каждый блок имеет "следующее" поле и часть оглавления, которая показывает, сколько
входов в этом блоке. Эта подпрограмма просматривает цепочку блоков SFT до тех пор, пока не найдет блок, содержащий вход SFT. Если описатель неверен или
если SFT испорчена, подпрограмма возвращает флаг переноса установленным.
Листинг 4-16. Использование описателя для получения
номера системного файла
----------------------------------------------------------------
GetSFN PROC NEAR
pushr ; макрокоманда сохранения
; регистров
mov ah,62h... ; получить текущий PSP
int 21h
mov ds,bx ; ds <== текущий PSP
pop bx ; описатель
cmp bx,0ffh ; проверка описателя
Jz BadHandle ; описатель не может быть
; отрицательным
cmp bx,ds:PSP_W_JFTSize
; описатель слишком велик?
jge BadHandle ; если ge - да
les di,ds:PSP_D_JFTAddr
; es:di <== JFT
mov al,es:[di][bx] ; al <== SFN (описатель)
cbw ; ax <== SFN (описатель)
clc ; успешная индикация
Done: popr ; восстановление регистров
ret ; возврат
BadHandle stc ; ошибка индикации
jmp SHORT Done ; общий выход
GetSFN ENDP
----------------------------------------------------------------
|
Листинг 4-17. Поиск системной таблицы файлов
----------------------------------------------------------------
LocateSFT PROC NEAR
push ax ; сохранение SFN
mov ah,52h ; запрос адреса
int 21h ; списка списков
;
; es:di <== 1-ый блок описателя оглавления списка SFT
;
les di,es:[bx].DOS_D_HDLSFT
pop ax ; восстановление SFN
xor bx,bx ; bx <== 0
_l0 cmp di,0ffffh ; конец последовательности
jz _l2 ; если z - да
;
; bx <== первый SFN в следующем блоке
;
add bx,es:[di].SFTBLK_W_Count
cmp ax,bx ; SFN в этом блоке?
jl _l1 ; если l - да
;
; es;ds <== следующий блок SFT
;
les di,es:[di].SFTBLK_D_Next
jmp SHORT _l0 ; продолжение поиска
;
; bx <== первый SFN этого блока
;
_l1 sub bx,es:[di].SFTBLK_W_Count
sub ax,bx ; ax <== смещение блока
mov bl,SFT_K_SIZE; bl <== размер входа
mul bl ; перевод смещения в байты
add di,ax ; di <== смещение в блоке
; (почти)
add di,SFTBLK_K_Size ; добавить сверху
clc ; успешная индикация
ret ; возврат
_l2 stc ; ошибка индикации
ret ; возврат
LocateSFT ENDP
----------------------------------------------------------------
|
|
|