Примеры резидентных программ

Написать резидентную программу, которая перехватывает прерывание int 5 (Print Screen) и вместо распечатки экрана на каждое нажатие клавиши PrtSc изменяет цвет рамки экрана. Рамка должна принимать циклически один из 16 цветов. Программа не должна позволять загрузить себя повторно. При попытке повторной загрузки программа должна выводить предупреждающее сообщение.

УКАЗАНИЯ:

· Передавать управление старому обработчику прерывания не надо.

· Для окрашивания рамки экрана следует использовать подфункцию 01h функции 10h прерывания 10h (ax = 1001h, bx = цвет).

· В начале программы следует не забыть записать в DS значение CS.

· Для проверки наличия резидентной программы в памяти использовать функцию FFh прерывания 2Fh.

Assume CS: Code, DS: Code

Code SEGMENT

org 100h

resprog proc far

mov ax,cs

mov ds,ax

jmp init

color db 0

old_int2Fh_off dw ?

old_int2Fh_seg dw ?

msg db 'Драйвер уже установлен$'

; Новый обработчик прерывания 2Fh

new_int2Fh proc far

cmp ax,0ff00h

jz installed

jmp dword ptr cs:old_int2Fh_off

installed: mov ax,0ffh

iret

new_int2Fh endp

; Новый обработчик прерывания 5

new_int5 proc far

mov bh,color

inc color

mov ax,1001h

int 10h

iret

new_int5 endp

resprog endp

ressize equ $-resprog ; Размер в байтах резидентной части

init proc near

; Проверка раличия резидентной программы в памяти

mov ax,0ff00h

int 2fh

cmp ax,0ffh

jnz first_start ; Не установлена

lea dx,msg ; Вывод сообщения о том,

mov ah,9 ; что драйвер уже загружен

int 21h

ret

first_start: mov ax,2505h ; Функция 25h, вектор 5

lea dx,new_int5

int 21h ; Запись нового вектора 5

mov ax,352fh ; Сохранение старого вектора прерывания 2Fh

int 21h

mov cs:old_int2fh_off,bx

mov cs:old_int2fh_seg,es

lea dx,new_int2Fh ; Запись нового вектора прерывания 2Fh

mov ax,252fh

int 21h

; Завершение программы с оставлением резидентной части в памяти

mov dx,(ressize+10fh)/16

mov ax,3100h

int 21h

init endp

Code ENDS

END resprog

Написать резидентную программу, записывающую содержимое экрана в символьном режиме в файл. Программа должна анализировать флаг активности DOS и не должна допускать повторной загрузки в память. По ключу /u программа должна выгружаться из памяти с освобождением занимаемого ей места. Замечание: приведенная ниже программа нормально работает лишь под DOS до версии 5.0, так как в более поздних версиях иначе происходит работа с клавиатурой.

Code SEGMENT

Assume CS: Code, DS: Code

org 100h

resprog proc far

mov ax,cs

mov ds,ax ; DS = CS

jmp init ; Переход на инициализирующую секцию

num dw 0 ; Количество сброшенных экранов

old_int8_off dw ? ; Адрес старого обработчика

old_int8_seg dw ? ; прерывания таймера 8h

old_int5_off dw ? ; Адрес старого обработчика

old_int5_seg dw ? ; прерывания 5h

old_int2F_off dw ? ; Адрес старого обработчика

old_int2F_seg dw ? ; мультиплексного прерывания 2Fh

adr_psp dw ? ; Адрес PSP

vbuf dw 0b000h ; Сегментный адрес видеобуфера

handle dw ? ; Дескриптор файла

buf db 2050 dup(0) ; Буфер для данных экрана

mes db 'Disk error$'

filename db 'filescr&.txt',0 ; Спецификация вых. файла

iniflag db 0 ; Флаг запроса на вывод экрана в файл

outflag db 0 ; Флаг начала вывода в файл

_crit dd ? ; Указатель на флаг активности DOS

; Новый обработчик прерывания 2Fh

new_int2F proc far

cmp ax,0ff00h

jz installed

jmp dword ptr cs:old_int2F_off ; Переход на старый обработчик 2Fh

installed: mov ax,0ffh ; "Программа в памяти"

iret

new_int2F endp

; Новый обработчик прерывания 1ch

new_int8 proc far

push ax

push bx

push cx

push dx

push si

push di

push ds

push es

mov ax,cs

mov ds,ax

cmp iniflag,0

jz exit8 ; Нет запроса

test outflag,0ffh

jnz exit8 ; Файл уже выводится

jnz exit8 ; DOS занята

les bx,_crit

test byte ptr es:[bx],0ffh

jnz exit8 ; DOS занята

; iniflag=1, outflag=0, crit=0

mov outflag,0ffh

call writef ; Вывод буфера в файл

exit9: pop es

pop ds

pop di

pop si

pop dx

pop cx

pop bx

pop ax

iret

new_int8 endp

; Новый обработчик прерывания 5

new_int5 proc far

mov cs:iniflag,0ffh

iret

new_int5 endp

; Запись видеобуфера в файл

writef proc near

mov ax,cs

mov ds,ax

mov ax,0e07h

int 10h

mov ax,vbuf ; Начало видеобуфера (сегмент)

mov es,ax

mov si,0

lea di,buf

mov dx,25 ; Число строк

cld

trans1: mov cx,80 ; Число символов в строке

trans: mov al,es:[si]

mov [di],al

inc si

inc si

inc di

loop trans

