Примеры резидентных программ
Написать резидентную программу, которая перехватывает прерывание 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