ОСНОВЫ МИКРОПРОГРАММИРОВАНИЯ
Порядок действий при прерывании:
Фрагмент таблицы прерываний
ПРИМЕР
Ситуация в памяти после загрузки на исполнение EXE- и COM- программы
Нажатие клавиши
Пример 1. Перехватывает аппаратное прерывание от клавиатуры (тип 9). Реализована схема 1. Программа предназначена для работы в
Пример 1. продолжение...
297.45K
Category: programmingprogramming

ОМП-11

1. ОСНОВЫ МИКРОПРОГРАММИРОВАНИЯ

Лекция 10. Перехват прерываний и создание
резидентных программ
к.т.н., доц. каф. ВМиК
Ольга Сергеевна Нургаянова
ауд.6-417а
E-mail: onurgayanova@yandex.ru
1

2. Порядок действий при прерывании:

1. Процессор автоматически сохраняет в стеке адрес возврата, т.е. адрес той команды фоновой
программы, на которую мы должны будем вернуться из обработчика. Для этого процессор
заталкивает в стек содержимое трех регистров: F (регистр флагов), CS и IP.
Пара CS:IP задает адрес возврата.
2. После того как адрес возврата сохранен, процессор загружает в регистры CS и IP адрес первой
команды обработчика, который он берет из таблицы прерываний.
3. В конце обработчика программист пишет команду iret (возврат из прерывания).
По этой команде процессор выталкивает из стека адрес возврата (в регистры CS и IP) и флаги
(в регистр F). Происходит возврат в фоновую программу.
В процессорах Intel каждому прерыванию присвоен номер (тип).
Тип прерывания лежит в диапазоне 0 – 255.
Возможно 256 различных прерываний. Реально в компьютерах
задействованы не все 256 прерываний. Для задействованного
прерывания должен быть обработчик, расположенный в известном
2
месте памяти.

3. Фрагмент таблицы прерываний

Ситуация в памяти после загрузки на исполнение EXE- и COM- программы
5

4. ПРИМЕР

Нажатие клавиши
Контроллер клавиатуры выставляет СКЭН-код нажатой клавиши в порт 60h и формирует запрос на контроллер
прерываний. Последний передает этот запрос на процессор и сообщает процессору тип данного прерывания (тип 9).
Обработчик 9-го прерывания читает порт 60h, переводит СКЭН-код в ASCII-код (если нажата символьная клавиша, для
функциональных клавиш ASCI-код = 0) и помещает и СКЭН- и ASCII-коды в кольцевой буфер клавиатуры,
расположенный в области переменных BIOS. Адрес элемента буфера, в который была записана информация о
нажатой клавише, хранится в ячейке памяти с адресом 0041ah. Прикладные программы и операционная система
считывают информацию о нажатых клавишах уже из этого буфера. Для этого они либо используют
соответствующие сервисные прерывания (например, int 16h), либо работают с буфером напрямую:
; читаем из буфера информацию о нажатой клавише
mov ax, 40h
mov es, ax
;начальный адрес сегмента 00400h
mov bx, es:[1ah] ; в bx смещение (относительно es) ;ячейки, в которой записана информация о клавише
mov ax, es:[bx]
; теперь в ah – СКЭН-, а в al –;ASCII-коды
Код отжатия = код нажатия+128
Примечание. Для некоторых функциональных клавиш, появившихся на расширенной клавиатуре (101 клавиша и более), СКЭН-код (как
нажатия, так и отжатия) представляет собой последовательность байтов (два байта, а иногда (если, например, включен NUM LOCK) и четыре).
Например, когда нажимаем клавишу «стрелка – вверх», расположенную не на цифровой клавиатуре, возникают два прерывания и код нажатия
имеет вид e0 48h, также два прерывания возникает и когда эту клавишу отпускаем, а код отжатия имеет вид 0e c8h. При включенном режиме
NUM LOCK код нажатия этой клавиши имеет вид e0 2a e0 48h, а код отжатия – e0 c8 e0 aah (и при нажатии, и при отжатии возникают по четыре
6
прерывания). Эту ситуацию тоже иногда приходится учитывать.

