Глава 1. Системные ресурсы.

Раздел 2. Управление прерываниями.

1.2.3 Hаписание собственного прерывания.

Имеется несколько причин для написания собственного прерывания. Во-первых, большинство из готовых прерываний, обеспечиваемых операционной системой, ничто иное, как обычные процедуры, доступные для всех программ, и Вы можете пожелать добавить свое в эту библиотеку. Hапример, многие Ваши программы могут использовать процедуру, выводящую строки на экран вертикально. Вместо того, чтобы включать ее в каждую программу в качестве процедуры Вы можете установить ее как прерывание, написав программу, которая останется резидентной в памяти после завершения {1.3.4}. Тогда Вы можете использовать INT 80H вместо WRITE_VERTICALLY (имейте ввиду, что вызов прерывания несколько медленней, чем вызов процедуры).

Второй причиной написания прерывания может быть использование какого-либо отдельного аппаратного прерывания. Это прерывание автоматически вызывается при возникновении определенных условий. В некоторых случаях BIOS инициализирует вектор этого прерывания так, что он указывает на процедуру, которая вообще ничего не делает (она содержит один оператор IRET). Вы можете написать свою процедуру и изменить вектор прерываний, чтобы он указывал на нее. Тогда при возникновении аппаратного прерывания будет выполняться Ваша процедура. Одна из таких процедур это прерывание времени суток {2.1.0}, которое автоматически вызывается 18.2 раза в секунду. Обычно это прерывание только обновляет показание часов, но Вы можете добавить к нему любой код, который Вы пожелаете. Если Ваш код проверяет показания часов и вступает в игру в определенные моменты времени, то возможны операции в реальном времени. Другие возможности - это написание процедур обработки Ctrl-Break {3.2.8}, PrtSC {3.2.9} и возникновения ошибочных ситуаций {7.2.5}. Прерывания принтера {6.3.1} и коммуникационные {7.1.8} позволяют компьютеру быстро переключаться между операциями ввода/вывода и другой обработкой.

Hаконец, Вы можете захотеть написать прерывание, которое полностью заменит одну из процедур операционной системы, приспособленное к Вашим программным нуждам. В {1.2.4} показано как написать прерывание внутри прерывания, которое позволяет Вам модифицировать существующие процедуры.

Средний уровень.

Функция 25H прерывания 21H устанавливает вектор прерывания на указанный адрес. Адреса имеют размер два слова. Старшее слово содержит значение сегмента (CS), младшее содержит смещение (IP). Чтобы установить вектор, указывающим на одну из Ваших процедур, нужно поместить сегмент процедуры в DS, а смещение в DX (следуя порядку нижеприведенного примера). Затем поместите номер прерывания в AL и вызовите функцию. Любая процедура прерывания должна завершаться не обычной инструкцией RET, а IRET. (IRET выталкивает из стека три слова, включая регистр флагов, в то время как RET помещает на стек только два. Если Вы попытаетесь тестировать такую процедуру как обычную процедуру, но кончающуюся IRET, то Вы исчерпаете стек.) Отметим, что функция 25H автоматически запрещает аппаратные прерывания в процессе изменения вектора, поэтому не существует опасности, что посреди дороги произойдет аппаратное прерывание, использующее данный вектор. ;---установка прерывания
PUSH DS ;сохраняем DS
MOV DX,OFFSET ROUT ;смещение для процедуры в DX
MOV AX,SEG ROUT ;сегмент процедуры
MOV DS,AX ;помещаем в DS
MOV AH,25H ;функция установки вектора
MOV AL,60H ;номер вектора
INT 21H ;меняем прерывание
POP DS ;восстанавливаем DS
;---процедура прерывания
ROUT PROC FAR
PUSH AX ;сохраняем все изменяемые регистры
.
.
POP AX ;восстанавливаем регистры
MOV AL,20H ;эти две строки надо использовать
OUT 20H,AL ;только для аппаратных прерываний
IRET
ROUT ENDP

В конце кода каждого из Ваших аппаратных прерываний Вы должны включить следующие 2 строчки кода:
MOV AL,20H
OUT 20H,AL

Это просто совпадение, что числа (20H) одни и те же в обеих строках. Если аппаратное прерывание не заканчивается этими строками, то микросхема 8259 не очистит информацию регистра обслуживания, с тем чтобы была разрешена обработка прерываний с более низкими уровнями, чем только что обработанное. Отсутствие этих строк легко может привести к краху программы, так как прерывания от клавиатуры скорее всего окажутся замороженными и даже Ctrl-Alt-Del окажется бесполезным. Отметим, что эта добавка не нужна для тех векторов прерываний, которые являются расширениями существующих прерываний, таким как прерывание 1CH, которое добавляет код к прерыванию времени суток {2.1.7}.

Kогда программа завершается, должны быть восстановлены оригинальные вектора прерываний. В противном случае последующая программа может вызвать данное прерывание и передать управление на то место в памяти, в котором Вашей процедуры уже нет. Функция 35 прерывания 21H возвращает текущее значение вектора прерывания, помещая значение сегмента в ES, а смещение в BX. Перед установкой своего прерывания получите текущее значение вектора, используя эту функцию, сохраните эти значения, и затем восстановите их с помощью функции 25H (как выше) перед завершением своей программы. Hапример:
;---в сегменте данных:
KEEP_CS DW 0 ;хранит сегмент заменяемого прерывания
KEEP_IP DW 0 ;хранит смещение прерывания
;---в начале программы
MOV AH,25H ;функция получения вектора
MOV AL,1CH ;номер вектора
INT 21H ;теперь сегмент в ES, смещение в BX
MOV KEEP_IP,BX ;запоминаем смещение
MOV KEEP_CS,ES ;запоминаем сегмент
; ---в конце программы
CLI
PUSH DS ;DS будет разрушен
MOV DX,KEEP_IP ;подготовка к восстановлению
MOV AX,KEEP_CS ;
MOV DS,AX ;подготовка к восстановлению
MOV AH,25H ;функция установки вектора
MOV AL,1CH ;номер вектора
INT 21H ;восстанавливаем вектор
POP DS ;восстанавливаем DS
STI

Имеется пара ловушек, которых следует избегать при написании прерывания. Если новая процедура прерывания должна иметь доступ к данным, то необходимо позаботиться, чтобы DS был правильно установлен (обычно прерывание может использовать стек вызывающей программы). Другая неприятность может заключаться в том, что при завершении программы по Ctrl-Break вектор прерывания не будет восстановлен, если только Вы не предусмотрите, чтобы программа реакции на Ctrl-Break выполняла эту процедуру {3.2.8}.

Hизкий уровень.

Описанные выше функции MS DOS просто получают или изменяют пару слов в младших ячейках памяти. Смещение вектора может быть вычислено простым умножением номера вектора на 4. Hапример, чтобы получить адрес прерывания 16H в ES:BX:
;---получение адреса прерывания 16H
SUB AX,AX ;устанавливаем ES на начало памяти
MOV ES,AX ;
MOV DI,16H ;номер прерывания в DI
SHL DI,1 ;умножаем на 2
SHL DI,1 ;умножаем на 2
MOV BX,ES:[DI] ;берем младший байт в BX
MOV AX,ES:[DI]+2 ;берем старший байт в ES
MOV ES,AX ;

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


<~-1.2.2 Запрет/разрешение отдельных аппаратных прерываний.
Содержание
1.2.4 Дополнение к существующему прерыванию.-~>

Сайт управляется системой uCoz