
LRP1
.pdfсором, когда он встречается с некоторыми особыми событиями вроде деления на 0. Это прерывания с номерами 0, 1, 3, 4 (см. табл.1).
В таблице 1 дано описание наиболее важных прерываний. Таблица 1
┌───────────┬────────────────────────────────────────────────────┐ │ Номер │ Описание │
└───────────┴────────────────────────────────────────────────────┘ 0 Ошибка деления. Вызывается автоматически после
выполнения команд DIV или IDIV, если в результате
деления произошло переполнение. DOS обычно при об работке этого прерывания выводит сообщение об ошибке и остановливает выполнение программы. Для процессора 8086 при этом адрес возврата указывает на следующую после команды деления команду, а в процессоре 80286 - на первый байт команды, вызвавшей прерывание
1Прерывание пошагового режима. Вырабатывается после выполнения каждой машинной команды, если в слове флагов установлен бит пошаговой трассировки TF. Используется для отладки программ. Прерывание не вырабатывается после выполнения команды MOV в сегментные регистры или после загрузки сегментных регистров командой POP
2Аппаратное немаскируемое прерывание. Это прерывание может использоваться по-разному в разных машинах. Обычно вырабатывается при ошибке четности в оперативной памяти и при запросе прерываний от сопроцессора
3Прерывание для трассировки. Это прерывание генерируется при выполнении однобайтовой команды с кодом CCh
иобычно используется отладчиками для установки точки прерывания
4Переполнение. Генерируется машинной командой INTO, если установлен флаг OF. Если флаг не установлен, то
команда INTO выполняется как NOP. Это прерывание ис-
пользуется для обработки ошибок при выполнении арифметических операций
────────────────────────────────────────────────────────────────
21
Продолжение табл.1 ┌───────────┬────────────────────────────────────────────────────┐ │ Номер │ Описание │
└───────────┴────────────────────────────────────────────────────┘
5Печать копии экрана. Генерыруется при нажатии на клавиатуре клавиши PrtScr. Обычно используется для печати образа экрана. Для процессора 80286 генерируется при выполнении машинной команды BOUND, если проверяемое значение вышло за пределы заданного диапазона
6Неопределенный код операции или длина команды больше 10 байтов (для процессора 80286)
7Особый случай отсутствия сопроцессора
8IRQ0 - прерывание интервального таймера, возникает 18,2 раза в секунду
9IRQ1 - прерывание от клавиатуры. Генерируется при нажатии и при отжатии клавиши. Используется для чтения данных от клавиатуры
AIRQ2 - используется для каскадирования аппаратных прерываний в машинах класса AT
BIRQ3 - прерывание асинхронного порта COM2
CIRQ4 - прерывание асинхронного порта COM1
DIRQ5 - прерывание от контроллера жесткого диска для XT
EIRQ6 - прерывание генерируется контроллером флоппи-дис- ка после завершения операции
FIRQ7 - прерывание принтера. Генерируется принтером, когда он готов к выполнению очередной операции. Многие адаптеры принтера не используют это прерывание
10 Обслуживание видеоадаптера
──────────────────────────────────────────────────────────────────
22
Продолжение табл.1 ┌───────────┬────────────────────────────────────────────────────┐ │ Номер │ Описание │
└───────────┴────────────────────────────────────────────────────┘
11Определение конфигурации устройств в системе
12Определение размера оперативной памяти в системе
13Обслуживание дисковой системы
14Последовательный ввод/вывод
15Расширенный сервис для AT-компьютеров
16Обслуживание клавиатуры
17Обслуживание принтера
18Запуск BASIC в ПЗУ, если он есть
19Загрузка операционной системы
1A Обслуживание часов
1B Обработчик прерываний Ctrl-Break
1C Прерывание возникает 18,2 раза в секунду, вызывается программно обработчиком прерывания таймера
1D Адрес видеотаблицы для контроллера видеоадаптера 6845
1E Указатель на таблицу параметров дискеты
1F Указатель на графическую таблицу для символов с кодами
ASCII 128-255
20-5F Используются DOS или зарезервированы для DOS
60-67 Прерывания, зарезервированные для пользователя
────────────────────────────────────────────────────────────────
23
Продолжение табл.1 ┌───────────┬────────────────────────────────────────────────────┐ │ Номер │ Описание │
└───────────┴────────────────────────────────────────────────────┘
68-6F Не используются
70IRQ8 - прерывание от часов реального времени
71IRQ9 - прерывание от контроллера EGA
72IRQ10 - зарезервировано
73IRQ11 - зарезервировано
74IRQ12 - зарезервировано
75IRQ13 - прерывание от сопроцессора
76IRQ14 - прерывание от контроллера жесткого диска
77IRQ15 - зарезервировано
78-7F Не используются
80-85 Зарезервированы для BASIC
86-F0 Используются интерпретатором BASIC
F1-FF Не используются
─────────────────────────────────────────────────────────────
3.2. Таблица векторов прерываний.
Для того чтобы связать номер прерывания с адресом программы обработки прерываний (обработчика прерываний), используется таблица векторов прерываний, занимающая первый килобайт оперативной памяти - адреса от 0000:0000 до 0000:03FF. Таблица состоит из 256 элементов - FAR-адресов обработчиков прерываний. Эти элементы называются векторами прерываний. В первом слове элемента таблицы записано смещение, а во втором - сегмент адреса обработчика прерываний.
Прерыванию с номером 0 соответствует адрес 0000:0000, прерыванию с номером 1 - 0000:0004 и т.д. Прерыванию с номером n будет соответствовать адрес 0000:4*n.
24
Инициализация таблицы происходит частично программой BIOS после тестирования аппаратуры, частично при загрузке DOS. DOS может переключить на себя некоторые прерывания BIOS.
3.3. Обработка прерываний.
Несмотря на многообразие типов прерываний алгоритм обработки прерывания процессором один и тот же и изображен на рис.2.
|
|
|
|
┌ |
|
|
|
──1──────── |
|
│ N - номер вектора |
|
|
|
Начало |
─ |
─ ─ │ |
прерывания |
|
|
─────────── |
|
└ |
|
|
┌ |
|
|
┌ |
|
|
│ ┌──2──────────┐ |
│ поместить в стек |
|||
|
│ │ |
|
│─ |
─ ─ │ регистр флагов |
|
|
│ └─────────────┘ |
└ |
|
||
|
│ |
|
|
┌ |
|
|
│ |
┌──3──────────┐ |
│ обнулить флаги |
||
|
│ |
│ |
│─ ─ ─ │ IF и TF |
||
|
│ |
└─────────────┘ |
└ |
|
|
|
│ |
|
|
┌ |
|
|
│ |
┌──4──────────┐ |
│ поместить в стек |
||
|
│ |
│ |
│─ ─ ─ │ значение регистра CS |
||
|
│ |
└─────────────┘ |
└ |
|
|
команда |
│ |
|
|
┌ присвоить адресу |
|
Int |
│ |
┌──5──────────┐ |
│ вектора прерывания |
||
(interrupt) < |
|
│ |
│─ ─ ─ │ значение N*4 |
||
|
│ |
└─────────────┘ |
└ |
|
|
|
│ |
|
|
┌ загрузить второе слово |
|
|
│ |
┌──6──────────┐ |
│ вектора прерываний |
||
|
│ |
│ |
│─ ─ ─ │ |
в регистр CS |
|
|
│ |
└─────────────┘ |
└ |
|
|
|
│ |
|
|
┌ |
|
|
│ |
┌──7──────────┐ |
│ поместить в стек |
||
|
│ |
│ |
│─ ─ ─ │ значение IP |
||
|
│ |
└─────────────┘ |
└ |
|
|
|
│ |
|
|
┌ загрузить первое слово |
|
|
│ |
┌──8──────────┐ |
│ вектора прерываний |
||
|
│ |
│ |
│─ ─ ─ │ в указатель команд IP |
||
|
│ |
└─────────────┘ |
└ |
|
|
|
└ |
|
|
|
|
|
|
|
25 |
|
|
|
|
|
|
┌ выполнить действия |
|
|
┌──9──────────┐ |
│ по обслуживанию |
|
|
|
│ |
│─ ─ ─ │ данного прерывания |
|
|
|
└─────────────┘ |
└ |
|
|
┌ |
|
|
┌ извлечь из стека значение |
|
│ |
┌──10─────────┐ |
│ и загрузить в |
|
|
│ |
│ |
│─ ─ ─ │ указатель команд IP |
|
|
│ |
└─────────────┘ |
└ |
|
|
│ |
|
|
┌ извлечь из стека значение |
команда |
│ |
┌──11─────────┐ |
│ и загрузить в регистр |
|
Iret |
< |
│ |
│─ ─ ─ │ сегмента команд CS |
|
(interrupt |
│ |
└─────────────┘ |
└ |
|
return) |
│ |
|
|
┌ извлечь из стека значение |
|
│ |
┌──12─────────┐ |
│ и загрузить в |
|
|
│ |
│ |
│─ ─ ─ │ регистр флагов |
|
|
│ |
└─────────────┘ |
└ |
|
|
└ |
|
|
|
──13───────
Конец
───────────
Рис. 2.
3.4. Маскирование прерываний.
Часто при выполнении критических участков программ, для того чтобы гарантировать выполнение определенной последовательности команд, приходится запрещать прерывания. Это можно сделать командой CLI (сброс флага разрешения прерывания). Ее нужно поместить в начало критической последовательности команд, а в конце расположить команду STI (установить флаг разрешения прерывания). Команда CLI запрещает только маскируемые прерывания, немаскируемые всегда обрабатываются процессором.
Если вы используете запрет прерываний с помощью команды CLI, следите за тем, чтобы прерывания не отключались на длительный период времени, т.к. это может привести к нежелательным последствиям, например, будут отставать часы.
Если надо запретить не все прерывания, а только некоторые, например, от клавиатуры, то для этого надо воспользоваться услугами контроллера прерываний.
3.5. Изменение таблицы векторов прерываний. Если программе потребуется организовать обработку некоторых прерываний, то для этого необходимо переназначить требуемый вектор прерываний на свой
26
обработчик. Это можно сделать, изменив содержание соответствующего элемента таблицы векторов прерываний.
Очень важно не забыть перед завершением работы программы восстановить содержимое измененных векторов, т.к. после завершения работы программы память, которая ей была распределена, считается свободной и может быть использована для загрузки другой программы. Если вектор не был восстановлен, и пришло прерывание, то работа системы может нарушиться - вектор теперь указывает на область, которая может содержать все, что угодно.
Поэтому последовательность действий для нерезидентных программ, обрабатывающих прерывания, должна быть такой:
-прочитать содержимое элемента таблицы векторов прерываний для вектора с номером того прерывания, какое требуется обработать; -запомнить это содержимое (адрес старого обработчика прерыва-
ний) в области данных программы; -установить новый адрес в таблице векторов прерываний так,
чтобы он соответствовал началу программы обработки прерываний пользователя;
-перед завершением работы программы прочитать из области данных адрес старого обработчика прерывания и записать его в таблицу векторов прерываний.
Отметим, что для резидентных программ (т.е. программ постоянно находящихся в оперативной памяти) последний пункт выполнять не нужно.
Операция изменения вектора прерываний должна быть непрерывной в том смысле, что во время изменения не должно произойти прерывание с номером, для которого производится замена программы обработки. Если, например, будет записано новое значение смещения, а сегмент адреса не успеет обновиться, то по какому адресу будет передано управления в случае прерывания и что при этом произойдет?
Поэтому перед записью в вектор прерываний нужно запретить прерывания командой CLI, а после записи - разрешить командой STI.
Для облегчения работы по замене прерывания DOS имеет специальные функции для чтения элемента таблицы прерываний и для записи в нее нового адреса. Правильность операций при этом будет гарантирована.
Для чтения вектора используйте функцию 35h DOS (прерывания 21 h). Перед ее вызовом регистр AL должен содержать номер вектора в таблице. После выполнения функции в регистрах ES:BX будет искомый адрес обработчика прерывания.
Функция 25h DOS установливает для вектора с номером, находящимся в AL, обработчик прерываний DS:DX.
27
3.6. Коррекция системных обработчиков прерываний.
Если необходимо добавить какие-либо собственные действия к тем, что выполняет стандартный обработчик прерывания, то можно организовать цепочку прерываний.
Для организации цепочки прерываний необходимо записать в таблицу векторов адрес собственного обработчика, не забыв сохранить прежнее содержимое таблицы. Обработчик пользователя получает управление по прерыванию, выполняет какие-либо действия, затем передает управление стандартному обработчику. Можно сделать и по-дру- гому: Обработчик пользователя вызывает стандартный обработчик, а затем выполняет дополнительные действия. Т.е. можно вставить дополнительную обработку как до вызова стандартного обработчика, так и после его вызова.
3.7. Состояние клавиш-переключателей.
В таблице 2 приведен формат байта по адресу 0040H:0017H, содержащий текущие состояния клавиш-переключателей.
Таблица 2
──────────────────────────────────────
Бит Значение, когда бит=1
──────────────────────────────────────
0нажата клавиша правый Shift
1нажата клавиша левый Shift
2нажата клавиша Ctrl
3нажата клавиша Alt
4режим ScrollLock включен
5режим NumLock включен
6режим CapsLock включен
7режим вставки включен
───────────────────────────────────────
4.Порядок выполнения
4.1.Разработать собственную процедуру обработки прерывания (см. п. 5.1.4), которая выполняла бы следующие действия:
-вызов программы обработки прерывания (см. п. 5.1.3) с одним из номеров прерывания, зарезервированных для пользователя (см. табл. 1);
-анализ состояния заданной клавиши-переключателя согласно таблицы 2;
-при нажатии клавиши - вывод на экран ее наименования.
28
4.2. Разработать программу, выполняющие следующие действия: -сохранить адрес системной программы обработки прерывания Int9; -записать адрес этой системной программы в таблицу векторов
прерываний по выбранному номеру прерывания пользователя; -записать адрес собственной процедуры обработки прерывания в
таблицу векторов по номеру 9; -завершить программу и оставить ее в памяти резидентной.
4.3. При работе с Турбо Паскалем получить Exe-файл программы на диске (для этого компилировать программу с опцией
Destination Disk) и, выйдя из среды Турбо Паскаля, запустить программу на выполнение.
5.Особенности программирования
5.1.На языке Турбо-Паскаль.
5.1.1. Для чтения вектора прерывания и для изменения таблицы векторов прерываний используйте предопределенный массив MemW. Например, для чтения смещения вектора 9 можно применить выражение
ofs_:= MemW[0000:4*9];
а для записи сегмента адреса обработчика прерываний в $60-й вектор прерываний -
Memw[0000:4*$60+2]:=Seg(Int9d);
где: ofs_:word - переменная для временного хранения значения смещения;
Int9d - имя процедуры обработки (коррекции) прерывания 9.
5.1.2. Для запрещения и разрешения прерываний используйте либо команды на ассемблере:
begin
. . . . .
asm
Cli {прерывания запрещены} end
. . . . .
asm
29
Sti |
{прерывания разрешены} |
end |
|
. . . . . . |
|
либо операторы Inline с машинными командами: |
|
begin |
|
. . . . . |
|
Inline($fa) |
{ Cli } |
. . . . . . |
|
Inline($fb) |
{ Sti } |
. . . . . . |
|
Inlin |
|
5.1.3. Для вызова программ обработки заданного прерывания используется процедура Intr.
Процедура Intr имеет следующую форму:
Intr(IntNo : byte; var Reg : Registers),
где:IntNo - номер прерывания (0...255),
Reg - запись типа Registers, определенного в модуле DOS, содержащая значения регистров процессора. Надо указать в программе модуль DOS после uses или включить в программу следующее описание типа записи:
type
Registers = record case integer of
0:(AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : word);
1:(AL, AH, BL, BH, CL, CH, DL, DH : byte); end;
где: AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags,AL,AH,BL,BH,CL, CH,DL,DH
- переменные, соответствующие одноименным регистрам процессо-
ра.
При выполнении программного прерывания (выполнении процедуры
Intr) процедура Intr загружает регистры AX, BX, CX, DX, BP, SI, DI, DS и ES процессора значениями из записи Regs (задаются пользователем). Когда обработка прерывания завершается, содержимое ре-
гистров AX, BX, CX, DX, BP, SI, DI, DS, ES и Flags возвращается в запись Regs.
Ограничения: Программные прерывания, которые зависят от опре30