На главную
Подписка
Новости










Главная / MS-DOS / MS-DOS. РУКОВОДСТВО РАЗРАБОТЧИКА / Глава 3 / REMOVE - пример интегрированной программы Сделать домашней страницей Добавить в избранное Написать писмо

НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

REMOVE - пример интегрированной программы

Программа удаления REMOVE (смотри листинг 3-13) предназначена для удаления установленной резидентной программы и базируется на примере, данном в INIT28 (смотри листинг 3-12). Программа REMOVE пытается идентифицировать резидентную программу путем дампирования байтов, следующих за точкой входа, и отображает 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         ; установка ответа для приведения в
                                   ; соответствие
         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
                 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. =
         ; ===== Если введено 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, в случае если =========
         ; ===== пользователь запомнил там адрес старого вектора при ====
         ; ===== установке. =============================================
         ;
         show_vector    PROC NEAR
                 push   cx         ; сохранение регистров,
                 push   dx         ;     используемых
                 push   ax         ; @DisChr и @DisStr
                 @DisStr vmsg1     ; начало отображения сообщений
                 pop    ax         ; восстановление значения AL
                 push   ax
                 mov    ah,al
                 mov    ch,2       ; отображение двух шестнадц. цифр
                 call   bin2hex
                 @DisStr vmsg2     ; показ потенциального адреса воосст-я
                 mov    ax,es:OLD_CS[bx] ; получение возможн. значения CS
                 mov    ch,4
                 call   bin2hex    ; отображение возможного старого CS
                 @DisChr ':'
                 mov    ax,es:OLD_IP[bx] ; получение возможн. значения CS
                 call   bin2hex    ; отображение возможного старого CS
                 cmp    byte ptr es:ID[bx],IRETOP
                 jne    noiret     ; это инструкция IRET?
                 @DisStr vmsg3
         noiret: @DisChr CR
                 @DisChr LF
                 mov    cl,16      ; дамп 16 байтов
                 call   dump       ; показ шестнадц. и ASCII значений
                 pop    ax
                 pop    dx
                 pop    cx
                 ret
         vmsg1   db     'Vector # $'
         vmsg2   db     '  Old Vector: $'
         vmsg3   db     'IRET$'
         show_vector    ENDP
         ;
         ; ===== DUMP отображает содержимое ячеек, отмеченных с помощью =
         ; ===== ES:BX, в шестнадцатиричном формате и в формате ASCII. ==
         ; ===== Содержимое CL # отображаемых байтов. ===================
         dump    PROC   NEAR
                 push   ax         ; сохранение регистров,
                 push   dx         ;     используемых
                 push   bx         ; @DisChr и @DisStr
                 push   cx
                 @DisStr dmsg1     ; начало отображения сообщений
                 mov    ch,2       ; 2 шестнадцатиричные цифры на байт
         h_dump: mov    ah,es:[bx] ; получение байта
                 jnc    bx         ; следующий байт
                 call   bin2hex
                 @DisChr ' '
                 dec    cl         ; счетчик цикла - 1
                 jnz    h_dump     ; повторение, пока счетчик не станет 0
                 @DisStr dmsg2     ; следующий раздел
                 pop    cx         ; восстановление значений
                 pop    bx         ;     BX (индекс)
                 push   bx         ;        и
                 push   cx         ;     CX (счетчик)
         t_dump: mov    al,es:[bx] ; получение байта
                 jnc    bx         ; следующий байт
                 cmp    al,' '     ; проверка возможного диапазона печати
                 jb     no_prnt    ; ? < памяти
                 cmp    al,7Eh     ; DEL невозможно напечатать, либо
                 ja     no_print
                 @DisChr al        ; возможно - выполнить так ...
                 jmp    nxt_txt
         no_prnt:
                 @DisChr '.'       ; используйте "." для невозможн.печати
         nxt_txt:
                 dec    cl         ; счетчик цикла - 1
                 jnz    t_dump     ; повторение, пока счетчик не станет 0
         ; Выполнение всех восстановлений и выход
                 @DisChr CR
                 @DisChr LF
                 pop    cx         ; восстановление регистров
                 pop    bx
                 pop    dx
                 pop    ax
                 ret
         dmsg1   db     'HEX: $'
         dmsg2   db     ' ASCII: $'
         dump    ENDP
         ;
         ; ===== GET_HEX осуществляет грамматический разбор буфера, =====
         ; ===== указанного в BX, возвращаемое количество в AX. =========
         ; ===== # цифр для грамматического разбора содержится в CH, ====
         ; ===== и BX увеличивается на # обработанных цифр. =============
         ;
         get_hex PROC   NEAR
                 push   dx         ; сохранение регистра DX
                 push   cx         ; сохранение регистра CX
                 mov    ax,0       ; очистка аккумулируемого #
                 mov    dh,0       ; очистка верхней рабочей памяти
                 mov    cl,4       ; установка сдвига счетчика
         nxt_digit:
                 mov    dl,[bx]    ; получение символа
                 sub    dl,'0'
                 jb     bad_digit  ; ? < '0' - неправильно
                 cmp    dl,0Ah
                 jb     ok_digit   ; от '0' до '9' - хорошо
                 sub    dl,'A'-'0'
                 jb     bad_digit  ; '9' < ? < 'A' - неправильно
                 add    dl,0Ah
                 cmp    dl,10h
                 jb     ok_digit   ; от 'A' до 'F' - хорошо
                 sub    dl,'a'-'A'-0Ah
                 jb     bad_digit  ; 'F' < ? < 'a' - неправильно
                 add    dl,0Ah
                 cmp    al,10h
                 jae    bad_digit  ; 'f' < ? - неправильно
         ok_digit:
                 add    ax,dx      ; аккумулирование цифр в AX
                 inc    bx         ; следующая цифра
                 dec    ch
                 jnz    more_digit ; еще цифры для аккумулирования?
                 clc               ; ошибки нет - очистка CY
                 pop    cx
                 pop    dx
                 ret
         more_digit:
                 shl    ax,cl      ; открытие места для следующей цифры
                 jmp    nxt_digit  ; цикл для следующей цифры
         bad_digit:
                 @DisStr digit_error ; информирование об ошибке элемента
                 stc               ; ошибка - установка переноса
                 pop    cx
                 pop    dx
                 ret
         ; ожидался двухцифровой шестнадцатиричный номер
         digit_error db 'A two-digit hex number was expected',CR,LF,'$'
         get_hex ENDP
         ;
         ; ===== BIN2HEX отображает значение, содержащееся в AX как =====
         ; ===== шестнадцатиричный #. Регистры не портятся. CH содержит =
         ; ===== # цифры для отображения, выбираемой слева направо в AX.=
         ; ===== (AH отображается, если CH равен 2). ====================
         ;
         bin2hex PROC   NEAR
                 push   ax         ; сохранение всех регистров
                 push   bx
                 push   cx
                 push   dx
                 mov    cl,4       ; установка счетчика чередования
                 mov    bx,ax      ; копирование AX для работы
         ; Начало цикла DIGIT (цифра) для обработки   цифр
         moredig:
                 rol    bx,cl      ; преобразование двоичн.-шестнадцат.
                 mov    al,bl
                 and    al,0Fh
                 add    al,90h
                 daa
                 adc    al,40h
                 daa
         ; Отображение цифры и проверка на последующие цифры - восста-
         ; новление, если нет
                 @DisChr al
                 dec    ch
                 jnz    moredig
                 pop    dx
                 pop    cx
                 pop    bx
                 pop    ax
                 ret
         bin2hex ENDP
         ;
         remove  ENDS
                 END    start
         ----------------------------------------------------------------

Эта секция, отображающая содержимое адресуемого размещения с помощью вектора, может быть выбрана и превращена в программу. Эта программа может быть использована для отображения содержимо- го любого вектора прерывания и его возможных подпрограмм обслу- живания.


Программа REMOVE служит примером для многих тем, обсужденных в этой главе, и помогает при демонстрации рекомендуемого инстру- ментария установки и удаления.


НАЗАД СОДЕРЖАНИЕ ВПЕРЁД

Hosted by uCoz