|
Если клавиша BGCombo в буфере обнаружена, или если в
настоящий момент TSR выполняется на заднем плане, то она переста-
ет быть активной.
Приостановка выполняется по шагам, аналогично активации, но в
обратном порядке. Подпрограмма BKGSuspend восстанавливает сохра-
ненные DTA и PSP, восстанавливает драйверы прерывания и критичес-
кой ошибки, сохраняет текущие регистры, восстанавливает экран
(SCRBackground), уменьшает значение флажка критической секции,
переключает стеки, восстанавливает индексные регистры и изменяет
- 4-46 -
переменную PGMState. Инструкция RET в конце подпрограммы
BKGSuspend возвращает управление в ISR, которая активизирует TSR.
Если TSR выполнялась на заднем плане, то подпрограмма
SCRBackground не выполняет переключение экрана.
Листинг 4-31. Перевод в состояние ожидания
и возобновление работы TSR
----------------------------------------------------------------
SuspendResume PROC NEAR
AltF10 EQU 113 ; расширенный код ASCII для
; клавиши ALT F10
BGCombo EQU AltF10 SHL 8 ; LSB расширенного ASCII=0
BKG_C_FG EQU 1
BKG_C_BG EQU 2
SaveStack STRUC
rSP DW 0
rSS DW 0
SaveStack ENDS
switch MACRO sstack,dstack ;; переключение стеков
cli ;; запрещение прерывания во
;; время переключения стеков
mov sstack.rSS,SS ;; запись текущего стека
mov sstack.rSP,SP
mov SS,dstack.rSS ;; установка нового стека
mov SP,dstack.rSP
sti ;; разрешение прерываний
ENDM
_text SEGMENT BYTE PUBLIC 'code'
PgmState DB 0 ; сохранение дорожки состояния
; программы
InDosFlag DD 0 ; здесь программа инициализации
; сохраняет адрес флажка крити-
; ческой секции
OldStack SaveStack <> ; стек прерванной программы
BKGStack SaveStack <> ; стек TSR. Устанавливается
; программой инициализации
BKGResume:
call BKGSaveAll ; сохранение всех регистров в
; текущем стеке
cld ; флаг начального направления
mov ax,cs
mov ds,ax ; ds <== программный сегмент
switch OldStack,BKGStack ; переключение на стек
; заднего плана
call BKGRestoreAll ; восстановление регистров
; заднего плана
pushr
les di,InDosFlag ; es:di <== флаг входа в DOS
inc BYTE PTR es:[di] ; установка флага входа в
; DOS
popr
call BKGNewErrHndlr ; установка своих собственных
; драйверов критической ошиб-
; ки и прерывания
call BKGSetPSP ; изменение PSP
call BKGSetDTA ; изменение DTA
- 4-47 -
cli
cmp PopupPending,0 ;;; ожидание popup?
jz _br0 ;;; если 0 -- нет
dec PopupPending ;;; уменьшение на 1
mov PgmState,BKG_C_FG ;;; перевод программы на
;;; передний план
call SCRForeground ;;; перевод экрана
call BKGBufFlush ;;; выключение буфера клавиа-
;;; туры
_br0: sti
ret
BKGSuspend:
cmp PgmState,BKG_C_FG ; выполнение на переднем
; плане?
jl _bs0 ; если меньше -- задний
; план
jg _bs2 ; если больше -- инициали-
; зация (игнорирование
; приостановки)
;
; Текущее выполнение на переднем плане. Проверка нажатия
; клавиши
;
push ax ; сохранение текущего значе-
; ния ax
xor ah,ah ; ah <== 1 (проверка состояния
inc ah
int 16h ; выдача запроса
jz _bs1 ; если 0 -- нет доступного
; символа
cmp ax,BKCombo ; это символ заднего плана?
jnz _bs1 ; если не 0 -- нет
xor ah,ah ; ah <== 0 (запрос чтения)
int 16h ; удаление символа из буфера
pop ax ; восстановление ax
;
; Выполнение на заднем плане и запрос приостановки.
;
_bs0: call BKGRestoreDTA ; восстановление DTA
call BKGRestorePSP ; восстановление PSP
call BKGRestoreErrHndlr ; восстановление старых
; драйверов критической ошиб-
; ки и прерывания
call SCRBackground ; восстановление экрана
call BKGSaveAll ; сохранение регистров зад-
; него плана
les di,InDosFlag ; es:di <== адрес входа в DOS
dec BYTE PTR es:[di] ; уменьшение флажка входа в
; DOS
switch BKGStack,OldStack ; изменение стеков
call BKGRestoreAll ; восстановление регистров
mov cs:PgmState,BKG_C_BG ; программы на заднем
; плане
ret ; возврат
_bs1: pop ax ; восстановление начального
; значения ax
_bs2: ret ; возврат
- 4-48 -
SuspendResume ENDP
_text ENDS
----------------------------------------------------------------
Удаление TSR из памяти
В связи с ограниченным размером физической памяти персональ-
ного компьютера может возникнуть необходимость удаления TSR из
памяти, когда она станет ненужной. Процесс удаления TSR из памяти
не представляет большого труда, однако, имеются некоторые пробле-
мы. Очень часто TSR захватывает векторы прерываний и перед осво-
бождением памяти необходимо восстановить эти векторы.
При инициализации TSR должна записать начальное содержимое
векторов, которые она будет изменять в процессе своей работы. Ес-
ли отсутствует другая TSR, загружаемая после захвата этих векто-
ров, то можно восстановить эти векторы прерываний в их первона-
чальные значения и освободить память, занимаемую TSR. Если
интересующие Вас векторы прерываний все еще указывают на Вашу
программу, то это является надежным подтверждением того, что дру-
гая программа TSR не захватила их.
|