Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
31
Добавлен:
20.06.2014
Размер:
262.14 Кб
Скачать

8. Создание диалоговой среды

Еще больше удобств дает возможность прямо отвечать на вопросы,

которые нам задает программа при загрузке. При этом сначала проверяется

загружена или нет данная резидентная программа. Если программа еще не

загружена, то производится ее загрузка. Если программа уже загружена,

то выдается запрос:

Вы хотите выгрузить РП из памяти? (Y,N)

В ответ требуется ввести один из указанных в скобках символов. В

зависимости от этого, либо выполнится выгрузка, либо просто закончится

программа.

Пример 8

Напишем фрагмент программы, который производит указанные выше

действия. Будем считать, что резидентная часть программы уже содержит

раздел проверки на повторную установку (как в примере 4), и раздел

выгрузки программы из памяти (как в примере 5). После проработки

предыдущих примеров у Вас появился достаточный опыт в составлении

резидентных программ. Поэтому приведем здесь лишь фрагмент инициирующей

части программы без конкретного значения меток переходов:

M1: ;---------------------- ;Инициирующая часть

mov AH,0C8h ;Вызов INT 2Fh с функцией C8h

mov AL,00 ;и подфункцией 00h

INT 2Fh ; -------

cmp AL,0FFh ;Вернулась подфункция = FFh?

jnz M16 ;Eсли 'нет', то на загрузку

mov AH,09h ;Вывод строки x1 с текстом:

lea DX,x1 ;'Вы хотите выгрузить РП ? (Y,N)'

INT 21h ; -------

mov AH,01h ;Прием символа с клав. в рег. AL

INT 21h ;Ожидает нажатия клавиши

cmp AL,'Y' ;Введен код клавиши 'Y'?

jz M18 ;Eсли 'да', переход к выгрузке РП,

;иначе - окончание программы.

9. Загрузка рп в верхнюю память

Любую резидентную программу можно загрузить в верхнюю память, чтобы

освободить место в обчной памяти для работы других программ. Это легко

сделать с помощью команды Loadhigh или LH:

LH rez.com Здесь 'rez.com'- имя резидентной программы

Выгрузку можно делать как с LH, так и без нее. Ведь при этом программа

никуда не устанавливается, а только выполняется:

rez.com off

Разумеется, резидентная программа загрузится в верхнюю память при

условии, что в файле CONFIG.SYS были загружены программы HIMEM и EMM386

и в блоке UPPER достаточно свободного места для размещения Вашей

программы.

10. Действия,выполняемые рп

Резидентная программа загружается в память с целью выполнения

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

и выполняемая ею функция носит название - обработчик прерывания.

Обработчик прерывания это главный фрагмент резидентной части программы,

выполняющий заданное действие, ради которого и была создана данная РП.

В приведенных выше примерах со 2 по 6 для вывода цветного символа на

зкран был использован обработчик прерывания вида:

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

Если обработчик прерывания вызывается аппаратным прерыванием,

в частности прерыванием от клавиатуры, как в вышеприведенных примерах,

то он не должен содержать внутри себя никаких прерываний DOS (int 21h).

Крайне нежелательны и прерывания BIOS, хотя некоторые из них иногда

работают нормально. Все зависит от среды из которой вызывается наш

обработчик.

Рассмотрим еще один обработчик прерывания от клавиатуры, который

может быть использован Вами при выполнении курсовой работы.

Пример 9

Вывод текущей даты в последние позиции экрана.

mov AL,87h ; Занесение адреса числа

out 70h,AL ; в порт 70h

in AL,71h ; Чтение числа из порта 71h

mov BX,00 ; Номер позиции на экране для вывода

call P1 ; Вывод 2-х цифр из AL на экран

mov AL,88h ; Занесение адреса месяца

out 70h,AL ; в порт 70h

in AL,71h ; Чтение месяца из порта 71h

mov BX,06 ; Номер позиции на экране для вывода

call P1 ; Вывод 2-х цифр из AL на экран

mov AL,89h ; Занесение адреса года

out 70h,AL ; в порт 70h

in AL,71h ; Чтение года из порта 71h

mov BX,12 ; Номер позиции на экране для вывода

call P1 ; Вывод 2-х цифр из AL на экран

mov AX,0EA3h ;

mov ES:[BX+3984],AX ;Вывод символа 'г'

jmp M3

P1 proc ;Процедура вывода 2-х цифр из AL на экран

push CX ;Сохраним те регистры, содержимое

push AX ;которых меняется в программе

mov CL,4 ;Число сдвигов

SHR AL,CL ;Сдвиг AL вправо 4 р

call P2 ;Перевод цифры из AL в символ

mov ES:[BX+3980],AX ;Вывод старшей цифры

pop AX ;Восстановим AX

call P2 ;Перевод цифры из AL в символ

mov ES:[BX+3982],AX ;Вывод младшей цифры

mov AX,0E2Eh ;

mov ES:[BX+3984],AX ;Вывод символа '.'

pop CX ;Восстановим CX

ret

P1 endp

P2 proc ;Процедура перевода цифры из AL в символ

and AL,0Fh ;Выделение мл. полубайта

add AL,'0' ;Добавление кода 30h

mov AH,0Eh ;Байт атрибутов

ret

P2 endp

Здесь все составляющие даты читаются из CMOS через порт 71h.

Предварительно в порт 70h должен быть записан требуемый Вам адрес

