Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Финогенов-основы_языка_ассемблера.doc
Скачиваний:
26
Добавлен:
17.09.2019
Размер:
3.35 Mб
Скачать

Глава 3

Команды и алгоритмы

109

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

Обработчики прерываний являются важнейшей составной частью многих программных продуктов. Как было показано в гл. 1, прерывания разделяются на внутренние, возникающие в самом микропроцессоре в случае определенных сбоев (попытка деления на 0, несуществующая ко­манда), внешние, приходящие из периферийного оборудования (клавиа­тура, мышь, диски, нестандартные устройства, подключенные к компь­ютеру) и программные, являющиеся реакцией процессора на команду int с тем или иным номером. В прикладных программах приходится обрабаты­вать, главным образом, внешние и программные прерывания. Общие прин­ципы обслуживания тех и других прерываний одинаковы, однако условия функционирования обработчиков аппаратных прерываний имеют значи­тельную специфику, связанную, главным образом, с тем, что прерыва­ния от аппаратуры приходят в произвольные моменты времени и могут прервать текущую программу в любой ее точке. Обработчик прерывания должен быть написан таким образом, чтобы его выполнение ни в какой степени не отразилось на правильном функционировании текущей (пре­рываемой) программы.

Инициализация

обработчика

прерываний


Прерывание 1 Прерывание 2

Р ассмотрим схематически структуру и функционирование программ­ного комплекса, включающего собственный обработчик какого-либо ап­паратного прерывания (рис. 3.4).

Дальнейший ход программы

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

Рис. 3.4. Функционирование программного комплекса с обработчиком прерываний.

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

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

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

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

Установив обработчик, программа может приступить к дальнейшей работе. В случае прихода прерывания, процессор сохраняет в стеке флаги и текущий адрес программы, извлекает из вектора адрес обработчика и передает управление на его входную точку. Все время, пока выполняется программа обработчика, основная программа, естественно, стоит. Завер­шающая обработчик команда iret извлекает из стека сохраненные там дан­ные и возвращает управление в прерванную программу, которая может продолжить свою работу. Последующие прерывания обслуживаются точно так же.

Функции обработчика прерываний зависят от решаемой задачи и на­значения того устройства, от которого поступают сигналы прерываний. В случае прерываний от клавиатуры задача обработчика прерываний — при­нять и сохранить код нажатой клавиши. Прерывания от мыши свидетель­ствуют о ее перемещении, что требует обновления положения курсора на экране. Если обслуживаемым устройством является физическая установ­ка, то сигнал прерывания может говорить о том, что в установке накоп­лен определенный объем данных, которые надо перенести из памяти ус-, тановки в память компьютера. В любом случае обработчик прерываний должен быть программой несложной, для выполнения которой не требу­ется много машинного времени.

Рассмотрим структуру программы с обработкой аппаратных прерыва-шй. Наиболее удобным аппаратным прерыванием, которое можно ис-юльзовать в исследовательских целях, является прерывание от систем йо­та и мера, которое генерируется 18.2 раза в секунду и служит источни-)м сигналов для хода системных часов, отсчитывающих время, истекшее юсле включения машины. Замена системного обработчика на приклад-сой не приводит к каким-либо неприятностям, кроме, возможно, оста-совки на некоторое время системных часов.

Ъ.нанды и алгоритмы

110

III

Будем считать, что наш программный комплекс представляет собой программу типа .ЕХЕ и что обработчик прерываний входит в общий с основной программой программный сегмент. Для определенности будем использовать вектор 08U, хотя, разумеется, для любого другого аппарат­ного вектора структура программы останется той же. Поначалу приведем текст программы с некоторыми купюрами.

;Пример 3-3. Обработчик прерываний от таймера code segment

assume CS:code,DS:data

;Главная процедура main ртос

mov AX,data Инициализация сегментного

mov DS,AX ;регистра DS

;Сохраним исходный вектор

mov AH,35h ;Функция получения вектора

mov AL,08h ;Номер вектора * -

int 21h

mov word ptr old_08,BX;Смещение исходного ;обработчика

mov word ptr оШ_08-$-2,Е5;Сегмент исходного обработчика ;Установим наш обработчик

mov AH,25h ;Функция заполнения вектора ч

mov AL,08h ;Номер вектора , .

mov DX,offset lгew_08;Cмeщeниe нашего ;обработчика

push DS ;Сохраним DS=data

push CS ;Перешлем CS в DS

pop DS ;через стек. DS:DX->new_08 ;,

int 21h v

pop DS ;Восстановим DS=data :;..

;Продолжение основной программы :\ . ;Перед завершением профаммы восстановим исходный вектор

;3аполним DS:DX из old_09 ;Функция заполнения вектора ;Номер вектора

;Функция завершения профаммы

Ids DX,oIdJ)8

mov AH,25h

mov AL,09h

int 21h

mov AX,4COOh

hit 21h

main endp K,-

;Процедура обработчика прерываний от таймера , .•

new_08 proc i ;.

;Действия, выполняемые 18 раз в секунду

mov AL,20h разблокировка прерываний L-

out 20h,AL ;в контроллере прерываний и

iret ;Возврат в прерванную программу &Ь

ne-wj)8 endp ^

code ends

data segment

old_08 dd 0 ;Ячейка для хранения исходного вектора

data ends

stk segment stack

db 256 dup (0) . .

stk ends

end main

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

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

Хотя и чтение, и заполнение вектора прерываний можно выполнить с помощью простых команд mov, однако предпочтительнее использовать специально предусмотренные для этого функции DOS. Для чтения векто­ра используется функция с номером 35h. В регистр AL помешается номер вектора. Функция возвращает исходное содержимое вектора в парс регис­тров ES:BX (легко догадаться, что в ES сегментный адрес, а в ВХ смеще­ние). Для хранения исходного содержимого вектора в сегменте данных предусмотрена двухсловная ячейка old_08. В младшем слове этой ячейки (с фактическим адресом old_08) будет хранится смещение, в старшем (с фактическим адресом old_08+2) — сегментный адрес. Для того, чтобы обратиться к словам, составляющим эту ячейку, приходится использо­вать описатель word ptr, который как бы заставляет транслятор на время забыть о начальном объявлении ячейки и позволяет рассматривать ее, как два отдельных слова. Если бы мы отвели для исходного вектора две 16-битовые ячейки, например

old_08_offs dw 0 ;Для смещения old_08_seg dw 0 ;Для сегментного адреса

то к ним можно было бы обращаться без всяких описателей.

Сохранив исходный вектор, можно установить в нем адрес нашего обработчика. Для установки вектора в DOS предусмотрена функция 25h. Она требует указания номера устанавливаемого вектора в регистре AL, a

112