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

Error message

Notice: Undefined index: add term path in hansel_get_breadcrumbs() (line 524 of /data/sites/msdosworld.ru/www/sites/all/modules/hansel/hansel.module).

   Имеется  несколько причин для написания собственного  прерыва-
ния. Во-первых, большинство из готовых прерываний, обеспечиваемых
операционной системой, ничто иное, как обычные процедуры, доступ-
ные для всех программ, и Вы  можете  пожелать добавить свое в эту
библиотеку.   Например, многие Ваши программы могут  использовать
процедуру, выводящую строки на  экран  вертикально.  Вместо того,
чтобы  включать  ее  в каждую программу в качестве  процедуры  Вы
можете установить ее как  прерывание,  написав программу, которая
останется резидентной в памяти после завершения [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]
позволяют компьютеру быстро  переключаться  между операциями вво-
да/вывода и другой обработкой.
   Наконец, Вы можете захотеть написать прерывание, которое  пол-
ностью заменит одну из процедур  операционной системы, приспособ-
ленное к Вашим программным нуждам.  В [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].
   Когда программа завершается, должны быть восстановлены  ориги-
нальные вектора прерываний. В  противном случае последующая прог-
рамма может вызвать данное прерывание и передать управление на то
место в памяти, в котором  Вашей  процедуры  уже нет.  Функция 35
прерывания  21H возвращает текущее значение  вектора  прерывания,
помещая значение сегмента в ES, а смещение в BX. Перед установкой
своего  прерывания  получите текущее значение вектора,  используя
эту функцию, сохраните эти  значения,  и  затем восстановите их с
помощью функции 25H (как выше) перед завершением своей программы.
Например:

;---в сегменте данных:
   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].

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

   Описанные выше функции MS  DOS  просто  получают  или изменяют
пару  слов в младших ячейках памяти.  Смещение вектора может быть
вычислено простым умножением номера вектора на 4. Например, чтобы
получить адрес прерывания 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         ;

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



 

Вы находитесь в разделе: 

Добавить коментарий