Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скляров И. Изучаем Assembler за 7 дней (2010).pdf
Скачиваний:
1335
Добавлен:
23.02.2015
Размер:
2.11 Mб
Скачать

http://www.sklyaroff.ru

140

Регистр маски прерываний ведущего контроллера доступен для записи и считывания через порт 21h, а ведомого контроллера — через порт 0A1h.

Можно сразу записать байт с установленным битом в регистр IMR, однако, если в регистре IMR уже были установлены какие-нибудь биты, то мы можем затереть эту информацию. Поэтому принято сначала считывать содержимое регистра IMR, изменять нужный бит в считанном значении, а затем полученное значение помещать обратно в регистр маски прерываний.

Между двумя обращениями к одному и тому же порту рекомендуется вставлять циклы задержки, поскольку контроллер i8259 по сравнению с процессором работает слишком медленно, обычно для этого используется пара операторов:

jmp short $+2 jmp short $+2

Например, вот так можно запретить прерывание от клавиатуры (IRQ1): in al,21h

or al,00000010b jmp short $+2 jmp short $+2 out 21h,al

Программист должен предусмотреть в своей программе обратную операцию — демаскирование запрещенного прерывания. Например, демаскирование прерывания от клавиатуры будет выглядеть следующим образом:

in al,21h

and al,11111101b jmp short $+2 jmp short $+2 out 21h,al

6.5.4. Собственный обработчик прерывания

Обработчик прерывания оформляется как обычная подпрограмма:

int_hook proc far

; тело обработчика iret

int_hook endp

После того как обработчик написан, его можно привязать к номеру прерывания. Это можно сделать, записав адрес обработчика в таблицу векторов прерываний. Однако перед этим следует сохранить адрес предыдущего обработчика (который мы заменяем) чтобы по окончании работы программы можно было его восстановить, — это необходимо для того, чтобы не нарушить нормальную работу системы.

В листинге 6.7 показан пример корректной замены обработчика прерывания. Наш обработчик будет вызваться командой INT 77h.

Листинг 6.7. Корректная замена обработчика прерывания

push 0 ; Записываем сегментный адрес таблицы векторов прерываний pop es ; в регистр ES

;Копируем адрес предыдущего обработчика в переменную old_hook mov eax,dword ptr es:[77h*4]

mov dword ptr old_hook,eax

;Устанавливаем наш обработчик

pushf ; Помещаем регистр флагов в стек

cli ; Запрещаем прерывания, чтобы не произошло прерывания в момент изменения адреса, т. к. возможен крах системы

http://www.sklyaroff.ru

141

;обработчик прерывания

;Помещаем дальний адрес нашего обработчика int_hook в таблицу

;векторов прерываний, в элемент с номером 77h

mov word ptr es:[77h*4], offset int_hook mov word ptr es:[77h*4+2], seg int_hook

popf ; восстанавливаем исходное значение флага IF

;Тело программы

....

....

....

;Восстанавливаем предыдущий обработчик push 0

pop es pushf cli

mov eax, word ptr old_hook mov word ptr es:[77h*4],eax popf

Существует еще один способ замены обработчика прерывания — с помощью функций операционной системы DOS 25h и 35h, которые вызываются по прерыванию int 21h:

Функция 35h (INT 21h) — получить вектор прерываний

Входные данные:

AH=35h

AL=номер прерывания (от 00h до 0FFh)

Возвращаемые значения:

ES:BX=адрес обработчика прерывания для INT AL.

Функция 25h (INT 21h) — установить вектор прерываний

Входные данные:

AH=25h

AL= номер прерывания (от 00h до 0FFh)

DS:DX=адрес обработчика прерываний

Возвращаемые значения:

Функция ничего не возвращает.

В листинге 6.8 показан пример замены обработчика прерывания с помощью функций DOS.

Листинг 6.8. Замена обработчика прерывания с помощью функций DOS

; Копируем адрес предыдущего обработчика в переменную old_hook mov ax,3577h

int 21h

mov word ptr old_hook,bx mov word ptr old_hook+2,es

mov ax,2577h

mov dx,seg int_hook