|
|
|
|
Внесение "заплат" в векторы прерываний
Резидентные подпрограммы активизируются в одном из двух случаев: они инициирутся с помощью прерываний аппаратных средств (управление событиями),
или они должна поместить "заплату" в существующую систему (управление перехватом). Возможна также комбинация этих способов, где точка "заплаты"
является одним из прерываний аппаратных средств. Если используемая система не поддерживает прерывания аппаратных средств, то следует использовать способ
"заплат".
Для доступа (с некоторыми сложностями) к резидентным подпрограммам могут быть использованы прерывания аппаратных средств, не используемые
операционной системой MS-DOS. До тех пор, пока программа не осуществляет вызов MS-DOS, никаких системных конфликтов не произойдет. Если аппаратные
средства системы доступны с помощью резидентной подпрограммы, то она должна проверить, что в это время нет больше доступных аппаратных средств,
и быть осторожной при восстановлении аппаратного средства в его исходное состояние. Примером минимального влияния подпрограммы управления
прерываниями является программа сохранения всех регистров текущего выполнения программы в зарезервированном разделе памяти, когда происходит внешнее
прерывание. Такая подпрограмма полезна при отладке программ реального времени. Однако, если используемое прерывание также используется системой, то
подпрограмма должна принимать во внимание управление перехватом, потому что резидентная подпрограмма установлена с "заплатой".
Способ "заплат" является способом вставки резидентных подпрограмм в обычное исполнение системы в данной точке так, чтобы доступ в эту точку
осуществлялся через резидентную подпрограмму. Примером вставки "заплат", вызывающей аппаратное прерывание, является установка резидентной подпрограммы
управления клавиатурой. Для этого вектор прерывания клавиатуры изменяется на точку для резидентной подпрограммы. Значение предыдущего вектора
клавиатуры запоминается в адресе назначения инструкции перехода far (далекий), которая используется при выходе из подпрограммы резидентной памяти.
Когда происходит прерывание клавиатуры, начинается выполнение резидентной подпрограммы. После завершения обработки прерывания, резидентная подпрограмма
передает управление драйверу клавиатуры. Если резидентная подпрограмма действительно использует ввод клавиатуры в некоторых случаях, которые не может
продолжить драйвер клавиатуры, то резидентная подпрограмма должна сама обслужить и очистить прерывание, и затем вернуться в вызывающую программу по
инструкции IRET. Во всех случаях резидентная подпрограмма должна сохранять контекст прерванной программы.
Другими возможными точками вставки "заплат", которые не выполняют использование прерываний аппаратных средств, является вставка "заплат" в один
из векторов прерывания программного обеспечения или в адрес перехода. Вставка "заплат" в MS-DOS через векторы прерываний программного обеспечения
обычно не делается потому, что в операционной системе MS-DOS отсутствует возможность распознавания таблицы переходов. Кроме того, в связи с тем, что
не существует стандартный интерфейс между MS-DOS и интерфейсом ее BIOS, вставка "заплат" между MS-DOS и BIOS обычно затруднительна. Использование
прерываний программного обеспечения остается проблематичным.
Одним из общих мест вставки "заплат" в векторы прерываний MS-DOS является прерывание int 28h. Это, по-видимому, вспомогательное прерывание,
используемое внутри MS-DOS. Это также одна из точек вставки "заплат", в которую гарантируется частый доступ. Резидентная подпрограмма, вставленная в
качестве "заплаты" в этой точке, не может вызывать драйверы функций MS-DOS, т.к. это приведет к сбою системы. Резидентная подпрограмма также должна
использовать свой собственный контекст для предотвращения изменения существующего стека и регистров. Листинг 3-12 показывает программные коды,
необходимые для установки резидентной подпрограммы в прерывании int 28h и поддержки этой резидентной подпрограммы.
Листинг 3-12. Программа INIT28 - Вставка "заплат" в векторы
прерываний системы
----------------------------------------------------------------
; ==== INIT28 - Этот файл вырабатывает программу формата .COM ==
; ==== Установка резидентной подпрограммы путем вставки ========
; ==== "заплаты" в прерывание int 28h ==========================
PAGE 60,132
; ==== Соответствует установке прерывания ======================
VECT_NUM EQU 28h ; номер вектора для установки
OFF EQU 0h ; подпрограмма неактивна
ON EQU 0FFFFh ; подпрограмма активна
;
INCLUDE STDMAC.INC ; включение описания макробиблиотеки
; ==== НАЧАЛО ПРОГРАММНОЙ СЕКЦИИ ===============================
init28 SEGMENT
ASSUME cs:init28
ASSUME ds:init28
ORG 0
SEG_ORG EQU $
ORG 0100h
main PROC FAR
start: jmp init ; пропуск памяти "старого вектора"
old_v dd ? ; пространство для запоминания старого вектора
entry: jmp first ; пропуск "идентификации"
db 'TEST ROUTINE'
first: @SwapNewStack ; макрос для переключения в новый стек
cmp go_switch,ON ; проверка если я активна
jne bypass ; да - продолжить для выхода
mov go_switch,OFF ; нет - установка переключателя
; активна
;
; < ЗДЕСЬ ИДЕТ ВАША РЕЗИДЕНТНАЯ ПОДПРОГРАММА >
;
mov go_switch,ON ; установка состояния неактивна
bypass: @SwapOLDStack ; установка стека (и включение данных)
jmp cs:exit ; переход к подпр-ме обслуж-я прерыв-я
exit dd ?
go_switch dw ?
db 32 dup ('stack ')
TOS EQU $
LAST_BYTE EQU $
;
; ===== СЕКЦИЯ ИНИЦИАЛИЗАЦИИ - ПОСЛЕ ЗАГРУЗКИ НЕ НУЖНА =========
;
init: mov go_switch,OFF ; предупреждение активизации
mov ah,35h ; получение адреса вектора
mov al,VECT_NUM
@DosCall
mov word ptr exit,bx ; сохранение указателя IP для
; выхода
mov word ptr exit+2,es ; сохранение указателя CS для
; выхода
mov word ptr old_v,bx ; сохранение указателя IP для
; удаления
mov word ptr old_v+2,es ; сохранение указателя CS
; для удаления
mov ah,25h ; установка нового указателя
mov al,VECT_NUM
mov dx,offset entry ; установка указателя IP
; ... (CS и DS аналогично)
@DosCall
mov go_switch,ON
mov dx,9offset LAST_BYTE - SEG_ORG + 15) shr 4
mov ah,31h ; завершить и оставить резидентной
@DosCall
;
main ENDP
init28 ENDS
END start
----------------------------------------------------------------
|
Другие возможные точки вставки "заплат" зависят от типа резидентной подпрограммы и частоты, с которой она должна вызываться. Например,
подпрограмма буферизации печати - print spooler routine (которая печатает файлы во время выполнения других программ) не только должна прерывать
прерывание для активации передачи символов в принтер, но также должна прерывать любое обращение к MS-DOS, которое использует принтер, так, чтобы
не возникали конфликты. Рис.3-16 показывает прерывание буферизации печати int 28h для активации самой себя и прерывание int 21h для охраны самой себя от
конфликтов при доступе к принтеру.
---------------
прерывание | ... | Таблица векторов се-
---------------------| Int 21 IP/CS |<---------------------
| прерывание | ... | мейства микропроцес-|
| -------------------| Int 28 IP/CS |<----- соров 8086 |
| | | ... | | |
| | --------------- |Внешний вызов |
| | --------------- | Int 28h |
| | ------>| MS-DOS |------ MS-DOS |
| | | | ... | |
| | --------|-------| Коды Int 21 |<----------------- |
| | | | | ... | | |
| | | -------| Коды Int 28 |<------- Возврат | |
| | | --------------- | в | |
| | | --------------- | MS-DOS | |
| --|--------------->| Подпрограмма | | из пре- | |
| | | буферизации | | рывания | |
| | | ... | | Int 21h | |
| | | Коды печати |------- | |
| | | ... | | |
| | |---------------|Передача Int 21h | |
----|--------------->|Проверка Int 21|------------------ |
| --------------- |
| --------------- |
| | Программа | |
| | пользователя | |
| | ... | |
--------------->| Int 21h |----------------------------
Возврат Int 21 в | ... |
программе пользова- ---------------
теля
Рис.3-16. Использование векторов прерываний подпрограммой
буферизации печати
|
При любом использовании векторов прерываний для реализации некоторого подобия параллелизма, имеется риск "выхода" из выполнения программы,
осуществляющей непосредственный доступ к аппаратным средствам. Например, если для обеспечения некоторых возможностей устанавливается вектор прерывания
клавиатуры и если другая программа обходит вектор клавиатуры и вместо этого осуществляет чтение с аппаратных средств, то резидентная подпрограмма
не получает управления. Этот эффект может легко произойти, если устанавливается несколько резидентных программ, потому что каждая программа должна
обойти MS-DOS для выполнения ввода/вывода. Например, если и подпрограмма буферизации печати и резидентная подпрограмма устанавливаются для печати
содержимого видеодисплея, и обе активизированы в одно и тоже время, то произойдет конфликт. Эти проблемы могут также возникнуть и при установке имеющихся
в наличии коммерческих резидентных подпрограмм. У пользователей существует только один способ защитить себя - это установка только одной
подпрограммы для проверки конфликтов.
|
|