Iret ;Выход в dos
M1: ;----------------Иниц. часть
MOV CL,ES:80h ;Чтение из PSP:80h кол-ва символов
CMP CL,0 ;Если их нет, то вывод сообщения:
JZ M 8 ;'ERROR'
MOV CH,0 ;Теперь кол. символов в рег.CX
MOV AL,'/' ;Поиск символа '/'
MOV DI,81h ;начиная с PSP:81h
REPNZ SCASB ;Результат: DI=адр.символа за '/'
CMP byte ptr [DI], 'z' ;Если найденный код='z', то
JZ M6 ;переход к загрузке РП
CMP byte ptr [DI], 'v' ;Если найденный код='v', то
JZ M7 ;переход к выгрузке РП
M8: MOV AH,09h ;Вывод сообщения ‘ERROR’
LEA DX, MESS1 ;
INT 21h
MOV AX,4C01h ;Вход в DOS
INT 21h
MESS1 db 'ERROR$'
M7: ;--------------Вызов выгрузки РП
MOV AH,0C8h ;Вызов INT 2Fh с функцией C8h
MOV AL, 01h ;и подфункцией 01h для
INT 2Fh ;выгрузки программы.
MOV AH,09h ;вывод сообщения
LEA DX ,MESS2 ;'RESID PROGA UNDOWNLOADER$'
INT 21h
MOV AX, 4C01h ;Завершить обычным способом
INT 21h
MESS2 db 'RESID PROGA UNDOWNLOADER$'
M6: ;-----------Вызов загрузки РП
MOV AX,352Fh ;Получить в ES:BX старый адрес
INT 21h ;обработчика прерывания int 2Fh
MOV word ptr old_2F,BX ;и запомнить его
MOV word ptr old_2F+2,E ;в ячейке old_2F
MOV AX,252Fh ;Установка нового адреса <адр.M4>
LEA DX,M4 ;обработчика прерывания int 2Fh
MOV AX, 351Ch ;Получить в ES:BX старый адрес
INT 21h ;обработчика прерывания int 1Ch
MOV word ptr old_1C, ;и запомнить его
MOV word ptr old_1C+2,ES ;в ячейке old_1C
MOV AX,251Ch ;Установка нового адреса <адр.M2>
LEA DX, M2 ;обработчика прерывания int 1Ch
INT 21h
MOV AH,09h ;Вывод сообщения
LEA DX, MESS ;'RESID PROGA DOWNLOADER$'
INT 21h
MOV AX, 3100h ;Завершить и оставить pезидентной
MOV DX, (M1-PROGA +10Fh)/16 ;часть размером (M1-PROGA+10Fh)/16
INT 21h
MESS db 'RESID PROGA DOWNLOADER$'
SEG1 ENDS ;Конец сегмента
END PROGA ;Полный конец программы PROGA
Вывод:
При запуске программы с клавиатуры используются опции(ключи загрузки-выгрузки)
PROGA /z - загрузить в память резидентную программу
PROGA /v - выгрузить из памяти резидентную программу
Программа вызывается по прерыванию от таймера пользователя (возникает 18,2 раз в сек) с вектором 1Ch. Это дублер прерывания системного таймера IRQ0.
Для того, чтобы прикладные программы могли использовать сигналы таймера,
не нарушая при этом работу системных часов, в программу BIOS, обслуживающую
аппаратные прерывания от таймера, поступающие через вектор 08, включен вызов
int 1Ch, передающий управление на программу-заглушку BIOS, которая содержит
единственную команду iret .Пользователь может записать в вектор
1Ch адрес прикладного обработчика сигналов таймера и использовать в своей
программе средства реального времени.
В нашем случае программа выводит в нижний правый угол экрана показания системных часов в ответ на каждый 64-й запрос таймера
Для снижения частоты вывода
нам пришлось в обработчике отсчитывать прерывания и выводить символ на экран
не при каждом вызове обработчика, а на каждый 64-й вызов.
В обработчике предусматривается ячейка count для отсчета прерываний. При
каждой активизации обработчика содержимое этой ячейки увеличивается на 1
Для выделения каждого 64-ого запуска обработчика в
программе используется команда test.
Команда test byte ptr CS:count,3Fh в сочетании с командой jnz M3
осуществляет переход на метку M3 т.е. на завершение программы, если
установлен хотя бы один из битов 0 ..5 байта count. Таким образом,
содержательная часть обработчика будет выполняться лишь в тех случаях, когда
все эти биты сброшены. При последовательном наращивании счетчика count такая
ситуация будет возникать при каждом 64-ом вызове обработчика. Следует
обратить внимание на необходимость использования в рассматриваемой команде
описателя byte ptr (byte pointer, указатель на байт). При указании второго
операнда в виде "безразмерного" непосредственного значения транслятор не
может решить, анализировать ли ему байт или слово.
Для управления процессом выгрузки воспользуемся мультиплексным
прерыванием INT 2Fh.
Обработчик прерывания INT 2Fh резидентной программы должен:
- приняв прерывание, проверить номер функции в регистре AH и, если
номер не свой, передать управление ранее загруженной резидентной
программе, также использующей прерывание INT 2Fh
JMP CS:old_2f
здесь 'old_2f' - ячейка памяти, где хранится старый адрес вектора
прерывания INT 2Fh.
- если номер функции свой, проверить номер подфункции в регистре AL
и, выполнив необходимые действия (в нашем случае это выгрузка
резидентной программы из памяти), вернуться в вызвавшую программу
командой IRET.
Если программа запущена с параметром в виде
PROGA/v
выполняется выгрузка резидентной программы из памяти.
Для выгрузки программы из памяти, внутри резидентной части есть специальная
программа выгрузки(строки15-45).
А для вызова программы выгрузки, в инициализирующей части используем прерывание
INT 2Fh.
В результате выполнения курсовой работы, была разработана РП на языке ассемблера персональных компьютеров типа IBM PC, работающих под управлением операционной системы MS-DOS в реальном режиме.
РП выводит показания системных часов в нижний правый угол экрана с частотой – один
раз в 3-4сек , что соответствует каждому 64-ому запросу таймера.
Ключ загрузки - /z. Ключ выгрузки - /v