- •Исследование программно управляемого обмена по готовности внешнего устройства и работы с прерываниями
- •1. Краткие теоретические положения
- •1.1. Состав рассматриваемой системы
- •2.2. Режимы обмена с периферийными устройствами
- •2.3. Реализация программного обмена между центральным процессором и контроллером клавиатуры посредством контроллера прерываний
- •3. Программирование таймера
- •Микросхема таймера 8254
- •Программирование таймера на уровне портов
- •Обработка прерываний
- •Взаимодействие обработчиков прерываний с основной программой
- •Задание на выполнение лабораторной работы
Обработка прерываний
Правила замены обработчика прерываний:
Адрес обработчика в таблице векторов прерываний вычисляется как номер вектора прерыванй умноженный на 4, так как каждый элемент таблицы представляет дальний указатель в формате смещение (2 байта по младшему адресу) и сегмента (2 байта по старшему адресу).
Адрес старого обрабочика прерыванй должен в обзяательном порядке сохраняться в памяти программы и восстанаваливаться в таблице векторов прерываний перед выходом из программы.
Процесс замены обработчика должен осуществляться при запрещенных прерываниях как минимум связанных с данным вектором или всех сразу путем очистки флага разрешения прерываний.
Пример:
old_int dd ?
…………………………………………….
xor AX , AX
mov ES , AX
mov DI , VECTOR_ADDR
mov AX , ES: [DI]
mov [word ptr old_int] , AX ; offset
mov AX , ES: [DI +2]
mov [word ptr old_int+2] , AX ; segment
cli
mov AX , offset NewInt
mov ES: [DI] , AX
mov AX , seg NewInt ; или cs для COM программ
mov ES: [DI+2] , AX
sti
Правила написания обработчив прерываний:
Обработчик прерываний описывается в виде процедуры, выполняющей указанные действия, оканчивающейся командой iret вместо ret. Разница между этими двумя командами состоит в том, что команда iret вынимает из стека не только точку возврата в виде дальнего указателя, но и состояние регистра флагов.
Обработчик прерывания должен иметь минимальную длительность исполнения, следовательно необходимо исключать все длительные операции.
При входе в обработчик прерывания процессор автоматически очищает флаг разрешения прерываний. Обработчик прерываний должен как можно скорее обеспечить его восстановление, чтобы дать возможность нормально функционировать другим обработчикам прерываний в соответствие с их приоритетами.
Передача параметров в обработчик прерываний производиться только посредством глобальных переменных. Исключение составляют только программно инициируемые прерывания, которые вызываются исключительно программными средствами, где параметры передаются через регистры (прерывания DOS и BIOS).
При входе в обработчик прерываний все регистры модифицируемые обработчиком прерывний должны сохраняться в стеке, а перед выходом из него восстанавливаться.
При проектировании обработчика прерываний следует учитывать, что все регистры могут иметь случайное значение, в том числе и сегментные регистры за исключением CS, так как обработчик прерывания может прервать другое прервание, которое могло относиться к резидентной программе или участку кода, работающего с другими сегментами данных. Поэтому перед тем как обращаться к переменным следует провести инициализацию соответсвующих сегментных регистров (ES,DS). Для COM программ допускается обращение к данным через сегментный регистр CS.
Во многих случаях обработчик прерываний должен вызывать старый обработчик прерываний, чтобы видоизменять или дополнять его функциональность и обеспечивать целостность работы системы. Если старый обработчик вызывается в начале или конце, то необходимо использовать вызов call [old_int] с предварительным сохранением регистра статуса в стеке с помощью команды pushf, а если в конце, то можно использовать вызов jmp [old_int], который заменяет команду iret. В данном примере old_int переменная типа double word, в которой хранится адрес старого обработчика.
В зависиости от режима программированния контроллера преррываний обработтчик прерывания должен сообщать об окончании обработки прерывания с помощью передачи команды 20h в порт 20h. Если в обработчике прерывания производится вызов старого обработчика, то это в большинстве случаев не требуется.
Пример обработчика прерывания:
proc NewInt
push AX
push DS
sti
mov AX , DATA_SEG ; Настроить сегмент данных
mov DS , AX
pushf ; Вызвать старый обработчик
call [old _int]
mov AL , 20h ; Послать команду окончания обработки (опционально)
out 20h, AL
pop DS
pop AX
iret
endp NewInt