Обработка программных и аппаратных прерываний в IBM PC совместимых компьютерах с помощью резидентных программ
Министерство образования и науки Российской Федерации
Федеральное государственное бюджетное образовательное
учреждение высшего профессионального образования
«Московский авиационный институт
(национальный исследовательский университет)»
филиал «Восход»
Кафедра ВТ
«Утверждаю»
Преподаватель __________ Иванин П.М.
«___»_______ 2012 г.
Курсовой проект
на тему: «Обработка программных и аппаратных прерываний в IBM PC совместимых компьютерах с помощью резидентных программ»
по дисциплине: Ассемблер
Студента гр. ВВМ5-58 ________ Свитавской А.А.
«___»_______ 2012 г.
Байконур 2012 г
Содержание
Введение
- Принципы и алгоритмы обработки прерываний
- Разработка структуры резидентной программы
- Разработка алгоритма резидентной программы
- Реализация резидентной программы на языке Ассемблер
- Тестирование и отладка резидентной программы
Заключение
Список используемой литературы
Приложение А
Приложение Б
Приложение В
Приложение Г
Приложение Д
Введение
В данном курсовом проекте необходимо разработать программу, изменяющую состояние управляющих клавиш: Caps Lock, Scroll Lock и Num Lock. При разработке программы использовалось несколько прерываний. Вход и выход из резидентной части осуществляется нажатием определенной комбинации клавиш. Резидентная программа защищена от повторной загрузки. Изменение состояния управляющих клавиш осуществляется в резидентной программе.
В первом разделе рассматриваются общие принципы и алгоритмы обработки прерываний.
Во втором разделе разрабатывается структура резидентной программы.
В третьем разделе разрабатывается алгоритм работы резидентной программы.
В четвертом разделе реализуется резидентная программа, написанная на языке Ассемблер.
В пятом разделе приводится методы тестирования и отладки резидентной программы.
- Принципы и алгоритмы обработки прерываний
Прерывания некий процесс, который возникает в системе, временно переключающий микропроцессор на выполнение другой программы с последующим возобновлением выполнения прерванной.
Прерывания делятся на внешние и внутренние. К внутренним относятся программные и от схем контроля. Программные вызываются командой int и используются для передачи управления из прикладных программ в операционную систему. Прерывания от схем контроля возникают в случаях, когда невозможна корректная работа процессора (прерывания по резервной инструкции, прерывания по нарушению защиты памяти или вида доступа к памяти). Внешние прерывания возникают по требованию внешних устройств, когда им необходимо обслуживание.
К аппаратным прерываниям относятся:
- Выводы микропроцессора:
intr вывод для входящего сигнала внешнего прерывания;
inta вывод микропроцессора для выходного сигнала, подтверждение в получении сигнала прерывания микропроцессором;
nmi вывод микропроцессора для входного сигнала, не маскируемого прерывания;
- микросхема программируемого контроллера;
- внешние устройства;
К программным средствам относятся:
- таблица векторов прерываний, в этой таблице содержатся указатели на процедуры обработки соответствующих прерываний
- флаги в регистре флагов
IF (Interrupt Flag) флаг прерывания. Предназначен для маскирования (запрещения) аппаратных прерываний, то есть прерываний по входу INTR. Если IF=1, микропроцессор обрабатывает внешний прерывания, если IF=0, микропроцессор игнорирует сигналы на входе INTR.
TF (Trace Flag) флаг трассировки. Единичное состояние флага переводит микропроцессор в режим покомандной обработки.
- машинные команды микропроцессора (int, into, iret, cli, sli)
Обработка прерываний (как внешних, гак и внутренних) в реальном режиме микропроцессора производится в три этапа:
- Прекращение выполнения текущей программы.
- Переход к выполнению и выполнение программы обработки прерываний.
- Возврат управления прерванной программе.
Первый этап должен обеспечить временное прекращение выполнения текущей программы таким образом, чтобы потом прерванная программа продолжила свою работу так, как будто никакого прерывания не было. Любая программа, загруженная для выполнения операционной системой, занимает свое, отдельное от других программ, место в оперативной памяти. Разделяемыми между программами ресурсами являются регистры микропроцессора, в том числе регистр флагов, поэтому их содержимое нужно сохранять. Обязательными для сохранения являются регистры cs, ip и flags\eflags, поэтому они, при возникновение прерывания, сохраняются микропроцессором автоматически. Пара cs:ip содержит адрес команды, с которой необходимо начать выполнение после возврата из программы обслуживания прерывания, a flags\eflags - состояние флагов после выполнения последней команды прерванной программы в момент передачи управления программе обработки прерывания. Сохранение содержимого остальных регистров должно обеспечиваться программистом в начале программы обработки прерывания до их использования. Наиболее удобным местом хранения регистров является стек. В конце первого этапа микропроцессор после включения в стек регистров Hags, cs и ip сбрасывает бит флага прерываний IF в регистре flags (но при этом в стек записывается предыдущее содержимое регистра flags с еще установленным IF). Тем самым предотвращаются возможность возникновения вложенных прерываний по входу INTR и порча регистров исходной программы вследствие неконтролируемых действий со стороны программы обработки вложенного прерывания. После того как необходимые действия по сохранению контекста завершены, обработчик аппаратного прерывания может разрешить вложенные прерывания командой sti.
Набор действий по реализации второго этапа заключается в определении источника прерывания и вызова соответствующей программы обработки. В реальном режиме микропроцессора допускается от 0 до 255 источников прерываний. Количество источников прерываний ограничено размером таблицы векторов прерываний. Эта таблица выступает связующим звеном между источником прерывания и процедурной обработки. Данная таблица располагается в памяти, начиная с адреса 0. Каждый элемент таблицы векторов прерываний занимает 4 байта и имеет следующую структуру: 1-е слово элемента таблицы значение смещения начала процедуры обработки прерывания (п) от начала кодового сегмента; 2-е слово элемента таблицы значение базового адреса сегмента, в котором находится процедура обработки прерывания.
Рассмотрим, для примера, работу обработчика аппаратного прерывания 09Н - прерывание клавиатуры.
Программа обработки прерывания от клавиатуры работает с контроллером клавиатуры, в функции которого входят распознавание нажатой клавиши и запись закрепленного за ней скэн-кода в свой регистр выхода. Программа обработки читает скэн-код нажатой клавиши из порта 60h и проводит его значения. Если это не клавиша управления, то прерывание 09h по таблице трансляции скэн-кода и кодов ASCII формирует двухбайтовый код, при этом скэн-код - в старшем, a ASCII - в младшем. При этом ASCII-код определяет закрепленный символ. Так как за каждой клавишей закреплено не менее двух символов, то каждому скэн-коду соответствует не менее двух ASCII-кодов. Для более точного определения требуется анализ прерыванием INT 09h состояния флагов, установленных ранее па основании информации из контроллера клавиатуры. Прерывание INT 09h, сформировав двухбайтовый код, помещает его в кольцевой буфер клавиатуры по адресу, находящемуся в хвостовом указателе этого буфера.
- Разработка структуры резидентной программы
При разработке резидентной программы необходимо решить несколько связанных инженерных задач.
Резидентная программа обычно состоит из двух связанных частей - нерезидентной части и резидентной части.
Нерезидентная часть получает управление при запуске программы, при необходимости анализирует параметры запуска и настраивает резидентную часть на конкретные условия работы, выполняет перехват и настройку необходимых векторов прерываний, и обычно с помощью системной функции 31h прерывания 21h оставляет резидентную часть в памяти, возвращая управление операционной системе.
Резидентная часть отвечает за реализацию полезного функционала резидентной программы. Для разрабатываемой программы это управление индикаторами клавиатуры Num Lock, Caps Lock, Scroll Lock. Поскольку управление индикаторами в соответствии с заданием требуется делать с клавиатуры ПК, то резидентная часть должна содержать обработчик прерывания клавиатуры 09h.
В соответствии с заданием требуется реализовать защиту от повторной загрузки резидентной программы. Это можно реализовать с помощью использование специального прерывания - 2Fh - называемого также мультиплексным, специально предназначенного для организации взаимодействия с резидентными программами. Проверка нахождения в памяти резидентной части осуществляется по схеме "запрос-отклик": нерезидентная часть заполняет регистр AX (в регистр AH помещается номер функции, причем номера 00h-0BFh зарезервированы для MS DOS, а номера 0C0h-0FFh предоставляются для прикладных программ; в регистр AL помещается номер подфункции) и вызывает прерывание 2Fh. Если резидентная часть уже установлена и ее повторная установка не требуется, необходимо вернуть в регистре AL сигнальное значение 0FFh. Таким образом, резидентная часть должна в своем составе иметь также обработчик прерывания 2Fh, а нерезидентная часть должна для проверки наличия резидентной программы в памяти вызывать это прерывание и анализировать результат.
Кроме этого, для реализации требования о включении и выключении резидентной программы, наиболее целесообразным является введение в области данных резидентной части программы специального байт-маркера "активности" резидентной части. При "неактивном" состоянии программы она не оказывает никакого влияния на работу компьютера, а при "активном" состоянии выполняет заданный функционал.
Поскольку резидентная программа должна занимать минимум памяти, выбрано решение, при котором программа компилируется в COM файл.
Общая структура программы приведена на рисунке.
- Разработка алгоритма резидентной программы
В приложении А представлена блок-схема работы инициализирующей части программы. В приложении Б блок-схема работы прерывания 2FH. В приложении В блок-схема работы прерывания 09H.
При запуске программы управление передается нерезидентной части программы. Нерезидентная часть выполняет инициализацию программы следующим образом:
1. Проверяет, не установлена ли уже резидентная программа, помещая в регистр AX "магическое значение" 0CDBAh (функция 0CDh, подфункция 0BAh), выполняя программное прерывание 2Fh и проверяя возврат - если программа уже установлена, в регистре AL при возврате из прерывания должно оказаться сигнальное значение 0FFh;
2. Если программа уже установлена, то производится вывод сообщения "Программа уже установлена!" и немедленное завершение программы без оставления резидентной части в памяти;
3. Если программа еще не установлена (значение в регистре AL отличается от 0FFh), производится перехват используемых векторов прерываний 09h и 2Fh с сохранением "старых" значений этих векторов в области данных резидентной части программы;
4. Производится вывод сообщения об успешной установке резидентной части и резидентное завершение программы вызовом функции 31h системного прерывания 21h. Для того, чтобы резидентная часть программы занимала в памяти как можно меньше места, производится вычисление минимального необходимого объема памяти, занимаемого только резидентной частью. Память, занимаемая нерезидентной частью (инициализирующий код), для работы резидентной части не нужна и возвращается системе.
Резидентная часть программы получает управление посредством программных или аппаратных прерываний. Используются два прерывания - 09h и 2Fh.
Обработчик мультиплексного прерывания 2Fh резидентной части программы выполняет следующие действия:
1. Проверяет значение в регистре AX на соответствие значению 0CDBAh. Если значение совпало, это свидетельствует о том, что выполнен еще один запуск программы, и инициализирующая часть проверяет, не установлена ли уже резидентная программа. В этом случае следует в регистр AL записать сигнальное значение 0FFh и немедленно завершить обработку прерывания и вернуть управление вызывающей программе. В противном случае, следует передать управление дальше "по цепочке", используя сохраненный обработчик этого прерывания.
Обработчик прерывания 09h (клавиатуры) получает управление при каждом нажатии клавиши на клавиатуре. Особенностью этого обработчика является то, что он получает управление дважды: первый раз при нажатии клавиши, второй раз - при отпускании клавиши. Для правильной обработки нажатий клавиш в программе организован специальный байт-маркер - "флажок", который "взводится" при нажатии клавиши и "сбрасывается" при отпускании клавиши. Состояние этого флажка позволяет различить нажатия и отпускания клавиш. Обработчик прерывания 09h выполняет следующие действия:
1. Проверяет состояние "активности" резидентной части. Если резидентная часть не активна (выключена), управление передается сохраненному обработчику прерывания 09h для "обычной" обработки нажатий клавиатуры.
2. Если резидентная часть "активна", производится проверка - нажата клавиша или отпущена. Если клавиша нажата, производится сдвиг горящей лампочки клавиатуры на 1 (по кольцу) и установка состояния лампочек. Сдвиг лампочки и установка состояния лампочек организованы как отдельные подпрограммы (процедуры).
3. Затем управление передается сохраненному обработчику прерывания 09h клавиатуры - это позволяет всем прикладным программам нормально получать и обрабатывать нажатия клавиш. Вызов прерывания эмулируется последовательностью инструкций pushf и call.
4. В конце обработчика анализируется факт одновременного нажатия "горячих клавиш" Left Ctrl + Left Shift и включается или отключается "активность" резидентной части программы. При неактивной (выключенной) резидентной части она не оказывает влияния на работу компьютера.
- Реализация резидентной программы на языке Ассемблер
Проверка активности резидента, нажатия клавиши:
mov AL, active
or AL, AL
jz inactive_continue
mov AL, pressed
or AL, AL
jz short key_down
mov pressed, 0
jmp short inactive_continue
Если клавиша нажата:
key_down:
call shift_light
call set_light
mov pressed, 1
Сдвиг и установка лампочки:
shift_light proc near
mov AL, light
shr AL, 1
and AL, 70h
jnz not_shifted
mov AL, 40h
not_shifted:
mov light, AL
ret
shift_light endp
set_light proc near
xor AX, AX
mov ES, AX
mov AL, ES:[0417h]
and AL, 8Fh
or AL, light
mov ES:[0417h], AL
ret
set_light endp
Чтение состояния клавиатуры и проверка нажатия “горячих клавиш”, приостанавливающих резидента:
mov AL, byte ptr ES:[0417h]
and AL, 6h
cmp AL, 6h
jne notPressed
mov AL, active
xor AL, 1
mov active, AL
- Тестирование и отладка резидентной программы
В приложении Д приведён скриншот результата выполнения программы. Из приведённого скриншота видно, что программа сообщает о своём запуске, опознаёт и сообщает, что программа уже загружена резидентно и переключает состояние клавиш Caps Lock, Num Lock и Scroll Lock при нажатии на клавишу.
Заключение
В данном курсовом проекте была разработана программа, изменяющая состояние управляющих клавиш: Caps Lock, Scroll Lock и Num Lock. Программа может использовать клавиатуру по-разному. Она может задержать своё выполнение, до тех пор, пока оператор не нажмёт какую-нибудь клавишу.
Список используемой литературы:
1. Финогенов К.Г. Самоучитель по системным функциям MS DOS. - М.: Радио и связь, Энтроп, 1995. - 382 с., ил.
2. Зубков С.В. Assembler. Язык неограниченных возможностей. - М.: ДМК Пресс, 1999. - 608 с., ил.
3. Пирогов В.Ю. Assembler. Учебный курс. - М.: Издатель Молгачева С.В., Издательство Нолидж, 2001. - 848 с., ил.
Приложение А
(обязательное)
Приложение Б
(обязательное)
Приложение В
(обязательное)
Приложение Г
(обязательное)
model tiny
code segment ; определение кодового сегмента
assume CS:code, DS:code ; CS и DS указывают на сегмент кода
org 100h
; резидентная часть программы
start:
jmp init ; переход на секцию инициализации
; данные резидентной части программы:
old2F dd ? ; сохраненный обработчик 2Fh
old09 dd ? ; сохраненный обработчик 09h
active db 0 ; флаг активности резидента
; int 09h получает управление дважды: при нажатии и при отжатии клавиши. Чтобы срабатывало при нажании,
; используется флаг:
pressed db 0 ; клавиша нажата/отпущена (0 - нажата, 1 - отпущена)
; лампочки контролируются битами 4,5,6 байта [0040h:0017h]
; бит 5 (00100000b) - NumLock
; бит 6 (01000000b) - CapsLock
; бит 4 (00010000b) - SrollLock
light db 20h ; маска лампочек (00100000b) - NumLock On
; обработчик прерывания клавиатуры 09h
int09Handler:
push ES
push AX
mov AL, active ; проверяем активность нашего резидента
or AL, AL
jz inactive_continue ; неактивен? ничего не делаем
mov AL, pressed ; нажата клавиша или отпущена?
or AL, AL
jz short key_down ; если нажата - переход
mov pressed, 0 ; отпущена - сбросить флажок
jmp short inactive_continue
key_down: ; при нажатии клавиши:
call shift_light ; сдвинуть лампочку
call set_light ; и установить ее
mov pressed, 1 ; и поставить флажок нажатия
inactive_continue:
pushf
call dword ptr CS:old09 ; перейти на сохраненный обработчик
xor AX, AX
mov ES, AX
mov AL, byte ptr ES:[0417h]
and AL, 6h ; проверяем одновременное нажатие клавиш (вкл/выкл резидента)
cmp AL, 6h ; 110b - биты 1 и 2 - Ctrl + Left Shift
jne notPressed
mov AL, active
xor AL, 1 ; переключаем состояние резидента (активен/неактивен)
mov active, AL
Приложение Г
(продолжение)
notPressed:
pop AX
pop ES
iret
; обработчик мультиплексного прерывания 2Fh
int2FHandler:
cmp AX, 0CDBAh ; сравнить с магическим значением
jne nextRetry
mov AL, 0FFh ; совпадает - занести в AL сигнал 0FFh
iret ; и сразу возврат из прерывания
nextRetry:
jmp CS:old2F ; перейти на сохраненный обработчик
; процедура сдвига горящей лампочки на 1
; код лампочки в light
shift_light proc near
mov AL, light
shr AL, 1 ; shift to right
and AL, 70h ; выделяем биты лампочек - 01110000b
jnz not_shifted ; если какая-то лампочка горит - переход
mov AL, 40h ; иначе установить 01000000bCapsLock On
not_shifted:
mov light, AL
ret
shift_light endp
; процедура установки горящей лампочки
; код лампочки хранится в light
set_light proc near
xor AX, AX
mov ES, AX
mov AL, ES:[0417h]
and AL, 8Fh ; очищаем биты лампочек, сохраняем остальные биты
or AL, light ; ставим маску горящих лампочек
mov ES:[0417h], AL
ret
set_light endp
end_resident: ; метка для определения размера резидентной части программы
; ================================================================================
; транзитная часть программы
init:
; 1. проверка установленной программы
mov AX, 0CDBAh ; магическое значение
int 2Fh ; вызов мультиплексного прерывания
cmp AL, 0FFh
je installed ; уже установлена - на выход
; 2. установка программы:
; перехват вектора 09h
mov AX, 3509h ; получение адреса старого обработчика
Приложение Г
(обязательное)
int 21h
mov word ptr old09, BX ; сохранение смещения обработчика
mov word ptr old09 + 2, ES ; сохранение сегмента обработчика
mov AX, 2509h ; установка адреса нашего обработчика
mov DX, offset int09Handler ; указание смещения нашего обработчика
int 21h
; перехват вектора 2Fh
mov AX, 352Fh ; получение адреса старого обработчика
int 21h
mov word ptr old2F, BX ; сохранение смещения обработчика
mov word ptr old2F + 2, ES ; сохранение сегмента обработчика
mov AX, 252Fh ; установка адреса нашего обработчика
mov DX, offset int2FHandler ; указание смещения нашего обработчика
int 21h
; включить лампочку NumLock
call set_light
mov AH, 09h ; вывод на экран успешного сообщения
mov DX, offset DoneResident
int 21h
; установка резидентом
mov AX, 3100h ; функция DOS завершения резидентной программы
mov DX, (end_resident - start + 10Fh) / 16 ; определение размера резидентной части программы в параграфах
int 21h
installed:
mov AH, 09h ; вывод на экран ругательного сообщения
mov DX, offset JustInstalledMsg
int 21h
mov AX, 4C01h ; завершить нерезидентно
int 21h
JustInstalledMsg db 'Programma uzhe ustanovlena!', 13, 10, '$'
DoneResident db 'Programma ostalas rezidentno.', 13, 10, '$'
code ends ; конец кодового сегмента
end start ; конец программы
Приложение Д
(обязательное)
Обработка программных и аппаратных прерываний в IBM PC совместимых компьютерах с помощью резидентных программ