.Model Small .Data old_kbd dd ? str db 'Laboratornaja rabota #2' str_len=$-Str ;флаг нажатой клавиши ESC .stack 256 .Code bflag db 0 main proc ;главная процедура mov ax, @data mov ds, ax ;настройка сегмента данных CLI ;запрещаем все прерывания ;Перепрограммироуем ведущий ПКП mov cl, 088h ;процедура выполнения повторной инициализации call reinit ;ведущего ПКП с базовым вектором 088h ;Сохраним старый вектор mov ax, 3589h int 21h mov word ptr old_kbd, bx ;сохраняем старый mov word ptr old_kbd+2, es ;базовый адрес ;«Запишим в таблицу адресс нашего обработчика прерывания mov ax, 2589h mov dx, offset new_kbd push ds push cs pop ds ;ds=cs настроили ds на начало сегмента кода int 21h pop ds ;вернем старое значение ;Запрет на уровне регистра маски всех прерываний кроме от клавиатуры mov al, 11111101b out 21h, al STI ;Цикл ожидания нажатия клавиши ESC m1: mov al, cs:bflag or al, al jz m1 ;востанавливаем старый вектор CLI mov ax, 2589h push ds lds dx, old_kbd int 21h pop ds ;Перепрограммируем ПКП в режиме по-умолчанию mov cl,08h call reinit mov al, 10111000b out 21h, al STI ;Завершаем процедуру и передаем управление MS DOS mov ax, 4c00h int 21h main endp ;Текст нового обработчика прерывания от клавиатуры new_kbd proc far push ax push ds push es push di push si push dx push cx in al, 60h ;считываем из выходного порта контроллера cmp al, 01h ;клавиатуры скан-код клавиши ESC jne m2 mov cs:bflag, al m2: ;Прямым отображением в видеобуфер выводим строку STR mov ax, 0b800h mov es, ax mov di, 0000h mov cx, str_len mov si, 0h ;Цикл вывода строки на экран m3: mov al, str[si] inc si mov es:[di], al inc di inc di loop m3 mov al, 20h out 20h, al pop cx pop dx pop si pop di pop es pop ds pop ax iret new_kbd endp ;Процедура инициализации ведущего ПКП ;Базовый адрес в процедуру передается через CL reinit proc mov al, 00010001b ;ICW1 out 20h, al mov al, cl out 21h, al mov al, 00000100b ;ICW3 out 21h, al mov al, 00001101b ;ICW4 out 21h, al ret reinit endp end main