Assembler - язык неограниченных возможностей


Обработчики прерываний


Когда в реальном режиме выполняется команда INT, управление передается по адресу, который считывается из специального массива, таблицы векторов прерываний, начинающегося в памяти по адресу 0000h:0000h. Каждый элемент этого массива представляет собой дальний адрес обработчика прерывания в формате сегмент:смещение или 4 нулевых байта, если обработчик не установлен. Команда INT помещает в стек регистр флагов и дальний адрес возврата, поэтому, чтобы завершить обработчик, надо выполнить команды popf и retf или одну команду iret, которая в реальном режиме полностью им аналогична.

; Пример обработчика программного прерывания int_handler proc far mov ax,0 iret int_handler endp

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

push 0 ; сегментный адрес таблицы ; векторов прерываний pop es ; в ES pushf ; поместить регистр флагов в стек cli ; запретить прерывания ; (чтобы не произошло аппаратного прерывания между следующими ; командами, обработчик которого теоретически может вызвать INT 87h ; в тот момент, когда смещение уже будет записано, а сегментный ; адрес еще нет, что приведет к передаче управления ; в неопределенную область памяти) ; поместить дальний адрес обработчика int_handler в таблицу ; векторов прерываний, в элемент номер 87h (одно из неиспользуемых прерываний) mov word ptr es:[87h*4], offset int_handler mov word ptr es:[87h*4+2], seg int_handler popf ; восстановить исходное значение флага IF

Теперь команда INT 87h будет вызывать наш обработчик, то есть приводить к записи 0 в регистр АХ.

Перед завершением работы программа должна восстанавливать все старые обработчики прерываний, даже если это были неиспользуемые прерывания типа 87h — автор какой-нибудь другой программы мог подумать точно так же. Для этого надо перед предыдущим фрагментом кода сохранить адрес старого обработчика, так что полный набор действий для программы, перехватывающей прерывание 87h, будет выглядеть следующим образом:

push 0 pop es ; скопировать адрес предыдущего обработчика в переменную old_handler mov eax,dword ptr es:[87h*4] mov dword ptr old_handler,eax ; установить наш обработчик pushf cli mov word ptr es:[87h*4], offset int_handler mov word ptr es:[87h*4+2], seg int_handler popf ; тело программы [...] ; восстановить предыдущий обработчик push 0 pop es pushf cli mov eax,word ptr old_handler mov word ptr es:[87h*4],eax popf




Начало  Назад  Вперед