; раммой
jmp SHORT DiskIOExit1
; переход к общему выходу
DiskIO ENDP
----------------------------------------------------------------
Проверка типа дисплея
Если необходимо, секция инициализации программы должна про-
верить тип дисплея и других периферийных устройств. TSR необходи-
мо знать совсем немного о дисплее, если она собирается поддержи-
вать горячие ключи. Тип используемого дисплейного адаптера MDA
(монохромный дисплейный адаптер) или CGA (цветной графический
адаптер) определить относительно просто. Многие типы дисплеев
эмулируют либо режим MDA, либо режим CGA. В связи с тем, что типы
дисплеев MDA и CGA в настоящее время являются наиболее общими,
ограничим свое обсуждение только этими двумя типами. Как отличить
дисплей MDA от дисплея CGA, показано в листинге 4-24.
Листинг 4-24. Определение типа дисплея
----------------------------------------------------------------
C40 EQU 1 ; дисплей CGA 40 x 25
C80 EQU 2 ; дисплей CGA 80 x 25
M80 EQU 3 ; дисплей MDA 80 x 25
DisplayType DB 0
int 11h ; прерывание проверки аппаратуры
and al,30h ; выделение видеобитов
mov cl,4 ; сдвиг между битами видеорежима
asr al,cl ; 0 и 1
mov DisplayType,al ; запоминание видеорежима
----------------------------------------------------------------
Освобождение операционной среды
Среда содержит строки символов. Каждая строка имеет имя пере-
менной, за которой следует значение (более полное описание среды
приведено в главе 3). DOS устанавливает среду при загрузке Вашей
резидентной подпрограммы TSR. Программы свободны в интерпретации
значений этих переменных. Файл COMMAND.COM использует переменную
PATH (путь) для указания каталогов, в которых необходимо произво-
дить поиск загружаемой программы или командного файла.
Так как при загрузке программы файл COMMAND.COM запрашивает
DOS о передаче копии операционной среды, TSR нет необходимости
проводить после ее завершения любые изменения в среде. Время, в
течение которого среда является правильной, - это время инициали-
зации TSR. Использует ли Ваша TSR среду или по разным причинам не
использует, зависит от приложения. В связи с тем, что после за-
вершения TSR среда является неправильной и она занимает опреде-
- 4-38 -
ленную память, то нет никаких причин хранить ее (хотя отказ от
освобождения среды не оказывает неблагоприятного воздействия на
TSR).
Начальный сегмент среды содержится в PSP по смещению 2Ch
(смотри листинг 4-15 "Структура PSP"). Для освобождения среды ис-
пользуйте функцию int 21h AH=49h "Освободить блок памяти". При
некоторых обстоятельствах среда отсутствует. Поэтому, прежде чем
освобождать среду, необходимо проверить эти обстоятельства. Если
среда отсутствует, то PSP будет содержать нули по смещению 2Ch
(функция 49h будет иметь некоторые проблемы при освобождении бло-
ка памяти в ячейке 00000h). Пример освобождения среды приведен в
листинге 4-25.
Листинг 4-25. Освобождение среды
----------------------------------------------------------------
;
; Освобождение среды
;
; Замечание: Структура PSP_W_Envron является частью структуры
; PSP с именем STRUC в листинге 4-15
FreeEnv PROC NEAR
pushr ; сохранение некоторых регистров
mov ah,62h ; запрос адреса PSP
int 21h
mov es,bx ; es <== PSP
xor ax,ax ; ax <== 0
xchg ax,es:PSP_W_Envron
; затирание сегмента среды в PSP
; ax <== сегмент среды
or ax,ax ; среда присутствует ?
jz NoEnv ; если 0 -- нет
mov es,ax ; es <== среда
mov ah,49h ; освободить блок памяти
int 21h
NoEnv: popr ; восстановление регистров
ret ; возврат
FreeEnv ENDP
----------------------------------------------------------------
Завершение программы
Последней задачей процесса инициализации является вызов функ-
ции "завершить и оставить резидентной" (int 21h, функция 31h).
При вызове функции "завершить и оставить резидентной" необходимо
сообщить DOS о том, какой объем памяти нужно сохранить. Для этого
перед выдачей запроса int 21h AH=31h, следует поместить в регистр
DX необходимое количество сегментов. DOS освободит все кроме пер-
вых DX сегментов памяти, которыми владела Ваша программа. Обще-
принято размещать программу инициализации в конце TSR так, чтобы
она могла быть удалена после завершения своей работы. Следующий
листинг иллюстрирует использование этой служебной функции. Эта
программа начинается с адреса (EndOfCode), получаемого округлени-
ем его до следующей границы сегмента и преобразованием в парагра-
фы путем деления на 16.
- 4-39 -
Листинг 4-26. Выполнение запроса
"завершить и оставить резидентной"
----------------------------------------------------------------
mov dx,OFFSET EndOfCode ; dx <== конец резидентной пр-мы
add dx,0fh ; округление до след. гран. сегм.
mov cl,4 ; преобразование смещения в сегм.
shr dx,cl ; dx <== резидентные параграфы
mov ah,31h ; функция TSR DOS
int 21h
----------------------------------------------------------------
В результате завершения запроса управление передается в DOS,
а DOS возвращает управление в командный процессор (обычно файл
COMMAND.COM). До тех пор, пока пользователь не вызовет другую
программу, прикладной программой переднего плана будет командный
процессор.
Повторная активизация TSR
Когда TSR получает запрос повторной активации, она должна
убедиться в безопасности дальнейшего выполнения. Эту задачу уп-
рощают действия, выполняемые программой инициализации. TSR должна
проверить флажки критической ошибки и критической секции, и убе-
диться в том, что не выполняются непрерываемые операции. Если
дальнейшее продолжение выполнения безопасно, TSR должна сохранить
текущие значения регистров, переключиться на свой собственный
стек, установить свои собственные подпрограммы критической ошибки
и break, записать информацию, сохраненную в различных глобальных
переменных DOS и, наконец, установить свою собственную среду,
включающую адреса текущих PSP и DTA. Заметим, что очень важен по-
рядок выполнения этих операций!
Кроме этих, могут потребоваться и другие операции. Так, если
необходимо использовать изображения, TSR должна сохранять в памя-
ти содержимое экрана. Программа PRINT.COM проверяет сводный ре-
гистр прерывания в контроллере 8259. Если активны какие-либо пре-
рывания, отличные от прерываний ISR, которые пробуждают ее, она
игнорирует запрос повторной активации. Вероятно, PRINT.COM делает
эту проверку, чтобы избежать потери символов последовательного
порта и других устройств отображения.
После завершения своей работы, TSR должна произвести откат
выполненных шагов и быстро перейти в фоновый раздел, ожидая снова
получения запроса повторной активации. TSR должна восстановить
значения регистров PSP, DTA, стека и других регистров прерванной
программы. После того, как TSR завершит эти шаги, она может безо-
пасно восстановить драйверы обработки критической ошибки и break
и осуществить возврат в прерванную программу.
Определение безопасности повторной активации
Невозможно предсказать, когда произойдет запрос на повторную
активацию TSR. Секции DOS не являются повторно входимыми, поэтому
и TSR не всегда может повторно активироваться при выдаче запроса
повторной активации. Детально эта проблема обсуждается в разделе
"Архитектура DOS". Необходимо с уважением относиться к этим огра-
ничениям, иначе Ваша программа, несомненно, разрушит систему и,
даже, возможно, разрушит диск.
Минимальный объем проверок, который должна выполнять Ваша
- 4-40 -
TSR, приведен в листинге 4-27. Эта программа предназначена для
выполнения с запрещением прерываний. Когда процессор отвечает на
прерывание, он запрещает прерывания. До тех пор, пока программа
обслуживания прерывания не разрешит прерывания перед вызовом
DOSSafeCheck, Вы не должны неявным образом манипулировать флажком
прерывания.
Эта программа начинается с увеличения значения того же самого
флажка BusyFlag (флажок "занято"), используемого новой подпрог-
раммой дискового в/в (листинг 4-23 "Типовое замещение программ
ISR дискового в/в"). Этот флажок имеет начальное значение -1. Ес-
ли инструкция INC в DOSSafeCheck имеет нулевой результат, то про-
должение выполнения безопасно. Ненулевой результат означает, что
выполняется одна или более дисковых операций (в конечном счете,
прерывание int 13h выполняется как результат прерываний int 25h и
int 26h), или незавершен предыдущий вызов TSR. Так как переключе-
ние стека выполняется программой повторной активации, то TSR не
является повторно входимой. (Позднее последовательность повторной
активации будет описана более подробно).
Затем эта программа проверяет флажки критической секции и
критического прерывания. Заметим, что необходимо проверять оба
флажка. Перед началом обработки критической ошибки драйвер крити-
ческой ошибки DOS уменьшает значение флажка критической секции и
увеличивает значение флажка критической ошибки. Побочным эффектом
вызова этой подпрограммы является то, что она предохраняет TSR от
повторного входа. Перед тем, как TSR переключится в фоновый раз-
дел, она должна уменьшить значение флажка "занято" (BusyFlag).
Листинг 4-27. Определение "безопасности" повторной активации
----------------------------------------------------------------
BusyFlag: DB -1 ; флажок "занято"
CSectFlg DW 0,0 ; здесь при инициализации запоми-