Краткие теоретические сведения. Прерывания (Interrupt) — предусмотренный в системе механизм изменения естественного порядка выполнения программ с целью обработки возникающих событий и для

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

В архитектуре ЭВМ на основе процессоров x86 (реальный режим) выделяются внутренние прерывания процессора — исключения (exception), возникающие при исполнении инструкций, маскируемые и немаскируемые внешние прерывания. Среди исключений выделяются вызванные специаль­ными инструкциями генерации прерываний int; их принято выделять как программные прерывания. Всего определено 256 прерываний, назначение части из которых документировано и закреплено за определенными источниками или программами-обработчиками, но большинство считаются зарезервированными для использования ОС и прикладными программами.

Для любых прерываний обработка их непосредственно процессором заканчивается выборкой адреса обработчика этого прерывания и передачей ему управления. Адреса обработчиков принято назвать векторами прерываний, они хранятся в таблице векторов, которая занимает первый физический килобайт адресного пространства x86.

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

Вызов обработчика отличается от обращения к обычным подпрограммам тем, что в стеке помимо адреса возврата сохраняется также и регистр флагов. Соответственно, при выходе из обработчика его надо или восстановить из стека (инструкция процессора iret или retf), или отбросить (инструкция возврата с очисткой стека ret 2). Вызов обработчика и возврат из него всегда дальние (far) — адреса обработчика и точки возврата включают и смещение, и сегмент.

Резидентная программа, или TSR (Terminate-and-Stay-Resident) — в отличие от обычной, называемой транзит­ной, целиком или частично остается в памяти после того, как возвращает управление системе. Очевидно, выделение резидентных программ имеет смысл только в однозадачных системах.

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

В общем случае, обработчик должен:

– сохранить текущий контекст выполнения, так как его вызов может произойти в любой момент времени и на фоне любой другой программы (если иметь в виду обработчик в резидентной программе);

– подготовить контекст для своего выполнения, в том числе проверить условия активизации;

– выполнить специфические функции, связанные с назначением обработчика;

– возможно, обратиться к сохраненному вектору прерывания;

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

Можно выделить несколько основных схем включения обработчика прерывания в каскад (цепочку).

1. Замещение — новый обработчик полностью перекрывает старый.

New_Handler PROC FAR

push …;сохранение контекста

…;функции обработчика

pop …;восстановление контекста

iret;возврат из обработчика

New_Handler ENDP

2. Предобработка — новый обработчик выполняет свои функции (например проверяет условия и модифицирует параметры) и затем передает управление старому.

New_Handler PROC FAR

push …;сохранение контекста

…;функции обработчика

pop …;восстановление контекста

jmp dword ptr cs:old_handler_off;передача управления старому обработчику

New_Handler ENDP

3. Постобработка — новый обработчик обращается к старому, вновь получает управление после его завершения и затем выполняет свои функции (например, модифицирует результат)

New_Handler PROC FAR

push …;сохранение контекста

…;функции обработчика

pop …;восстановление контекста

pushf;эмуляция «обычного» вызова обработчика

call dword ptr cs:old_handler_off; обращение к старому обработчику

iret;возврат из обработчика

New_Handler ENDP

4. Комбинированный — например, проверка условий, в зависимости от них подготовка параметров, вызов старого обработчика и затем модификация результата.

New_Handler PROC FAR

push …;сохранение контекста

…;функции обработчика

pop …;восстановление контекста

pushf;эмуляция «обычного» вызова обработчика

call dword ptr cs:old_handler_off;обращение к старому обработчику

push …

…;продолжение функций обработчика

pop …

iret;возврат из обработчика

New_Handler ENDP

Кроме показанных, есть более изощренные способы организации переходов и вызовов процедур. Например, можно разместить ячейки, хранящие адрес, непосредственно в коде процедуры-обработчика, предварив их кодом инструкции call far или jmp far с прямой адресацией. Бóльший практический интерес представляет следующая конструкция:

pushf

push <segment_to_jmp>

push <offset_to_jmp>

retf

Её результат эквивалентен «обычному» jmp far, но в отличие от косвенной адресации точки перехода не требуется обязательное наличие переменной, содержащей готовый адрес. Загружаемые в стек компоненты адреса могут быть константами, вычисляемыми значениями, находиться в регистрах и так далее в любых сочетаниях. Такой прием полезен при ограничениях на использование переменных, например если программа находится в ПЗУ. Аналог­ичным образом получается и эквивалент инструкции call far.

Если новый обработчик был установлен на внешнее прерывание, и нет передачи управления старого обработчика, то перед выходом необходимо разрешить работу внешнего контроллера прерываний, в противном случае новые прерывания останутся заблокированы:

mov al, 20h

out 20h, al

Однако если обращение к старому обработчику есть, то он уже выполняет эту операцию, и дублировать ее в своем коде не следует.

С осторожностью следует относиться и к разрешению или запрету прерываний посредством флага IF. Стандартно он сбрасывается перед переда­чей управления обработчику, а после завершения восстанавливается предыду­щее значение всего регистра флагов. Аккуратность требуется, если сохранен­ные флаги игнорируются (возврат командой ret 2), а новое содержимое регистра FLAGS формируется самим обработчиком.