CMOS с единицей в старшем разряде (см.лекцию 'Часы реального времени'),

то есть, например, вместо адреса 04h, следует записать 84h.

Карта адресов CMOS

00 Секунды 01 Секунды будильника

02 Минуты 03 Минуты будильника

04 Часы 05 Часы будильника

06 День недели (1 - воскресенье)

07 Число месяца

08 Месяц

09 Год

Процедуры P1 и P2 нужны для перевода чисел прочитанных из CMOS

в символьную форму. Например, чтобы вывести на экран число 0101b (5h),

его надо преобразовать в код 35h.

Следует также помнить, что там, где Вы в программе сохраняете

в стеке реистры: push AX, push ES и т.д., надо добавить и сохранение

регистров используемых обработчиком!

Если обработчик прерывания вызывается прерыванием пользователя,

например int 60h, то написание его программы упрощается. Такой

обработчик может содержать внутри себя любые прерывания DOS и BIOS.

Рассмотрим такой обработчик прерывания, вызываемый пользовательским

прерыванием int 60h. Он также может быть использован Вами при выполнении

курсовой работы. Для вызова РП, команда int 60h вписывается в нужные

места отлаживаемой программы.

Пример 10

Вывод содержимого регистров отлаживаемой программы.

Для удобства здесь приведена полностью резидентная часть РП.

;--------------------- Резидентная часть

str1 db 10,13,' Регистры:',10,13

str2 db ' SS=**** ES=****',10,13

str3 db ' DS=**** SP=****',10,13

str4 db ' IP=**** CS=****',10,13

str5 db 'Флаг=**** ',10,13,'$'

P1 ;Процедура перевода 4-х цифр регистра AX в символьную форму

proc

push AX ;Сохраним AX

mov CL,12 ;Сдвиг 1-й цифры в самый младший

shr AX,CL ;полубайт рег.AX

call P2 ;Перевод в симв. форму 1-й цифры

;и занесение его в строку вывода

pop AX ;Восстановим AX

push AX ;Сохраним AX

mov CL,8 ;Сдвиг 2-й цифры в самый младший

shr AX,CL ;полубайт рег.AX

inc SI ;Для занесения в след. байт

call P2 ;Перевод в симв. форму 2-й цифры

;и занесение его в строку вывода

pop AX ;Восстановим AX

push AX ;Сохраним AX

mov CL,4 ;Сдвиг 3-й цифры в самый младший

shr AX,CL ;полубайт рег.AX

inc SI ;Для занесения в след. байт

call P2 ;Перевод в симв. форму 3-й цифры

;и занесение его в строку вывода

pop AX ;Восстановим AX

inc SI ;Для занесения в след. байт

call P2 ;Перевод в симв. форму 4-й цифры

ret ;и занесение его в строку вывода

P1 endp

;------------------------------------------

P2 proc

and AX,0Fh ;Выделим мл. цифру из AX

cmp AL,0Ah ;если цифра >=10

jnb V1 ;то переход к V1

add AL,'0' ;иначе добавл.30h

jmp V2 ;вывод цифры <10

V1: add AL,37h ;доб. 37h (коды цифр A,B,C,D...)

V2: mov [SI],AL ;Занесение в строку вывода

ret

P2 endp

;----------------------- Обработчик прерывания РП

M2:

push SP ;Сохраним в стеке используемые

push DS ;регистры. Заодно, будет удобно

push ES ;читать и содержимое этих

push SS ;регистров командами MOV AX,[BP]

mov BP,SP ;Указатель стека в BP

push CS ;Пересылка из CS в DS

pop DS

mov AX,[BP] ;Выводимый рег. SS

lea SI,str2+5 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+2 ;Выводимый рег. ES

lea SI,str2+15 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+4 ;Выводимый рег. DS

lea SI,str3+5 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+6 ;Выводимый рег. SP

lea SI,str3+15 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+8 ;Выводимый рег. IP

lea SI,str4+5 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+10 ;Выводимый рег. CS

lea SI,str4+15 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AX,[BP]+12 ;Выводимый рег. Флагов

lea SI,str5+5 ;Адрес, куда помещать результат

call P1 ;Перевод 4-х цифр из AX в символы

mov AH,09h ;Вывод строки результатов

lea DX,str1 ;Адрес начала строки вывода

int 21h

pop SS ;Восстановим содержимое

pop ES ;регистров

pop DS ;

pop SP ;

IRET ;Выход в DOS

M1: ;---------------------- ;Инициирующая часть

Здесь обработчик прерывания читает содержимое регистров прямо из стека

с помощью команд:

mov AX,[BP] ;Содержимое рег. SS

mov AX,[BP]+2 ;Содержимое рег. ES

mov AX,[BP]+4 ;Содержимое рег. DS

и т.д.

Регистры IP, CS и рег. флагов помещаются в стек еще при вызове int 60h,

поэтому их содержимое мы также можем извлечь.

Командами типа:

lea SI,str2+15

мы заносим в рег. SI адрес байта в строке, куда будем помещать

результат командой:

mov [SI],AL ;Занесение в строку вывода

при выполнении процедуры P2.

После того,как строки str2, str3, str4, str5 будут заполнены, их

вывод на экран (всех сразу) производится прерыванием int 21,09h:

mov AH,09h ;Функция вывода

lea DX,str1 ;Адрес начала строки вывода

int 21h ;Вывод строки результатов

Соседние файлы в папке Кр и методичка Разработка резидентной программы в MS DOS