mov byte ptr [di],0dh

inc di

mov byte ptr [di],0ah

inc di

dec dx

jnz trans1

; Создание файла

test word ptr num,0ffffh ; Сброшено экранов 0 ?

jnz sdwig ; Переход на смещение указателя

mov word ptr num,2050

mov ah,3ch ; Функция создания файла

mov cx,0 ; Без атрибутов

lea dx,filename ; Адрес спецификации файла

int 21h

jc noform

mov handle,ax ; Сохранение дескриптора файла

jmp write

sdwig: mov ax,3d01h ; Открытие файла с записью

lea dx,filename

int 21h

jc noform

mov handle,ax

mov ax,4200h ; Установка указателя файла

mov bx,handle

mov cx,0

mov dx,num

add word ptr num,2050

int 21h

; Запись файла

write: mov ah,40h ; Функция записи в файл

mov bx,handle ; Дескриптор файла

mov cx,2050 ; Длина записываемого массива

lea dx,buf ; Адрес записываемого массива

int 21h

jc noform

;Закрытие файла

mov ah,3eh ; Функция закрытия файла

mov bx,handle ; Дескриптор файла

int 21h

jmp prend

noform: mov ah,9

mov dx,offset mes

int 21h

prend: mov outflag,0

mov iniflag,0

ret

writef endp

resprog endp

ressize equ $-resprog ; Размер в байтах резидентной части

init proc near

; Проверка ключа /u

mov bx,80h

mov cx,[bx] ; Кол. символов в командной строке

inc bx ; Начало командной строки

cmd: mov al,[bx]

cmp al,20h

jz cmd1 ; Пробел

cmp al,'/'

jnz cmd2 ; Не ключ

cmp byte ptr [bx+1] ,'u'

jnz cmd2 ; Не u

; Освобождение блока памяти

; Проверка загруженности

mov ax,0ff00h

int 2fh

cmp ax,0ffh

jz uninst ; Программа в памяти

lea dx,msgno ; Вывод сообщения о том,

mov ah,9 ; что программы нет в памяти

int 21h

int 20h

uninst: call set_int ; Восстановление векторов прерываний

int 20h

cmd1: inc bx

loop cmd

cmd2: mov ax,0ff00h ; Проверка загруженности

int 2fh

cmp ax,0ffh

jnz first_start ; Не установлена

lea dx,msg ; Вывод сообщения о том,

mov ah,9 ; что драйвер уже загружен

int 21h

int 20h

first_start: mov ax,3505h ; Сохранение старого вектора прерывания 5

int 21h

mov cs:old_int5_off,bx

mov cs:old_int5_seg,es

mov ax,2505h ; Функция 25h, вектор 5

lea dx,new_int5

int 21h ; Запись нового вектора 5

mov ax,352fh ; Сохранение старого вектора прерывания 2Fh

int 21h

mov cs:old_int2F_off,bx

mov cs:old_int2F_seg,es

lea dx,new_int2F ; Запись нового вектора прерывания 2Fh

mov ax,252fh

int 21h

mov ax,351ch ; Сохранение старого вектора прерывания 8

int 21h

mov cs:old_int8_off,bx

mov cs:old_int8_seg,es

lea dx,new_int8 ; Запись нового вектора прерывания 8

mov ax,251ch

int 21h

mov ah,34h ; Запись указателя на флаг критической секции DOS

int 21h

mov word ptr _crit,bx

mov word ptr _crit[2],es

; Определение адреса видеобуфера

mov ah,0fh ; Функция получения видеорежима

int 10h

cmp al,7

jz ini1

mov vbuf,0b800h

ini1: lea dx,msg2

mov ah,9

int 21h

; Завершение программы с оставлением резидентной части в памяти

mov dx,(ressize+10fh)/16

mov ax,3100h

int 21h

init endp

set_int proc near

mov ax,3505h

int 21h ; ES - сегментный адрес PSP резидента

mov adr_psp,es

; Восстановление старого вектора 2Fh

push ds

mov dx,es:old_int2F_off

mov ax,es:old_int2F_seg

mov ds,ax

mov ax,252fh ; Установка старого вектора 2Fh

int 21h

mov dx,es:old_int8_off

mov ax,es:old_int8_seg

mov ds,ax

mov ax,251ch ; Установка старого вектора 8

int 21h

mov dx,es:old_int5_off

mov ax,es:old_int5_seg

mov ds,ax

mov ax,2505h ; Установка старого вектора 5

int 21h

pop ds

mov ah,9

lea dx,msg1

int 21h

mov es,adr_psp

mov ah,49h ; Освобождение памяти

int 21h

ret

set_int endp

msg db 0dh,0ah,'Программа уже в памяти',0dh,0ah,'$'

msgno db 0dh,0ah,'Программы нет в памяти',0dh,0ah,'$'

msg1 db 0dh,0ah,'Программа выгружена',0dh,0ah,'$'

msg2 db 0dh,0ah

db 'Программа для записи содержимого символьного',0dh,0ah

db 'экрана в файл FILESCR&.TXT.',0dh,0ah

db 'ALESOFT (C) Roshin A. 1994.',0dh,0ah

db 'Для копирования нажамите PrtSc.',0dh,0ah

db 'В файл можно записать не более 32 экранов.',0dh,0ah

db 'Для выгрузки программы следует набрать'

db ' filescr /u',0dh,0ah

db 0dh,0ah,'$'

Code ENDS

END resprog

Наши рекомендации