Предыдущий раздел | ПРЕРЫВАНИЯ И РЕЗИДЕНТНЫЕ ПРОГРАММЫ | Следующая глава |
Для выбора свободного номера прерывания можно использовать отладчик Debug. С помощью его команды “d 0:0” просмотрим начало области памяти, занимаемой таблицей векторов прерываний. (Для продолжения просмотра достаточно вводить команду d.) В этой области выберем любую последовательность из четырех нулевых байтов, номер младшего из которых делится нацело на четыре. Тогда частное от такого деления и есть искомый номер прерывания. Например, пусть выбранная последовательность четырех байтов начинается с номера 200h = 512. Тогда искомый номер прерывания n = 200h/4 = 80h = 128.
Пример. Сделаем резидентной «вежливую» com-программу, рассмотренную ранее. Для ее инициирования будем использовать программное прерывание с номером 80h. Текст программы на ассемблере:
; Резидентная программа выводит сообщение “Здравствуйте” на экран
; -----------------------------------------------------------------------------------------
; Вызов программы: команда int 80h
;
cr equ 0dh ; Код ASCII возврата каретки
lf equ 0ah ; Код ASCII перевода строки
absolute 2ch ; Следующий байт имеет адрес-смещение 2ch
Blocokr resw 1 ; Адрес блока окружения
segment code ; Виртуальный сегмент кода
org 100h
Start: jmp Init ; Переход на инициализацию
; Обработчик прерываний
Msg db ‘Здравствуйте’, cr, lf, ‘$’ ; Выводимое сообщение
Begin: sti ; Разрешить маскируемые прерывания
push ax ; Сохранение содержимого
push dx ; регистров
push ds ; в стеке
mov ax, cs ; DS будет адресовать данные
mov ds, ax ; резидентной программы
mov dx, Msg ; DX ß адрес строки-сообщения
mov ah, 9 ; Вывод строки
int 21h ; на экран
pop ds ; Восстановление содержимого
pop dx ; регистров
pop ax ; из стека
iret ; Возврат из прерывания
; Инициализационная часть программы
Init: mov ax, 2580h ; Запись стартового адреса обработчика
mov dx, Begin ; в вектор прерываний
int 21h ; с номером 80h
mov ah, 49h ; Освобождение области памяти,
mov es, [Blocokr] ; занимаемой
int 21h ; блоком окружения
mov dx, Init ; Возврат в DOS, оставшись
int 27h ; резидентным
Данная программа состоит из двух основных частей:
1) обработчик прерываний (резидентная часть);
2) инициализационная часть.
Инициализационная часть нерезидентна по той причине, что она выполняется всего один раз, и нет смысла постоянно держать ее в памяти. При этом следует учитывать, что, так как резидентная программа находится в ОП во время выполнения других программ, то занимаемую ею память следует минимизировать.
Новым средством уменьшения затрат памяти, которое применено в программе, является освобождение области, выделенной для блока окружения программы. Напомним, что такая область статически назначается любой программе, и ее размер кратен 512 байтам. Подобное освобождение возможно потому, что наш обработчик прерываний (как и любой другой) эту область не использует.
Обратим внимание, что первые команды обработчика прерываний запоминают в стеке, а последние команды извлекают из стека содержимое тех регистров, в которые выполняется запись в программе обработчика. Среди этих регистров есть и регистр сегмента данных DS, в который обработчик записывает новое значение, совпадающее с содержимым регистра CS. Это обусловлено тем, что при вызове обработчика (через прерывание) новое значение записывается лишь в единственный сегментный регистр CS (это значение берется из вектора прерываний). Остальные регистры сегментов (DS, SS и ES) сохраняют свое значение, полученное ранее в вызывающей программе. Поэтому для того, чтобы программа обработчика могла использовать свои данные, она помещает в DS соответствующий адрес-сегмент (для com-программ он совпадает с содержимым CS).
Интересно добавить, что, так как содержимое регистров SS и SP поступает в обработчик прерываний из вызывающей программы без изменений, то обработчик использует тот же самый стек, что и программа. Это свойство позволяет достаточно просто выполнять информационный обмен между программой и обработчиком, используя стек.
В ы п о л н и т е данную резидентную программу. Для ее тестирования необходимо после инициализации резидентной программы запустить вторую com-программу, выполняющую запуск резидентной программы.
Предыдущий раздел | В начало | Следующая глава |