|
|
|
|
Альтернатива для перехвата Int 1Сh
Важно заметить, что ISR Int 1Сh вложена в ISR Int 8, так как прерывание по времени имеет высший приоритет; никакие прерывания не обслуживаются, пока
контроллер прерываний не получит EOI (конец прерывания). Любые команды, которые зависят от прерываний, не будут работать. Другой потенциальной проблемой
является то, что DOS будет терять такты таймера, если он будет слишком долго путешествовать по цепочке int 1Сh. PRINT.COM решает эту проблему пересылкой
EOI в свой int 1Сh ISR.
Альтернативной стратегией является перехват int 8. Новая int 8 ISR сразу вызывает старую ISR, которая посылает EOI контроллеру прерываний перед
возвращением. ISR, приведенная на листинге 4-8 работает вместе с приведенной на листинге 4-7. Если горячий ключ не обработан, или если с последней
активации прошла 1 секунда, то для реактивации TSRint 8 ISR вызывает BKGResume.
Листинг 4-8. Пример замены прерывания по времени ISR int 8
----------------------------------------------------------------
OldInt8 DD 0 ; сохранение кода инициализации
; начальный адрес ISR int 8
BusyFlag DB -1 ; запрет прерывания
; нереентерабельная секция
; программы
PopupPending DB 0 ; не 0, если встретилась нажатая клавиша
Ticks DB 18 ; выполняется один раз в секунду
Int8ISR PROC FAR
NewInt8:
pushf ;;; моделирование прерывания
call cs:OldInt8 ;;; посылка кода ROM
cli ;;; не является необходимым
cmp cs:PopPending,0 ;;; ожидание запроса выборки?
jnz i8_0 ;;; если не 0 - да
cmp cs:Ticks,0 ;;; счетчик тактов = 0?
jz i 8_0 ;;; если 0 - да
dec cs:Ticks ;;; иначе - уменьшение его
jnz Int9Exit1 ;;; если еще не 0 - продолжение
8_0 call DOSSafeCheck ;;; OS не испорчена?
jc Int8Exit0 ;;; если c - нет
;;; заметим, что отметка времени
;;; остается на 0, попытаемся
;;; сохранить для передачи
;;; каждую отметку
call BKGResume ; передача фоновой программе
mov cs:Ticks,18 ; сброс счетчика
Int8Exit0:
dec cs:BusyFlaag ; закрыть
Int8Exit1:
iret ; возврат
Int8ISR ENDP
----------------------------------------------------------------
|
|
|