Читайте также:
|
|
Листинг программы:
#include <stdio.h>
#include <dos.h>
#define TAIL_PTR 0x1c
#define HEAD_PTR 0x1a
#define SOST_KLAV 0x18
void interrupt (*old_int09)(); /* Для стандартного обработчика
прерывания 9 (нажатие/отпускание клавиши) */
void interrupt (*old_int1c)(); /* Для стандартного обработчика
прерывания 0x1c (от таймера) */
union REGS rg;
int active,i; char c;
int n1,n2,n3,j,zflag;
unsigned key_codes[]={0x1265,0x266c,0x1f73,0x1265};
/* В массиве key_codes[] слово "else" в виде скэн-ASCII-кодов.
Но, если вместо скэн-составляющих здесь указать просто 4 нулей
или 4 любых скэн-кодов, то ничего от этого не изменится. */
void interrupt new_int1c()
{ /* Новый обработчик прерывания 0x1c - (от таймера) */
if(active)
{ i++; if(i>4) active=0;
else
{ disable();
rg.x.ax=0x0500; /* Номеp вызываемой
функции для пpеpывания 16h pавен ah=05h */
rg.x.cx=key_codes[i]; /* ch - скэн-код, а cl - ASCII-код
символа,записываемого в буфеp клавиатуpы */
int86(0x16,&rg,&rg); /* тепеpь в al будет 0 если и только
если запись в буфеp удалась, т.е. он не пеpеполнен */
enable(); }
}
(*old_int1c)(); /* Передадим управление старому
обработчику прерывания 0x1c */
}
void interrupt new_int09()
{ /* Новый обработчик прерывания 0x09 -
(нажатие/отпускание любой клавиши) */
register unsigned _es *t1, _ec *t2, _ec *t3;
disable();
t1=SOST_KLAV&0x40;
t2=TAIL_PTR&0x40;
t3=HEAD_PTR&0x40;
n2=*t2; n3=*t3; n1=*t1;
printf("n1 = %x",n1&0x10);
if(((n1&0x10)==0x38)&&(!active)&&(n2==n3))
/* Если прижата Alt и active==0 и буфер клавиатуры пуст*/
{ i=-1; active=1;j=0;
for(j=0;j<3;j++)
printf("%c",key_codes[j]); (*old_int09)();}
else
(*old_int09)();
/* Передадим управление старому обработчику прерывания 0x09 */
enable();
}
void main(void)
{ /* Прототипы вызываемых отсюда ф-ий - в dos.h */
active=0; disable(); /* Запретить прерывания */
old_int09=getvect(0x09); /* Запомнит старый вектор 9-го
прер-ия (нажатие или отпускание клавиши) */
setvect(0x09,new_int09); /* Занести на место этого вектора
новый - адрес нашего обработчика */
old_int1c=getvect(0x1c); /* Запомнит старый вектор
прер-ия 0x1c (от таймера) */
setvect(0x1c,new_int1c); /* Занести на место вектора 0x1c
прер-ния от таймера - адрес нашего обработчика этого прер-ния */
enable(); /* Разрешить прерывания */
keep(0,750); /* Примерно разделили на 8 размер EXE-файла этой
программы и получили 750 */
}
Пояснительная записка к программе 3.
Составление собственных программ обработки прерываний и замена стандартных обработчиков MS-DOS и BIOS является достаточно сложной задачей. Необходимо учитывать все тонкости работы аппаратуры, а также взаимодействия программного и аппаратного обеспечения. При отладке возможно разрушение операционной системы с непредсказуемыми последствиями, поэтому надо очень внимательно следить за тем, что делает ваша программа.
Таблица векторов прерываний
Для того чтобы связать адрес обработчика прерывания с номером прерывания, используется таблица векторов прерываний, занимающая первый килобайт оперативной памяти. Эта таблица находится в диапазоне адресов от 0000:0000 до 0000:03FFh и состоит из 256 элементов - дальних адресов обработчиков прерываний.
Элементы таблицы векторов прерываний называются векторами прерываний. В первом слове элемента таблицы записана компонента смещения, а во втором - сегментная компонента адреса обработчика прерывания.
Вектор прерывания с номером 0 находится по адресу 0000:0000, с номером 1 - по адресу 0000:0004 и т. д.
Для программиста, использующего язык С, таблицу векторов прерываний можно описать следующим образом:
void (far* interrupt_table[256])();Инициализация таблицы выполняется частично системой базового ввода/вывода BIOS после тестирования аппаратуры и перед началом загрузки операционной системой, частично при загрузке MS-DOS. Операционная система MS-DOS может изменить некоторые вектора прерываний, установленные BIOS.
Расскажем о назначении наиболее важных векторов прерываний.
Номер | Описание |
Ошибка деления.Вызывается автоматически после выполнения команд DIV или IDIV, если в результате деления происходит переполнение (например, при делении на 0). Обычно при обработке этого прерывания MS-DOS выводит сообщение об ошибке и останавливает выполнение программы. При этом для процессора i8086 адрес возврата указывает на команду, следующую после команды деления, а для процессора i80286 и более старших моделей - на первый байт команды, вызвавшей прерывание | |
Прерывание пошагового режима.Вырабатывается после выполнения каждой машинной команды, если в слове флагов установлен бит пошаговой трассировки TF. Используется для отладки программ. Это прерывание не вырабатывается после пересылки данных в сегментные регистры командами MOV и POP | |
Аппаратное немаскируемое прерывание.Это прерывание может использоваться по-разному в разных машинах. Обычно оно вырабатывается при ошибке четности в оперативной памяти и при запросе прерывания от сопроцессора | |
Прерывание для трассировки. Генерируется при выполнении однобайтовой машинной команды с кодом CCh и обычно используется отладчиками для установки точки прерывания | |
Переполнение. Генерируется машинной командой INTO, если установлен флаг переполнения OF. Если флаг не установлен, команда INTO выполняется как NOP. Это прерывание используется для обработки ошибок при выполнении арифметических операций | |
Печать копии экрана. Генерируется, если пользователь нажал клавишу <PrtSc>. В программах MS-DOS обычно используется для печати образа экрана. Для процессора i80286 и более старших моделей генерируется при выполнении машинной команды BOUND, если проверяемое значение вышло за пределы заданного диапазона | |
Неопределенный код операции или длина команды больше 10 байт | |
Особый случай отсутствия арифметического сопроцессора | |
IRQ0 - прерывание интервального таймера, возникает 18,2 раза в секунду | |
IRQ1 - прерывание от клавиатуры. Генерируется, когда пользователь нажимает и отжимает клавиши. Используется для чтения данных из клавиатуры | |
A | IRQ2 - используется для каскадирования аппаратных прерываний |
B | IRQ3 - прерывание асинхронного порта COM2 |
C | IRQ4 - прерывание асинхронного порта COM1 |
D | IRQ5 - прерывание от контроллера жесткого диска (только для компьютеров IBM PC/XT) |
E | IRQ6 - прерывание генерируется контроллером НГМД после завершения операции ввода/вывода |
F | IRQ7 - прерывание от параллельного адаптера. Генерируется, когда подключенный к адаптеру принтер готов к выполнению очередной операции. Обычно не используется |
Обслуживание видеоадаптера | |
Определение конфигурации устройств в системе | |
Определение размера оперативной памяти | |
Обслуживание дисковой системы | |
Работа с асинхронным последовательным адаптером | |
Расширенный сервис | |
Обслуживание клавиатуры | |
Обслуживание принтера | |
Запуск BASIC в ПЗУ, если он есть | |
Перезагрузка операционной системы | |
1A | Обслуживание часов |
1B | Обработчик прерывания, возникающего, если пользователь нажал комбинацию клавиш <Ctrl+Break> |
1C | Программное прерывание, вызывается 18,2 раза в секунду обработчиком аппаратного прерывания таймера |
1D | Адрес видеотаблицы для контроллера видеоадаптера 6845 |
1E | Указатель на таблицу параметров дискеты |
1F | Указатель на графическую таблицу для символов с кодами ASCII 128-255 |
20-5F | Используется MS-DOS или зарезервировано для MS-DOS |
60-67 | Прерывания, зарезервированные для программ пользователя |
68-6F | Не используются |
IRQ8 - прерывание от часов реального времени | |
IRQ9 - прерывание от контроллера EGA | |
IRQ10 - зарезервировано | |
IRQ11 - зарезервировано | |
IRQ12 - зарезервировано | |
IRQ13 - прерывание от арифметического сопроцессора | |
IRQ14 - прерывание от контроллера жесткого диска | |
IRQ15 - зарезервировано | |
78 - 7F | Не используются |
80-85 | Зарезервировано для BASIC |
86-F0 | Используются интерпретатором BASIC |
F1-FF | Не используются |
Прерывания, обозначенные как IRQ0 - IRQ15 являются аппаратными прерываниями.
Что это такое резидентная программа?
Обычно после завершения очередной программы MS-DOS освобождает место в памяти, которое занимала программа, чтобы загрузить на это место новую. Однако есть способ оставить программу в памяти и после ее завершения. Такая программа и будет резидентной, т. е. постоянно присутствующей в памяти.
Для чего используются резидентные программы?
Резидентные программы могут переключать на себя обработку прерываний, например, связанных с выводом на печать или с обращением к клавиатуре и т. д.
Вы можете встретить множество резидентных программ, предназначенных для загрузки русских шрифтов в память видеоконтроллера, для печати текста, содержащего символы кириллицы, на принтере в графическом режиме, для русификации клавиатуры и т. п. Все эти программы обычно запускаются один раз при загрузке компьютера через файл autoexec.bat.
Другой пример использования резидентных программ: резидентные калькуляторы, справочные базы данных или интегрированные системы, наподобие Borland SideKick.
Такие программы тоже обычно запускаются через файл autoexec.bat или при необходимости. Они перехватывают прерывания, предназначенные для работы с клавиатурой. Как только пользователь нажимает заранее определенную комбинацию клавиш, резидентная программа активизируется. Поверх имеющегося на экране изображения выводится диалоговое окно резидентной программы.
Иногда резидентные программы используют вместо загружаемых драйверов для обслуживания нестандартной аппаратуры. В этом случае резидентная программа может встроить свой обработчик, через который все прикладные программы смогут обращаются к аппаратуре.
Дата добавления: 2015-10-16; просмотров: 69 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Задача 2. | | | Инициализация резидентной программы |