
- •1. Рп с вызовом через вектор прерывания Int 60h.................4
- •Резидентные программы
- •1. Установка резидентной программы
- •2. Резидентный обработчик прерываний от клавиатуры с подключением до системного обработчика.
- •3. Резидентный обработчик прерываний от клавиатуры
- •4. Резидентная программа
- •5. Выгрузка рп с помощью ее вызова
- •6. Общая программа загрузки и выгрузки рп
- •7. Обработка опций
- •8. Создание диалоговой среды
- •9. Загрузка рп в верхнюю память
- •10. Действия,выполняемые рп
- •Задание на курсовую работу
2. Резидентный обработчик прерываний от клавиатуры с подключением до системного обработчика.
Чаще всего резидентная программа запускается по заданной клавише. То есть с помощью прерывания от клавиатуры IRQ1 с вектором 09. Однако, в этом случае надо, чтобы кроме нашей программы, выполнялось и стандартное прерывание обработки кодов клавиатуры. Это наиболее сложный способ. Здесь надо сначала получить адрес старого вектора прерывания с помощью:
Int 21,35 - получить адрес вектора прерывания
AL - номер прерывания
Результат:
ES:BX - адрес прерывающей программы
и запомнить адрес старого вектора прерывания в виде переменной, находящейся в резидентной части программы. Нельзя запоминать его в регистрах или в стеке, так как программа будет вызываться многократно.
После этого выполнить нашу резидентную программу можнотремя способами:
- выполнить собственный обработчик прерывания до системного;
- выполнить собственный обработчик прерывания после системного;
- выполнить часть обработчика прерывания до и часть после системного.
Рассмотрим сначала первый способ:
В этом случае, сразу после вызова нужно выполнить собственный обработчик прерывания. Затем передать управление по старому адресу перехваченного прерывания для обработки кода нажатой клавиши, тем самым заодно обеспечив и выход в DOS из резидентной программы.
Пример 2
Создадим резидентную программу с вызовом по клавише со скан-кодом 29h (обр.апостроф).
При вызове программа выводит цветной символ в последнюю
позицию экрана и меняет цвет символа при каждом новом вызове.
Seg1 SEGMENT
ASSUME SS:Seg1,DS:Seg1,CS:Seg1,ES:Seg1
ORG 100h ;Начало программы с 0100h
Pr: JMP M1 ;Пропускаем резидентную часть
;--------------------- Резидентная часть
old_09 dd 0 ;Старый адрес Int 09h
sym1 dw 421Eh ;1-й выводимый символ
sym2 dw 241Eh ;2-й выводимый символ
;---------------------
M2: push AX ;Сохраним те регистры, содержимое
push ES ;которых меняется в программе
in AL,60h ;Ввод кода нажатой кл.из рег.60h
cmp AL,29h ;Анализ кода нажатой кл.
jnz M3 ;Переход, если скан-код не 29h
mov AX,0B800h ;В рег.ES засылаем cегментный
mov ES,AX ;адрес буфера экрана B800
mov AX,CS:sym1 ;¬
xchg AX,CS:sym2 ;¦Oбмен местами sym1 - sym2
mov CS:sym1,AX ;-
mov ES:3998,AX ;Вывод в посл.поз.экрана 3998
M3: pop ES ;Восстановим содержимое
pop AX ;регистров ES и AX
jmp CS:old_09 ;передать управление на системный
; обработчик прерываний
M1: ;---------------------- ;Инициирующая часть
mov AX,3509h ;Получить старый адрес в ES:BX
INT 21h ;обработчика прерывания int 09h
mov word ptr CS:old_09,BX ;и запомнить ES:BX
mov word ptr CS:old_09+2,ES ;в ячейке old_09
mov AX,2509h ;Установка нового адреса <адр.M2>
lea DX,M2 ;обработчика прерывания int 09h
INT 21h ; -------
mov AH,09h ;Вывод строки:
lea DX,x ;'Резидентный обработчик загружен$'
INT 21h ; -------
mov AX,3100h ;Завершить и оставить pезидентной
mov DX,(M1-Pr+10Fh)/16 ;часть размером (M1-Pr+10Fh)/16
INT 21h ; -------
x db 'Резидентный обработчик загружен$'
Seg1 ENDS ;Конец сегмента
END Pr ;Полный конец программы Pr
Здесь полученный старый адрес обработчика прерывания int 09h запоминается двумя командами вида 'mov word ptr CS:old_09,BX'.
Поскольку переменная 'old_09' типа 'dd'(двойное слово), потребовалось переопределять тип переменной.
Резидентная часть здесь всегда заканчивается переходом на системный обработчик прерывания 09h (команда 'jmp CS:old_09'). Это приводит к тому, что по клавише со скан-кодом 29h(обр.апостроф) программа выводит не только цветной символ в последнюю позицию экрана, но и нормальный символ клавиши. Чтобы этого не происходило, следует по выбранному коду клавиши заканчивать прерывание 09h самостоятельно.
Для этого необходимо:
- в 7 р. регистра 'B' контроллера клавиатуры (адр. 61h) заслать сначала 1, затем 0. Этим мы указываем контроллеру, что обработка кода клавиши закончена;
- в 5 р. регистра контроллера прерываний (адр.20h) заслать единицу, указав тем самым, что обработка прерывания закончена;
- самостоятельно закончить резидентную программу командой IRET.
Такая программа от предыдущей будет отличаться только окончанием резидентной части:
;--------------------- Резидентная часть
old_09 dd 0 ;Старый адрес Int 09h
sym1 dw 421Eh ;1-й выводимый символ
sym2 dw 241Eh ;2-й выводимый символ
;---------------------
M2: push AX ;Сохраним те регистры, содержимое
push ES ;которых меняется в программе
in AL,60h ;Ввод кода нажатой кл.из рег.60h
cmp AL,29h ;Анализ кода нажатой кл.
jz M3 ;Переход, если скан-код = 29h
pop ES ;Восстановим содержимое
pop AX ;регистров ES и AX
jmp CS:old_09
M3: mov AX,0B800h ;В рег.ES засылаем сегментный
mov ES,AX ;адрес буфера экрана B800
mov AX,CS:sym1 ;¬
xchg AX,CS:sym2 ;¦Oбмен местами sym1 - sym2
mov CS:sym1,AX ;-
mov ES:3998,AX ;Вывод в посл.поз.экрана 3998
in AL,61h ;
or AL,80h ;В регистр по адр. 61h
out 61h,AL ;засылаем 1 в 7-й разряд
and AL,7Fh ;В регистр по адр. 61h
out 61h,AL ;засылаем 0 в 7-й разряд
mov AL,20h ;В регистр по адр. 20h
out 20h,AL ;засылаем 1 в 5-й разряд
pop ES ;Восстановим содержимое
pop AX ;регистров ES и AX
iret ;Выход в DOS
Для занесения 1 или 0 в один из разрядов рег. 61h, мы должны сохранить информацию в остальных разрядах этого регистра. Для этого содержимое регистра сначала читается командой 'in AL,61h', затем изменяется содержимое рег. AL и записывается в рег.61h. В регистр по адр. 20h просто заносится число 20h без сохранения предыдущего кода.
Почему выход в DOS осуществляется командой IRET, а не RET уже объяснялось ранее.