|
У
пользователей существует только один способ защитить себя - это
установка только одной подпрограммы для проверки конфликтов.
REMOVE - пример интегрированной программы
Программа удаления REMOVE (смотри листинг 3-13) предназначе-
на для удаления установленной резидентной программы и базируется
на примере, данном в INIT28 (смотри листинг 3-12). Программа
REMOVE пытается идентифицировать резидентную программу путем
- 3-66 -
дампирования байтов, следующих за точкой входа, и отображает 4
байта, предшествующих точке входа, как адрес предыдущего векто-
ра. Кроме того, программа REMOVE предполагает, что резидентная
программа представлена в формате .COM, и пытается разместить ад-
реса PSP и блока среды. Всю эту информацию программа REMOVE пре-
доставляет пользователю для принятия решения о том, удалять ре-
зидентную программу, вставленную в вектор прерывания, или нет.
Листинг 3-13. REMOVE - удаление резидентной подпрограммы,
вставленной в качестве "заплаты" в вектор
прерывания
----------------------------------------------------------------
PAGE 60,132
;===== REMOVE - Этот файл генерирует программу типа .COM =======
;===== Удаление резидентной подпрограммы, вставленной в ка- ====
;============ честве "заплаты" в вектор прерывания =============
;(Interrupt Service Routine (ISR) - это подпрограмма обслужива-
; ния прерывания))
OLD_IP EQU -4 ; Возможное положение IP в ISR
OLD_CS EQU -2 ; Возможное положение CS в ISR
ID EQU 0 ; Положение 1-го байта в ISR
IRETOP EQU 0CFh ; Код операции IRET
;
;===== МАКРООПРЕДЕЛЕНИЯ ДЛЯ УТИЛИТ =============================
;
INCLUDE STDMAC.INC ; Включение макроопределений
;
remove SEGMENT
ASSUME cs:remove
ASSUME ds:remove
; Определение необходимых адресов внутри сегмента программого
; префикса (PSP)
ORG 2Ch
env_adr LABEL WORD ; Адрес указателя среды
ORG 80h
cmd_len db ? ; Длина командной строки
new_len db ? ; Длина строки буферизованного чтения
cmd_buf db ? ; Строка командной строки
;===== НАЧАЛО ПРОГРАММНОГО КОДА ================================
ORG 0100h
main PROC FAR
start:
mov ch,byte ptr [cmd_len]
cmp ch,0 ; аргумент обеспечен ?
jnz have_cmd
; Аргумент не обеспечен - приглашение пользователя для указания
get_cmd:
@DisStr request ; приглашение для номера вектора
mov byte ptr [cmd_len],80
mov dx,offset cmd_len
mov ah,0Ah ; выполнение буферизованного чтения в
@DosCall ; буфер командной строки
@DisChr LF ; новая строка
mov ch,new_len ; получение размера введенного текста
cmp ch,0 ; просмотр, ответил ли пользователь?
jz abort ; если нет, то предполагается выход
inc ch ; установка ответа для приведения в
- 3-67 -
; соответствие
have_cmd:
cmp ch,3 ; проверка для правильного # символов
je ok_cmd
@DisStr bad_cmd ; если ошибка, то некорректный флажок
abort: jmp finis
ok_cmd: mov bx,offset cmd_buf
mov ch,2 ; грамматический разбор 2 символов
call get_hex ; преобразование # в буфер в двоичн.
jc abort ; выход, если ошибка преобразования
mov vec_num,al ; сохранение адреса вектора
mov ah,35h ; получение указателя вектора из MS-DOS
@DosCall
mov vec_ip,bx ; сохранение IP вектора
mov al,vec_num ; восстановление номера вектора
call show_vector ; отображение содержимого вектора
@DisStr askresv
call yesno
jc no_restore ; нельзя желать восстановить вектор
;
; ВОССТАНОВЛЕНИЕ ВЕКТОРА ПО АДРЕСУ В ПОДПРОГРАММЕ
mov bx,vec_ip ; получение адреса подпрограммы
mov dx,es:OLD_IP[bx] ; получение IP старого вектора
mov cx,es:OLD_CS[bx] ; получение CS старого вектора
mov al,vec_num ; получение номера вектора
push ds ; сохранение текущего DS
mov ds,cx ; установка назначения вектора
mov ah,25h ; установка адреса вектора
@DosCall
pop ds ; восстановление сегмента данных
;
; Отображение адреса среды и выдача приглашения для удаления.
; Адрес среды будет действительным, если это программа типа .COM
no_restore:
@DisStr askremb ; отображение адреса среды
mov ax,es:env_adr ; получение адреса среды
mov ch,4
call bin2hex ; отображение возможного сегмента среды
@DisStr ip0
call yesno
jc no_env ; обход удаления среды
;
; УДАЛЕНИЕ БЛОКА СРЕДЫ
push es ; сохранение сегмента главной подпрограммы
mov cx,es:env_adr ; получение адреса среды
mov es,cx ; и подготовка к удалению
call rem_mem ; попытка удалить блок
pop es ; восстановление адреса главной подпрограммы
;
; Отображение адреса сегмента главной подпрограммы и выдача
; приглашения для его удаления
no_env:
@DisStr askremm ; отображение адреса главного блока
mov ax,es ; адрес главного блока
mov ch,4
call bin2hex
@DisStr ip0
- 3-68 -
call yesno
jc finis ; нельзя желать удаления главного блока
;
; УДАЛЕНИЕ ГЛАВНОГО БЛОКА ПАМЯТИ РЕЗИДЕНТНОЙ ПОДПРОГРАММЫ
call rem_mem ; попытка удаления блока
;
finis: mov ax,4C00h ; завершение программы
@DosCall
;
vec_num db ? ; память для запоминания номера вектора
vec_ip dw ? ; память для запоминания IP вектора
; Номер удаляемого вектора
request db 'Vector number to remove: $'
; Аварийное завершение из-за ошибки в командной строке
bad_cmd db 'Command Line format error - aborting',CR,LF,'$'
; Восстановить вектор из старого ?
askresv db 'Restore Vector from Old? $'
; Удаление блока среды
askremb db 'Remove Environment Block: $'
; Удаление блока главной программы
askremm db 'Remove Main Program Block: $'
ip0 db ':0000 $'
;
main ENDP
;
; == REM_MEM использует функцию 49 (шестн.) MS-DOS для попытки =
; ======= перераспределения блока памяти, адресуемого ES =======
;
rem_mem PROC NEAR
push ax ; сохранение регистров
push cx ; используемых
push dx ; @DisStr и @Dischr
mov ah,49h ; освобождение распределенной памяти
@DosCall
jnc free_ok ; нет ошибок - выдача сообщения об успехе
push ax ; сохранение кода ошибки
@DisStr fail ; информирование о сбое
pop ax ; и выдача кода ошибки
mov ch,4 ; (все 4 цифры)
call bin2hex
@DisChr CR
@DisChr LF
jmp rem_exit
free_ok:
@DisStr pass
rem_exit:
pop dx ; восстановление регистров
pop cx
pop ax
ret
; Успешное освобождение распределенной памяти
pass db 'Successful Free Allocated Memory',CR,LF,'$'
; Сбой при освобождении распределенной памяти - код ошибки
fail db 'Failed to Free Allocated Memory - Error Code: $'
rem_mem ENDP
;
; ===== YESNO приглашает пользователя ответить либо Y, либо N. =
- 3-69 -
; ===== Если введено Y (да), то YESNO возвращает без переноса ==
; ===== (NC). Если введено N (нет) или , то YESNO возвра- =
; ===== щает с переносом (CY). =================================
yesno PROC NEAR
push ax
push dx
@DisStr prompt ; приглашение пользователя для ввода
retry: mov ah,08h ; получение ответа (no echo - нет эха)
@DosCall
@Case al,<'y','Y','n','N',CR>,
@DisChr 07h ; неправильный ответ - гудок
jmp retry ; и ожидание нового ответа
no: @DisStr 'N'
stc
jmp yn_exit
yes: @DisChr 'Y'
clc ; очистка переноса
yn_exit:
@DisChr CR
@DisChr LF
pop dx
pop ax
ret
prompt db ' (Y/N): $',
yesno ENDP
;
; ===== SHOW_VECTOR отображает содержимое отмеченных ячеек =====
; ===== в ES:BX в шестнадцатиричном формате и в формате ASCII. =
; ===== Так как это используется внутри отображения вектора, ===
; ===== то она также показывает AL в шестнадцатиричном формате =
; ===== как номер вектора, и информирует пользователя, если ===
; ===== в инструкции IRET отмечен первый байт. =================
; ===== SHOW_VECTOR также отображает два слова, размещенные ====
; ===== перед адресом вектора как CS:IP, в случае если =========
; ===== пользователь запомнил там адрес старого вектора при ====
; ===== установке.
|