- •1. Рп с вызовом через вектор прерывания Int 60h.................4
- •Резидентные программы
- •1. Установка резидентной программы
- •2. Резидентный обработчик прерываний от клавиатуры с подключением до системного обработчика.
- •3. Резидентный обработчик прерываний от клавиатуры
- •4. Резидентная программа
- •5. Выгрузка рп с помощью ее вызова
- •6. Общая программа загрузки и выгрузки рп
- •7. Обработка опций
- •8. Создание диалоговой среды
- •9. Загрузка рп в верхнюю память
- •10. Действия,выполняемые рп
- •Задание на курсовую работу
5. Выгрузка рп с помощью ее вызова
из специальной программы
Чтобы выгрузить резидентную программу, необходимо:
- восстановить прежние значения всех перехваченных векторов прерываний;
- освободить блок памяти занимаемый программой;
- освободить блок памяти занимаемый ее окружением.
Для выполнения функции освобождения блоков памяти служит прерывание:
Int 21,49 - освободить блок памяти
ES - сегментный адрес выгружаемого блока памяти
Размер выгружаемого блока памяти определяется чтением данных из
блока MCB внутри самого прерывания Int 21,49.
Восстановить прежние значения всех перехваченных векторов прерываний
можно только внутри собственной программы, так как никто не знает, где
спрятаны старые значения их адресов.
ЗАМЕЧАНИЕ: Корректно выгрузить можно только последнюю резидентную
программу, перехватившую заданное прерывание. В противном случае, все
позже загруженные резидентные программы, вызываемые тем же прерыванием,
останутся в памяти но вызываться не будут.
Для управления процессом выгрузки опять воспользуемся мультиплексным
прерыванием INT 2Fh.
Обработчик прерывания INT 2Fh резидентной программы должен:
- приняв прерывание, проверить номер функции в регистре AH и, если
номер не свой, передать управление ранее загруженной резидентной
программе, также использующей прерывание INT 2Fh
JMP CS:old_2f
здесь 'old_2f' - ячейка памяти, где хранится старый адрес вектора
прерывания INT 2Fh.
- если номер функции свой, проверить номер подфункции в регистре AL
и, выполнив необходимые действия (в нашем случае это выгрузка
резидентной программы из памяти), вернуться в вызвавшую программу
командой IRET.
В качестве вызывающей программы на первый случай используем специальную
короткую программу выгрузки.
Пример 5
Создадим резидентную программу примера 3, но с возможностью ее
выгрузки. Для простоты не будем включать в нее защиту от повторной
установки. Приведем здесь только измененное начало резидентной части
программы, включающую программу выгрузки, и полностью - ее
инициирующую часть.
;--------------------- Резидентная часть
old_2F dd 0 ;Старый адрес Int 2Fh
old_09 dd 0 ;Старый адрес Int 09h
sym1 dw 421Eh ;1-й выводимый символ
sym2 dw 241Eh ;2-й выводимый символ
M4: cmp AH,0C8h ;Cвоя функция прерывания 2Fh?
jnz M5 ;На переход, eсли не своя
cmp AL,01 ;Cвоя подфункция прерывания 2Fh?
jnz M5 ;На переход, если не своя
;---------------------- ;Начало программы выгрузки
push DS ;Сохраним те регистры, содержимое
push ES ;которых меняется в программе
push DX
mov DX,CS:word ptr old_09
mov DS,CS:word ptr old_09+2
mov AX,2509h ;Восстановление старого адреса old_09
INT 21h ;обработчика прерывания int 09h
mov DX,CS:word ptr old_2F
mov DS,CS:word ptr old_2F+2
mov AX,252Fh ;Восстановление старого адреса old_2F
INT 21h ;обработчика прерывания int 2Fh
mov ES,CS:2Ch ;Занесение из PSP:2Ch адреса
mov AH,49h ;окружения в рег.ES и выгрузка
INT 21h ;блока окружения
push CS ;Сегментный адрес начала блока
pop ES ;с программой из рег. CS в ES
mov AH,49h ;Выгрузка блока с резидентной
INT 21h ;программой
pop DX ;Восстановим содержимое
pop ES ;регистров DS, ES и DX
pop DS
;---------------------- ;Конец программы выгрузки
iret ;Возврат в вызвавшую программу
M5: jmp CS:old_2F ;Переход к 'чужой' резидентной
;программе раньше нас перехватившей
;прерывание INT 2Fh
M2: pushF ;Это начало основной части
call CS:old_09 ;резидентной программы,
push AX ;полностью соответствующей
push BX ;тексту примера 3
.......... ..................
.......... ..................
M1: ;---------------------- ;Инициирующая часть
mov AX,352Fh ;Получить в ES:BX старый адрес
INT 21h ;обработчика прерывания int 2Fh
mov word ptr old_2F,BX ;и запомнить его
mov word ptr old_2F+2,ES ;в ячейке old_2F
mov AX,252Fh ;Установка нового адреса <адр.M4>
lea DX,M4 ;обработчика прерывания int 2Fh
INT 21h ; -------
mov AX,3509h ;Получить в ES:BX старый адрес
INT 21h ;обработчика прерывания int 09h
mov word ptr old_09,BX ;и запомнить его
mov word ptr 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 ;Завершить и оставить резидентной
mov DX,(M1-Pr+10Fh)/16 ;часть размером (M1-Pr+10Fh)/16
INT 21h ; -------
x db 'Резидентный обработчик загружен$'
Seg1 ENDS ;Конец сегмента
END Pr ;Полный конец программы Pr
Здесь можно только пояснить, почему в резидентной части программы
в командах чтения или записи в память необходимо явное указание
сегмента, а в инициирующей части этого не требуется.
Дело в том, что при дальних вызовах подпрограмм командами CALL, INT
или переходах JMP автоматически изменяются только адреса в регистрах
CS и IP. Содержимое остальных регистров остается без изменения.
Инициирующая часть выполняется в 'родной' среде, при начальной загрузке
COM-программы. Здесь содержимое регистров DS и CS одинаково. Поэтому
команда:
mov word ptr old_2F,BX
по умолчанию равная команде:
mov DS:word ptr old_2F,BX
эквивалентна также и команде:
mov CS:word ptr old_2F,BX
А резидентная часть программы выполняется после ее вызова прерыванием
в 'чужой' среде, где содержимое регистров DS и CS разное.
В качестве программы вызова выгрузки РП используем следующую
короткую программу:
Seg1 SEGMENT
ASSUME SS:Seg1,DS:Seg1,CS:Seg1,ES:Seg1
ORG 100h ;Начало программы с 0100h
Pr: mov AH,0C8h ;Вызов INT 2Fh с функцией C8h
mov AL,01 ;и подфункцией 01h для
INT 2Fh ;выгрузки программы.
mov AX,4C01h ;Завершить обычным способом
INT 21h ; -------
Seg1 ENDS ;Конец сегмента
END Pr ;Полный конец программы Pr
Программа достаточно прозрачна и дополнительных пояснений не требует.
