|
Обнуление
регистра ES перед выполнением этого второго запроса позволяет, по
крайней мере, знать, что ответившая TSR возвращает некоторое зна-
чение в регистре ES. (Вам конечно известно, что TSR не должна
загружаться в сегмент 0).
Листинг 4-20. Размещение TSR путем использования
мультиплексируемых прерываний
----------------------------------------------------------------
OurID EQU 81h ; TSR выбирает значение AH
OldISR2f LABEL FAR ;здесь сохраняется старый вектор int 2Fh
UniqueID DB 'уникальная строка' ;для идентификации TSR
- 4-33 -
IDLength EQU $-UniqueID ; длина строки
OldInt2f DD 0 ; здесь программа инициализации запи-
; сывает начальный адрес ISR
NewISR2f PROC FAR ; новая ISR int 2Fh
cmp ah,OurID ; запрос для нас?
jz ItsMe ; если 0 -- для нас
jmp cs:Oldint2f ; передача запроса
ItsMe: or al,al ; загрузка проверена?
jnz GetAddress ; если не 0 -- нет
mov al,0ffh ; загружена
iret ; возврат
GetAddress:
cmp al,1 ; проверен ли адрес?
jnz BadFunction ; если не 0 -- нет
push cs ; возврат сегмента в ES pop es iret
BadFunction:
stc ; индуцирует ошибку
iret
NewISR2f ENDP
LocateISR PROC NEAR
mov ax,OurID SHL 8 ; ожидание чего-либо?
int 2Fh
cmp al,0ffh ; проверка выдаваемого ответа
jnz NotFound ; не 0 ==> нет ответа
xor ax,ax ; затирание сегмента
mov es,ax ; проверка выдаваемого ответа
mov ax,(OurID SHL 8) OR 1
; запрос сегмента
int 2Fh
jc NotFound ;если cy=1, то это не нам
xor ax,ax ; изменения ES проводились?
mov bx,es ; если изменения ES не проводились
cmp bx,ax
jz NotFound ; изменения ES не проводились
lea bx,NewISR2f ; ES:BX имеет адрес ISR
clc ; индикация успешна
ret ; возврат
NotFound: stc
ret
LocateISR ENDP
TSRResdnt PROC NEAR ; определяет резидентная ли TSR
call LocateISR ; получает адрес TSR
jc NotLoaded
call CheckISR ; проверяет идентификатор ID
ret ; возврат
; zr=1 ==> установлена
; zr=0 ==> не установлена
NotLoaded: or al,1 ; установка zr=0
ret ; возврат
TSRResdnt ENDP
----------------------------------------------------------------
Заметим, что TSR не может просто так перехватывать прерывание
int 2Fh. Если некоторая другая TSR, загружаемая позже других,
"захватит" этот вектор прерывания, то вход IVT будет указывать не
на первую TSR, а на загруженную позже других.
- 4-34 -
Запись адреса сегмента программного префикса (PSP)
Сегмент программного префикса (PSP) является важной структу-
рой данных в DOS. Операционная система DOS использует адрес PSP
для управления программами и поддержки многих служебных функций
ввода/вывода. DOS не знает как управлять несколькими PSP, она мо-
жет управлять только текущим PSP. Если Ваша подпрограмма TSR пе-
решла к выполнению какого-либо действия, то за судьбу текущего
PSP отвечаете Вы. Позднее мы узнаем, как сообщать DOS о том, ка-
кой PSP использовать. Если какой-либо подпрограмме TSR после ее
инициализации в последующем понадобится адрес ее PSP, то она
должна сохранить этот адрес на этапе выполнения инициализации.
Только на этапе инициализации можно быть полностью уверенным, что
текущий PSP относится непосредственно к Вам. Следующая программа
иллюстрирует, как определить адрес Вашего PSP (Листинг 4-21).
Листинг 4-21.
|