#include <dos.h>
#include <stdio.h>
#include <stdlib.h>

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

#pragma check_stack( off )
#pragma check_pointer( off )

// Макро для подачи звукового сигнала

#define BEEP() _asm { \
								_asm xor  bx, bx    \
								_asm mov  ax, 0E07h \
								_asm int  10h       \
						  }

// Указатель на старую функцию обработки
//   9-го прерывания

void (_interrupt _far *oldkey)( void );

// Объявление новой функции обработки
//   9-го прерывания

void _interrupt _far newkey( void );

void main(void);

void main(void) {

	 unsigned size; // Размер резидентной части
						 // TSR-программы

	 char _far *newstack; // Указатель на новый стек,
								 // который будет использовать
								 // TSR-программа

	 char _far *tsrbottm; // Указатель на конец
								 // TSR-программы, используется
								 // для определения размера
								 // резидентной части

	 // Записываем адрес стека TSR-программы

	 _asm mov  WORD PTR newstack[0], sp
	 _asm mov  WORD PTR newstack[2], ss

	 FP_SEG(tsrbottm) = _psp; // Указатель конца
	 FP_OFF(tsrbottm) = 0;    // программы устанавливаем
									  // на начало PSP

	 // Вычисляем размер программы в параграфах
	 // Добавляем 1 параграф на случай
	 // некратной параграфу длины

	 size = ((newstack - tsrbottm) >> 4) + 1;

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

	 oldkey = _dos_getvect(0x9);
	 _dos_setvect(0x9, newkey);

	 // Завершаем программу и остаемся в памяти

	 _dos_keep(0, size);
}


// Новый обработчик клавиатурного прерывания

void _interrupt _far newkey() {

	BEEP(); // Выдаем звуковой сигнал

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

	_chain_intr( oldkey );

}

