Автор работы: Пользователь скрыл имя, 14 Мая 2012 в 16:48, курсовая работа
В данной работе рассмотрено явление, которое в операционной системе MSDOS играет роль многозадачности. С истинной многозадачностью можно столкнуться, рассматривая программирование в операционной системе Windows. Многозадачность же, рассматриваемая в этой курсовой работе, может быть названа нелегальной. Термин TSR происходит от английской фразы Terminate State Resident, т.е. "завершить и остаться резидентным". Резидентная программа, находясь в памяти, выполняет свои функции через перехваченные прерывания. Связь с резидентной программой также осуществляется посредством прерываний.
1 РЕЗИДЕНТНЫЕ ПРОГРАММЫ 4
2 ЗАЩИТА РЕЗИДЕНТНЫХ ПРОГРАММ ОТ ПОВТОРНОЙ УСТАНОВКИ .....8
3 ВЫГРУЗКА РЕЗИДЕНТНЫХ ПРОГРАММ ИЗ ПАМЯТИ 12
4 ОПИСАНИЕ ПРОГРАММЫ 13
Заключение 21
Литература 22
Приложение-листинг 23
Приложение-рисунок 35
mov si,80h lodsb cmp al,3 jl bue inc si lodsw cmp ax,'u/' jne bue
mov ax,3528h int21h push ds
Ids dx,dword ptr es:old_09
mov ax,2509h
int21h
Ids dx,dword ptr es:old_l С
mov ax,251Ch
int21h
Ids dx,dword ptr es:old_28 mov ax,2528h int 21h
Ids dx,dword ptr es:old_2F
mov ax,252Fh
int 21h
pop ds
mov ah,49h
int 21h
mov es,word ptr es:[0()2ch] mov ah,49h int 21h
bue:
mov ax,4c00h
int 21h TSRprog endp code_seg ends end begin
Во-первых, сразу запросим прерывание 2F - нет ли нашей программы в памяти. Для этого занесем в АХ запланированный нами код функции (см. выше процедуру New_2F - мы там решили занять для своих нужд функцию 80 и подфункцию 00 . Проверим поступивший из прерывания «отзыв». Наша программа должна отозваться кодом 0ABCD (см.выше процедуру New_2F).
Если это так, то мы пытаемся второй раз установить программу - это не нужно, а может быть мы хоти выгрузить ее из памяти? Надо проверить ключ в строке параметров запуска программы, поэтому перейдем к метке analiz.
В противном случае начинаем установку программы резидентом в памяти. Для этого сначала сохраним адреса старых векторов прерываний, которые мы планируем заместить своими процедурами. Начнем с вектора 28h. Используя стандартную функцию 35h прерывания 21h получим этот вектор в ES:BX и сохраним его в специально подготовленной ячейке old_28 (см.выше).
С помощью стандартной функции 25п прерывания 21h на место старого вектора установим адрес нашей процедуры, и затем то же самое проделаем с вектором 2Fh и с вектором 1 Ch.
Разместим в регистре dx адрес начала не резидентной части программы с помощью прерывания 27h завершим нашу программу, оставив ее в памяти резидентной:
lea dx,start int 27h
Теперь удем анализировать содержимое строки параметров нашей программы. После запуска программы, содержимое командной строки операционная система размещает по смещению 80h в PSP программы. Точнее по самому смещению 80h находится байт, в котором размещается число, равное количеству символов в строке параметров. Получим его из PSP, для чего смещение интересующего нас байта занесем в SI. Потом загрузим этот байт в AL:
lodsb
и проверим, не меньше ли длина строки параметров 3-х символов. Если меньше, то выйти из программы , иначе перейдем на адрес следующего байта командной строки и возьмем из нее в АХ два байта. Проверим, это наш ключ /и:
cmp ах,'и/'
если не равно, то это не наш ключ и программу завершаем. В противном случае начинаем модуль выгрузки программы из памяти. Для начала загрузим регистры ES:BX адресом нашей программы в памяти для чего возьмем вектор любого из контролируемых ею прерываний, например, 28h:
mov ax,3528h int 21h
Теперь сохраним регистр ds.
Загрузим регистры DS:DX адресом старого вектора прерывания 1С взятого из памяти нашей программы, которая сейчас стоит резидентом:
Ids dx,dword ptr es:old_09
mov ax,2509h
int21h
Ids dx,dword ptr es:old_lC
To же сделаем с прерыванием 28h и прерыванием 2F. Восстановим регистр DS. Используя стандартную функцию 49h прерывания 21h, освободим память, занимаемую нашей резидентной программой. Функция освобождает память, сегмент которой стоит в ES. А там как раз адрес начала нашей резидентной программы:
mov ah,49h int 21h
Теперь надо освободить память, занятую блоком окружения программы. Возьмем оттуда этот адрес и поместим его в ES:
mov es,word ptr es:[002ch] после чего дадим команду освободить этот блок:
mov ah,49h
int 21h
Когда блок окружения программы свободен, завершить программу и возвратиться в операционную систему: bue:
mov ax,4c00h
int 21h TSRprog endp code_seg ends end begin
Заключение
Многие программы, обеспечивающие функционирование вычислительной системы (драйверы устройств, программы сжатия или шифрования данных, русификаторы, интерактивные справочники и др.), должны постоянно находиться в памяти и быстро реагировать на запросы пользователя или на какие-то события, происходящие в вычислительной системе. Такие программы носят название программ, резидентных в памяти (Terminate and Stay Resident, TSR), или просто резидентных. Сделать резидентной можно любую программу, однако ввиду того, что резидентная программа должна быть максимально компактной, чаще всего в качестве резидентных используют программы типа .СОМ.
Литература
1. Пирогов В.Ю. ASSEMBLER Учебный курс Москва Издатель Молгачева СВ., 2001
2. Зубков С. В. ASSEMBLER -язык неограниченных возможностей Издательство «ДМК Пресс», 1999
3. АССЕМБЛЕР И ПРОГРАММИРОВАНИЕ ДЛЯ IBM PC Под редакцией Ершова В.Г.
4. В. И. Юров ASSEMBLER Учебник для вузов. 2-е изд. / В. И. Юров — СПб.: Питер, 2003. —637 с: ил.
5. Рудаков П. И., Финогенов К. Г. Язык ассемблера: уроки программирования. - М.: ДИАЛОГ-МИФИ, 2001. - 640 с.
6. Интернет.
Приложение-листинг
code_seg segment TSRprog proc far
assume cs:code_seg
org lOOh begin:
jmp start
old_09 dw ? dw?
New_09 Proc pushf
call cs:dword ptr old_09 cli
mov ah, 0lh int 16h jz exit_int
cmp al,'q'; clear Cnt, key combination 'q'
jne exit_int
mov cs:cnt,0
exit_int:q sti iret
New_09 endp
New_2F Proc
;обработка мультиплексного прерывания
24
24
exit:
cli
cmp ax,08000h
jne exit
mov ax, OABCDh
sti
iret
sti
jmp cs:[O1d_2F] Old 2F DD 0
;запретим на время все прерывания в ОС ; проверим, а нашу ли программу вызывают? ;если нет, то выйти из процедуры. ;иначе - отправить пароль «я здесь» разрешить опять все прерывания в ОС. ; выйти из прерывания
разрешить опять все прерывания в ОС. ;и перейти по адресу старого обработчика прерывания 2F.
;это место под адрес старого обработчика прерывания 2F.
21
New_2F endp
New 1С Proc
21
cmpcs:Cnt,9 1 ;проверяем прошло ли 5 сек.?
jb М2 ;если нет, то переход на увеличение счетчика jb
mov cs:flg_timer,l
M2:
;проверяем, прошло ли 5 секунд?
;если нет, то переход на увеличение счетчика jb
;сообщение можно выводить, поэтому установим
;в ячейке флага истечения
контрольного времени 1
inc byte ptr cs:Cnt увеличить счетчик времени на 1
jmp cs:[O1d_lC] ;перейти по адресу обработчика прерывания 2F.
01d_lC DD 0 ;адрес обработчика прерывания 2F.
Cnt DB 0 ;ячейка для счетчика тиков
21
flg_timer DB 0 ;ячейка для флага истечения заданного времени
New_lC endp
New_28 proc
;сохраним регистр флагов процессора
pushf
; проверим - в ячейке флага контроля истечения заданного времени установлена ли единица?
cmp cs:flg_timer,l
;если нет, то время до вывода сообщения на экран ;еще не истекло и мы переходим на старый ;обработчик прерывания 28h
jne Ml
;в противном случае активизируем модуль вывода
;сообщения на экран. Для чего
;сначала сохраним в стеке регистры, которые
;сейчас начнем использовать. Иначе
;мы испортим в них данные прерванной нами
программы.
push ах push bx push bp push es push cx
;3апретим прерывания нашей программы другими программами
mov ah, OFh ;Читаем текущий видео режим
int 1 Oh
mov ax,cs
mov es,ax ;Выводимая строка
;Количество строк
;Вызов random
;Строка начала вывода
mov bp,offset curtime
mov cl,25
call random
mov dh,al
mov cl,73 ;Количество колонок - количество символов
;(80-7)
call random ;Вызов random
mov dl,al ;Колонка начала вывода
mov bl,2Eh ;Атрибуты строки: желтые буквы на
;зеленом фоне
mov сх,7 ;Длина строки
mov ax,1300h ;Вывод
int 10h
jmpql
random:
;Сохраняем в стек регистры
push es
push bx push dx push cx
mov ah,0 ;Читаем часы
int lAh ;cx - старшая часть значения
;dx - младшая часть значения
mov es,cx mov bx,dx
mov al,byte ptr es:[bx] ;Возвращаемое значение
11:
12:
pop cx
cmp al,cl jb 12
sub al,cl jmp 11
;Восстанавливаем
; Сравнение
;Если ниже
;Иначе CL - AL ;Повторная проверка
;Восстанавливаем сохраненные регистры
pop dx
pop bx
pop es
ret
mov cs:flg_timer,0 mov cs:cnt,0
;разрешим внешние прерывания
Ml:
sti
pop cx pop es pop bp pop bx pop ax
popf
восстановим все сохраненные регистры
jmp cs:[old_28]
;В заключение процедуры передадим управление старому обработчику
;А это область данных нашей процедуры New_28. ; Здесь хранится текстовая строка выводимая на ;экран ПЭВМ
curtime db "Message'
old_28 dd 0
New_28 endp
start:
mov ax,08000h
;Во-первых, сразу запросим прерывание 2F - нет
ли нашей программы в памяти?
;Для этого занесем в АХ запланированный нами
;код функции (см. выше процедуру
;New_2F - мы там решили занять для своих нужд
функцию 80 и подфункцию 00
; Обратимся к функции 2F
int 2Fh
;Проверим поступивший из прерывания «отзыв». ;Наша программа должна отозваться кодом
;0ABCD (см.выше процедуру New_2F)
cmp ax,0ABCDh
;Если это так, то мы пытаемся второй раз
установить программу - это не нужно,
;а может быть мы хоти выгрузить ее из памяти?
;Надо проверить ключ в строке
параметров запуска программы, поэтому
перейдем к метке ANALIZ
je analiz
;В противном случае начинаем установку программы резидентом в памяти ;Для этого сначала сохраним адреса старых ; векторов прерываний, которые мы ;планируем заместить своими процедурами. ;Начнем с вектора 28h. Используя стандартную функцию 35h прерывания 21h ;получим этот вектор в ES:BX
mov ax,3528h
int 21h
;и сохраним его в специально подготовленной ;ячейке old_28 (см.выше)
mov word ptr old_28,bx
mov word ptr old_28+2,es
;C помощью стандартной функции 25h прерывания 21h на место старого вектора установим адрес нашей процедуры
mov ax,2528h
lea dx,new_28
int21h
; Теперь то же самое проделаем с вектором 2Fh
mov ax,352Fh
int 21h
mov word ptr old_2F,bx
mov word ptr old_2F+2,es
mov ax,252Fh
lea dx,New_2F
int21h
;и с вектором lCh
mov ax,351Ch
int21h
mov word ptr old_lC,bx
mov word ptr old_lC+2,es
mov ax,251Ch
lea dx,New_lC
int21h
mov ax,3509h
int21h
mov word ptr old_09,bx
mov word ptr old_09+2,es
mov ax,2509h
lea dx,New_09
int21h
27
27
lea dx, start
int 27h analiz:
;Разместим в регистре dx адрес начала НЕ РЕЗИДЕНТНОЙ части программы
;с помощью прерывания 27h завершим нашу
программу, оставив
;ее в памяти резидентной
27
занесем в SI
mov si,80h
lodsb
cmp al,3
jl bue
;Будем анализировать содержимое строки
щараметров нашей программы.