Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПО / Лекции / КурсЛекций.doc
Скачиваний:
94
Добавлен:
23.02.2015
Размер:
8.22 Mб
Скачать

6.3. Обработчики прерываний

Для установки своего обработчика прерываний используйте функцию _dos_setvec. Эта функция имеет два параметра - номер прерывания и указатель на новую функцию обработки прерывания. Например:

_dos_setvect(0x16, my_key_intr);

В этом примере для клавиатурного прерывания с номером 16h устанавливается новый обработчик прерывания my_key_intr.

Если вам надо узнать адрес старого обработчика прерывания по его номеру, лучше всего воспользоваться функцией _dos_getvect, которая принимает в качесте параметра номер прерывания и возвращает указатель на соответствующий этому номеру в таблице векторов прерываний обработчик. Например:

old_vector = _dos_getvect(0x16);

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

Следующий простой пример иллюстрирует применение всех трех функций, предназначенных для работы с прерываниями. Эта программа встраивает собственный обработчик прерывания таймера, который будет вызываться примерно 18,2 раза в секунду. Встраиваемый обработчик прерывания считает тики таймера и, если значение счетчика кратно 20, на динамик компьютера выдается звуковой сигнал. В конце работы новая программа обработки прерывания таймера вызывает старый обработчик с помощью функции _chain_intr.

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

 

#include <dos.h>

#include <stdio.h>

#include <stdlib.h>

// Выключаем проверку стека и указателей

#pragma check_stack( off )

#pragma check_pointer( off )

// Это макро используется для выдачи

// сигнала на внутренний динамик

// компьютера. Используется вывод

// в формате TTY символа BELL (7)

// через прерывание BIOS 10h

#define BEEP() _asm { \

_asm mov bx,0 \

_asm mov ax, 0E07h \

_asm int 10h \

}

void main(void);

// Объявление программы обработки прерывания

void _interrupt _far timer(void);

// Эта переменная предназначена для хранения

// старого значения вектора прерывания

// таймера. Она должна быть глобальной.

void (_interrupt _far *oldvect)(void);

// Переменная для подсчета тиков таймера

volatile long ticks;

void main(void) {

ticks=0L; // Сбрасываем счетчик тиков таймера

oldvect = _dos_getvect(0x1c); // Запоминаем адрес

// старого обработчика

// прерывания

_dos_setvect(0x1c, timer); // Устанавливаем свой

// обработчик

printf("\nТаймер установлен. Нажмите любую"

"клавишу...\n");

getch(); // Ожидаем нажатия на любую клавишу

_dos_setvect(0x1c,oldvect); // Восстанавливаем старый

// обработчик прерывания

// таймера

exit(0);

}

// Функция обрабатывает прерывания таймера

void _interrupt _far timer(void) {

ticks++; // Увеличиваем счетчик тиков таймера

// Если значение счетчика тиков кратно 20,

// выдаем сигнал на динамик компьютера

if((ticks % 20) == 0) BEEP();

// Вызываем старый обработчик прерывания

_chain_intr(oldvect);

}