Предыдущий раздел ПРЕРЫВАНИЯ И РЕЗИДЕНТНЫЕ ПРОГРАММЫ Следующая глава

19.2.2. Использование свободных прерываний

Для выбора свободного номера прерывания можно использовать отладчик Debug. С помощью его команды “d 0:0” просмотрим начало области памяти, занимаемой таблицей векторов прерываний. (Для продолжения просмотра достаточно вводить команду d.) В этой области выберем любую последовательность из четырех нулевых байтов, номер младшего из которых делится нацело на четыре. Тогда частное от такого деления и есть искомый номер прерывания. Например, пусть выбранная последовательность четырех байтов начинается с номера 200h =  512. Тогда искомый номер прерывания n200h/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-программу, выполняющую запуск резидентной программы.

 


Предыдущий раздел В начало Следующая глава