Исходник резидентной программы, которая через заданный промежуток времени выдает на экран заданное сообщение.
Теория
Резидентная программа (terminate and stay resident, TSR) является специальным типом программы, которая остается в памяти после того, как вы ее запустили. Такое поведение находится в полной противоположности к поведению обычной прикладной программы, которая остается в памяти только в процессе выполнения. Эти программы называются резидентными еще и потому, что они требуют для себя блок памяти и обычно остаются в нем до тех пор, пока система не будет перезагружена. Фактически, они становятся почти постоянными жителями в памяти, подобно самой DOS.
Дня перехвата системного и установки своего прерывания обычно используются две функции DOS (функции 21h-го прерывания):
25h - установить вектор прерывания (Set Interrupt Vector);
35h - прочитать вектор прерывания (Get Interrupt Vector).
Все процедуры размещены в модуле установки программы в памяти, который будет делиться на две части: резидентная часть и установочная часть. Резидентная часть состоит из трех процедур:
1. Модуль предотвращения повторной установки программы в памяти и, одновременно, модуль выгрузки программы из памяти. Модуль будет устанавливаться вместо стандартного обработчика прерывания 2Fh. Сама программа будет закреплена за функцией 0FF00h, подфункция 0FFh. При наличии программы в памяти она будет отзываться на запрос прерывания 2Fh кодом 0FFh, возвращаемом в регистре AX.
2. Модуль контроля за истечением заданного времени будет устанавливаться на стандартное прерывание 1Ch (пользовательское прерывание таймера). Это прерывание в операционной системе вызывается 18,2 раза в секунду, следовательно, чтобы отсчитать промежуток времени в 10 заданных нам секунд надо пропустить 182 прерывания, после чего программа должна установить в некоторой ячейке, которую назовем "Флаг истечения времени", единицу, что будет являться сигналом для следующего блока, что заданное время ожидания истекло.
3. Модуль активизации и печати сообщения будет установлен взамен стандартного прерывания 28h. Это прерывание вызывается операционной системой в тот момент, когда она свободна и может выполнять запросы TSR программ. Модуль проверяет ячейку "Флаг истечения времени" и если там появляется единица, печатает заданное сообщение на экране, сбрасывает в ноль ячейку "Флаг истечения времени", сбрасывает счетчик модуля контроля за истечением заданного времени, устанавливая его в исходное состояние, и все начинается сначала
Текст программы
Код на ASM .286 assume cs:code, ds:code, es:code code segment org 2Ch EnvPtrlabel word ; сегмент окружения org 100h start:jmp realstart Interval equ 36 ; 2 секунды TickCnt dw Interval TimeOut db 0 OldHandler2F dd ? OldHandler28 dd ? OldHandler1C dd ? msgPastTimedb ' УРААААААААААААААААА! ' msgPastTimeLen equ $-msgPastTime ; обработчик прерывания 2Fh Handler2F: cmp ah, 0FFh jne NotThisFunction cmp al, 0 jne Handler2FEnd mov al, 0FFh Handler2FEnd: iret NotThisFunction: jmp cs:OldHandler2F ; обработчик прерывания 28h Handler28: cmp cs:TimeOut, 1 ; надо печатать сообщение ? jne Handler28End pusha push es mov cs:TimeOut, 0 ; печать сообщения mov ah, 0Fh ; получение номера текущей int 10h ; страницы в bh mov ax, cs ; настройка параметров и вывод mov es, ax ; строки сообщения mov bp, offset msgPastTime mov cl, 25 call random mov dh, al mov cl, 80-msgPastTimeLen call random mov dl, al mov bl, 2Eh mov cx, msgPastTimeLen mov ax, 1300h int 10h pop es popa Handler28End: jmp cs:OldHandler28 random: push es push bx push dx push cx mov ah, 0 int 1Ah ; cx:dx - время mov cx, 0 mov es, cx mov bx, dx mov al, es:bx pop cx l1: cmp al, cl jb l2 sub al, cl jmp l1 l2: pop dx pop bx pop es ret ; обработчик расширенного прерывания таймера 1Ch Handler1C: dec cs:TickCnt jnz Handler1CEnd mov cs:TickCnt, Interval mov cs:TimeOut, 1 Handler1CEnd: jmp cs:OldHandler1C ; Конец резидентной части EndResidentlabel byte msgLoadTSR db ' Лабораторная работа 5 по ОС', 13, 10 db ' TSR установлен' db '$' msgUnloadTSR db ' Программа выгружена из памяти' db '$' realstart: ;Сразу запросим прерывание 2Fh-нет ли нашей ;программы в памяти mov ax, 0FF00h ;для этого занесем в ах запланированный нами;код функции int 2Fh ;обратимся к функции 2Fh cmp al, 0FFh ;проверим поступивший из прерывания "отзыв" je Unload ;надо проверить ключ в строке параметров ;запуска программы mov dx, offset msgLoadTSR mov ah, 9 int 21h ; сохраним адреса старых векторов прерываний(вектора прерывания 2F), mov ax, 352Fh ;которые мы планируем заместить своими процедурами int 21h ;используя станд. функцию 35h прерывания 21h mov word ptr OldHandler2F ,bx ;получим вектор es:bx mov word ptr OldHandler2F+2,es mov ax, 252Fh ;с помощью стандартной функции 25h и прерывания 21h mov dx, offset Handler2F ;на место старого вектора установим адрес нашей процедуры int 21h ;(проделаем то же самое) получение и сохранение вектора прерывания 1C mov ax, 351Ch int 21h mov word ptr OldHandler1C , bx mov word ptr OldHandler1C+2, es mov ax, 251Ch mov dx, offset Handler1C int 21h ; (проделаем то же самое) получение и сохранение вектора прерывания 28 mov ax, 3528h int 21h mov word ptr OldHandler28 , bx mov word ptr OldHandler28+2, es mov ax, 2528h mov dx, offset Handler28 int 21h ; освобождение блока окружения DOS mov ax, EnvPtr mov es, ax mov ah, 49h int 21h ; резидентный выход mov dx, offset EndResident int 27h Unload: ; получение и сохранение адреса старой программы mov ax,352Fh int 21h ; es - сегмент TSR части ; восстановление старого вектора для 2Fh mov ax, 252Fh ;загрузим регистры ds:dx адресом старого вектора прерывания 2F, lds dx, es:OldHandler2F ;взятого из памяти нашей программы, кот. сейчас стоит резидентом int 21h ; восстановление старого вектора для 1Ch mov ax, 251Ch lds dx, es:OldHandler1C int 21h ; восстановление старого вектора для 28h mov ax,2528h lds dx, es:OldHandler28 int 21h ; удаление из памяти TSR (в ES - сегмент-адрес начала резид. прог.)) mov ah, 49h int 21h mov ax, cs mov ds, ax ;Выводим сообщение об освобождении mov dx, offset msgUnloadTSR mov ah, 9 int 21h ;завершение программы, возврат а ОС mov ax, 4C00h int 21h code ends end start
После запуска программы на экране в произвольных местах с интервалом в 2 секунды начинают появлятся надписи "УРАААААААААААА! ". Повторный запуск программы удаляет резидентную часть из памяти.
|