5. Ситуация в памяти после загрузки на исполнение EXE- и COM- программы

Структура COM-программы
PSP
Область данных резидентной части
РЕЗИДЕНТНАЯ ЧАСТЬ
ЗАГРУЗОЧНАЯ (инициализирующая) ЧАСТЬ
Область данных загрузочной части
Завершить работу программы, оставив ее (или ее часть) в
памяти, можно с помощью прерывания int 27h. Входным
параметром этого прерывания является размер (в байтах)
оставляемой в памяти части программы (начиная с начала
программы, т.е. с PSP). Этот входной параметр задается
в dx. Определить размер оставляемой части можно,
поставив метку на первую команду загрузочной части
(например, start:) и написать команду mov dx, offset start.
7

6. Нажатие клавиши

Последовательность действий в загрузочной части может быть
примерно следующей:
1. Считать из таблицы прерываний старый вектор (функция 35h прерывания 21h).
2. Произвести проверку на повторную установку, при положительном результате перейти к пункту 6.
3. Сохранить старый вектор в известном (резиденту!) месте памяти.
4. Поместить в таблицу прерываний (на место старого вектора) новый вектор, указывающий на наш резидент
(функция 25h прерывания 21h).
5. Завершить программу, оставив ее резидентной (прерывание 27h).
6. Вывести сообщение о том, что программа уже установлена, и завершить программу, ничего не оставляя в
памяти (функция 4ch прерывания 21h).
Последовательность действий в резидентной части определяется назначением нашего резидента. Однако
если рассматривать эту последовательность на глобальном уровне, то можно выделить три основные схемы
действий резидентной части.
8

7.

Схема 1.
1. Сохраняем (в стеке) значения всех регистров фоновой программы, в том числе и сегментных, которые
портит наш резидент. Если этого не сделать, то фоновая программа при возврате получит испорченное
содержимое регистров и вряд ли будет работать корректно.
2. Выполняем требуемую обработку. Восстанавливаем значения регистров из стека (в обратном порядке!).
3. Передаем управление системному обработчику (командой jmp far), адрес которого нам сохранила
загрузочная часть. Системный обработчик впоследствии сам вернет управление фоновой программе
(командой iret).
9

8.

Схема 2.
1. Сохраняем значения регистров.
2. Передаем управление системному обработчику, выполнив команды:
pushf
call far
Первая команда заталкивает в стек содержимое регистра флагов, вторая – вызывает системный обработчик как
подпрограмму. (Возврат из этой «подпрограммы» происходит по команде iret, которая выталкивает из стека
адрес возврата и флаги! Именно поэтому нужна команда pushf.)
3. При возврате из системного обработчика управление снова получает наш резидент. Он выполняет
требуемые действия, восстанавливает регистры и возвращает управление фоновой программе (командой iret).
10

9.

Схема 3.
1. Сохраняем значения регистров.
2. Выполняем требуемую обработку.
3. Восстанавливаем регистры.
4. Возвращаем управление фоновой программе (командой iret).
В этой схеме полностью игнорируем системный обработчик и, следовательно, должны работать «за него». В
частности, если мы перехватываем аппаратное прерывание (от таймера, от клавиатуры и т.д.), то должны не
забыть снять «штору», которую ставит контроллер прерываний, послав число 20h в порт 20h. То есть здесь
должны знать и учитывать все нюансы работы аппаратуры. Именно поэтому эта схема на практике
используется редко.
11

10.

Пример 1. Перехватывает аппаратное прерывание от клавиатуры (тип 9). Реализована схема 1.
Программа предназначена для работы в текстовом режиме. Например, в графическом (не
полноэкранном) режиме FAR она может работать некорректно.
12

11.

Пример 1. продолжение...
13

12. Пример 1. Перехватывает аппаратное прерывание от клавиатуры (тип 9). Реализована схема 1. Программа предназначена для работы в

Пример 2. Перехватывает прерывание BIOS int 16h.
14

13. Пример 1. продолжение...

Пример 2. продолжение...
15
English     Русский Rules