MS-DOS обеспечивает следующие основные функции прерывания int 21h для работы с прерываниями, их обработчиками и резидентными программами.

AH=25h — установка вектора прерывания. Вход: AL — номер вектора, DS:DX — адрес нового устанавливаемого обработчика.

AH=35h — получение вектора прерывания. Вход: AL — номер вектора. Выход: ES:BX — адрес текущего обработчика.

AH=31h — завершение программы с сохранением ее резидентной. Вход: AL — код возврата, DX — размер оставляемой в памяти части программы (в параграфах)..

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

; начало резидентной части

Start:

jmp Init

; область переменных

old_handler_off DW?

old_handler_seg DW?

; код обработчиков

New_Handler PROC FAR

call dword ptr cs:old_handler_off

iret

New_Handler ENDP

; конец резидентной части

; транзитная часть – секция инициализации

Init:

…;другие подготовительные операции

; получение и сохранение адреса старого обработчика

mov ah, 35h

mov al, <номер_вектора>

int 21h

mov cs:old_handler_off, bx

mov cs:old_handler_seg, es

; установка нового обработчика

mov ah, 25h

mov al, <номер_вектора>

mov dx, seg New_Handler

mov ds, dx

lea dx, New_Handler

int 21h

…;другие завершающие операции

; вычисление размера резидентной части

; и завершение программы, оставляя ее резидентной

mov ax, 3100h

mov dx, offset Init

add dx, 0Fh

shr dx, 1

shr dx, 1

shr dx, 1

shr dx, 1

int 21h

END Init

Метка Start: и инструкция jmp в начале программы избыточны — при явном указании метки при директиве END выполнение программы будет начинаться именно с нее. Однако этот элемент оформлении может быть легко забыт, тогда стартовой точкой программы становится первая объявленная метка. Кроме того, в формате исполняемого файла COM (модель памяти TINY) возможности управлять начальной меткой нет, управление всегда передается на начало программы. Одновременно, для COM-формата потребуется директива ORG 100h для пропуска сегмента PSP.

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

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

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

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

Контрольные вопросы

1) Понятие прерывания и его обработчика.

2) Таблица векторов прерываний.

3) Особенности обработки аппаратных и программных прерываний.

4) Основные прерывания BIOS и операционной системы DOS.

5) Способы перехвата и обработки (перекрытия) прерываний.

6) Каркас обработчиков прерываний.

7) Резидентные программы.

8) Каркас резидентной программы.

9) Обработка прерывания клавиатуры, таймера.

10) Обработка программных прерываний.

Варианты заданий

1. Перекрыть прерывание клавиатуры и сделать так, чтобы буква “a” подменялась на букву “b”.

2. Перекрыть прерывание клавиатуры и сделать так, чтобы все согласные буквы игнорировались.

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

4. Перекрыть прерывание клавиатуры и сделать так, чтобы вместо каждой введенной цифры вводилось две. Например, вместо “1” получалось “11”.

5. Перекрыть прерывание клавиатуры и сделать так, чтобы все введенные цифры заменялись на следующие по порядку.

6. Перекрыть прерывание клавиатуры и сделать так, чтобы регистр вводимых букв менялся с нижнего на верхний (или наоборот).

7. Перекрыть прерывание клавиатуры и сделать так, чтобы все вводимые цифры суммировались в переменной summa.

8. Перекрыть прерывание клавиатуры и сделать так, чтобы пробелы игнорировались.

9. Перекрыть прерывание клавиатуры и сделать так, чтобы вместо пробела вводился символ ввода.

10. Перекрыть прерывание таймера и сделать так, чтобы каждые 5 секунд на экране выводился заданный текст (например “go”).

11. Модифицировать прерывание 21h так, чтобы при выводе строки на экран функцией 09h регистр букв в строке менялся с верхнего на нижний (или наоборот).

12. Модифицировать прерывание 21h так, чтобы при выводе строки на экран функцией 09h в строке подсчитывалась считалась сумма всех цифр и эта сумма выводилась на экране вместо строки.

13. Модифицировать прерывание 21h так, чтобы при выводе строки на экран функцией 09h вместо строки показывалось число слов в ней.

14. Модифицировать прерывание 21h так, чтобы при вводе строки функцией OAh во введенной строке удалялись все пробелы.

15. (повышенной сложности) Написать драйвер виртуального символь­ного устройства — генератор псевдослучайной последовательности.

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

При чтении из созданного устройства возвращается содержимое переменной. Необходимо обеспечить корректное считывание многобайтных значений.

16. (повышенной сложности) Написать драйвер виртуального символь­ного устройства — текущие дата и время.

При считывании из созданного логического устройства драйвер получает дату и время, используя функции BIOS или DOS, и возвращает его программе, читающей из устройства.

Лабораторная работа 5:
Сложные обработчики
и взаимодействие резидентных программ


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: