Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Защищенный режим процессоров Intel 80286/80386/80486

© Александр Фролов, Григорий Фролов
Том 4, М.: Диалог-МИФИ, 1993, 234 стр.

[Назад] [Содеожание] [Дальше]

7.2. Драйверы, резидентные программы и WINDOWS

В этом разделе, как и в следующем, мы не будем ничего говорить о защищённом режиме работы процессора. Мы рассмотрим здесь некоторые особенности, которые необходимо учитывать при разработке резидентных программ и драйверов, работающих совместно с WINDOWS.

Очень часто резидентные программы или драйверы перехватывают аппаратное прерывание клавиатуры и отслеживают коды нажимаемых клавиш, выполняя те или иные действия при нажатии заданных комбинаций. Например, драйвер "секретного" диска Norton DISKREET может при нажатии заданной комбинации клавиш блокировать доступ к "секретному" диску, экрану и клавиатуре.

Так как WINDOWS в расширенном режиме использует собственную систему клавиатурного ввода/вывода, основанную на очередях сообщений, а также реализует концепцию виртуальных машин, нажатие активизирующих резидентную программу комбинаций клавиш в неподходящий момент может не привести к желаемому результату и даже стать причиной "зависания" системы.

Есть два возможных решения этой проблемы. Во-первых, можно запретить запуск WINDOWS, если активна резидентная программа или драйвер, не способные работать совместно с WINDOWS. Во-вторых, на время работы WINDOWS можно запретить выполнение резидентной программой или драйвером специфических функций, несовместимых с WINDOWS (например, запретить активизацию резидентной программы при нажатии комбинации клавиш).

Перед запуском WINDOWS и перед её завершением вызываются функции прерывания INT 2Fh 1605h и 1606h соответственно. Ваша резидентная программа или драйвер могут подготовить собственные обработчики для этих прерываний и отслеживать моменты запуска WINDOWS и завершения её работы.

Функция 1605h вызывается при запуске WINDOWS:

Регистры при вызове прерывания:

AX      1605h
ES:BX   0000h:0000h
DS:SI   0000h:0000h
CX      0000h
DX      Флаги:
    Бит 0 = 0, если выполняется инициализация WINDOWS в расширенном режиме;
    Бит 0 = 1, если выполняется инициализация DOS-экстендера 
	"Microsoft 286 DOS extender" (используется в 
	стандартном режиме работы WINDOWS);
    Биты 1-15 зарезервированы, их содержимое неопределено.




Регистры перед возвратом из прерывания:

CX      0000h, если WINDOWS может продолжать инициализацию;
CX <> 0, если запуск WINDOWS недопустим.




Функция 1606h вызывается при завершении WINDOWS расширенном или стандартном режиме:

Регистры при вызове прерывания:

AX      1606h
DX      Флаги:
    Бит 0 = 0, если выполняется завершение WINDOWS, работавшей в расширенном режиме;
    Бит 0 = 1, если выполняется завершение DOS-экстендера 
	"Microsoft 286 DOS extender";
    Биты 1-15 зарезервированы, их содержимое не определено.




Обработчик функции 1605h может выполнить необходимые действия, связанные с модификацией алгоритма работы резидентной программы или драйвера, а также при помощи соответствующей установки регистра CX может разрешить или запретить запуск WINDOWS.

Обработчик функции 1606h получает управление при завершении работы WINDOWS и может восстановить прежний алгоритм работы критичной к WINDOWS резидентной программы или драйвера.

Приведённая ниже резидентная программа перехватывает прерывание INT 2Fh и отслеживает фунции 1605h и 1606h, вызавая сообщение и ожидая нажатия на любую клавишу при запуске и завершении работы WINDOWS:

Листинг 22. Контроль запуска WINDOWS
Файл wintsr.asm
-----------------------------------------------------------


.MODEL tiny
        .CODE
        .STARTUP
 
        jmp begin


old_int2Fh_off  dw 0  ; Адрес старого обработчика
old_int2Fh_seg  dw 0  ; прерывания 2Fh

; Сообщение, которое будет выдано на экран
; при запуске WINDOWS

msg_win     db 'WINDOWS Started. Press any key...$'
msg_win_off dw offset msg_win

; Сообщение, которое будет выдано на экран
; при завершении WINDOWS

msg_win1     db 'WINDOWS Ended. Press any key...$'
msg_winend_off dw offset msg_win1

; Новый обработчик прерывания 2Fh нужен
; для проверки наличия программы в памяти
; при ее запуске для предохранения
; от повторного запуска

new_int2Fh  proc  far
                cmp   ax,0FF00h
                jz    installed

                cmp   ax,1605h
                jz    winstart

                cmp   ax,1606h
                jz    winend
                jmp   dword ptr cs:old_int2Fh_off

winstart:       ; запуск WINDOWS

                push ax
                push bx
                push cx
                push dx
                push ds

                mov   dx,cs:msg_win_off
                mov   ah,9
                push  cs
                pop   ds
                int   21h

                mov   ax,0
                int   16h

                pop ds
                pop dx
                pop cx
                pop bx
                pop ax

                jmp   dword ptr cs:old_int2Fh_off

winend:         ; завершение WINDOWS

                push ax
                push bx
                push cx
                push dx
                push ds

                mov   dx,cs:msg_winend_off
                mov   ah,9
                push  cs
                pop   ds
                int   21h

                mov   ax,0
                int   16h

                pop ds
                pop dx
                pop cx
                pop bx
                pop ax

                jmp   dword ptr cs:old_int2Fh_off


; Если код функции 0FF00h, то возвращаем
; в регистре AX значение 00FFh. Это признак
; того, что программа уже загружена в память

installed:
                mov   ax,00FFh
                iret

new_int2Fh  endp

;==============================

; Точка входа в программу
; В этом месте начинается выполнение программы

begin proc

; Проверяем, не загружена ли уже программа
; в память

                mov   ax,0FF00h
                int   2Fh

                cmp   ax,00FFh
                jne   first_start

                mov   dx,offset msg_load1
                mov   ah,9
                int   21h

                .EXIT

; Первоначальный запуск программы

first_start:

; Запоминаем адрес старого обработчика прерывания 2Fh

                mov   ax,352Fh
                int   21h
                mov   cs:old_int2Fh_off,bx
                mov   cs:old_int2Fh_seg,es

                push  cs
                pop     ds

; Выводим сообщение

                mov   dx,offset msg_load
                mov     ah,9
                int   21h


                mov   dx,OFFSET new_int2Fh
                mov   ax,252Fh
                int   21h

; Завершаем программу и оставляем резидентно
; в памяти часть программы, содержащую новые
; обработчики прерываний

                mov   dx,OFFSET begin
                int   27h

begin endp

msg_load      db 'Резидентная программа WINTSR загружена$'
msg_load1     db 'Резидентная программа WINTSR уже загружена$'

                end




Следующая резидентная программа работает аналогично, но она запрещает запуск WINDOWS. Попробуйте, запустив предварительно программу NOWINTSR, запустить WINDOWS и посмотрите, что из этого получится.

Листинг 23. Запрет запуска WINDOWS
Файл nowintsr.asm
-----------------------------------------------------------


                .MODEL tiny
                .CODE
                .STARTUP
  
                jmp begin


old_int2Fh_off  dw 0  ; Адрес старого обработчика
old_int2Fh_seg  dw 0  ; прерывания 2Fh

; Сообщение, которое выдаётся при запуске WINDOWS

msg_win db 'NOWINTSR несовместима с WINDOWS. Нажмите любую клавишу...$'
msg_win_off dw offset msg_win

; Сообщение, которое выдаётся при завершении WINDOWS

msg_win1     db 10,13,'WINDOWS Ended. Press any key...$'
msg_winend_off dw offset msg_win1

; Новый обработчик прерывания 2Fh нужен
; для проверки наличия программы в памяти
; при ее запуске для предохранения
; от повторного запуска

new_int2Fh  proc  far
                cmp   ax,0FF00h
                jz    installed

                cmp   ax,1605h
                jz    winstart

                cmp   ax,1606h
                jz    winend
                jmp   dword ptr cs:old_int2Fh_off

winstart:

                push ax
                push bx
                push cx
                push dx
                push ds

                mov   dx,cs:msg_win_off
                mov   ah,9
                push  cs
                pop   ds
                int   21h

                mov   ax,0
                int   16h

                pop ds
                pop dx
                pop cx
                pop bx
                pop ax

                mov  cx,0ffh
                jmp   dword ptr cs:old_int2Fh_off

winend:

                push ax
                push bx
                push cx
                push dx
                push ds

                mov   dx,cs:msg_winend_off
                mov   ah,9
                push  cs
                pop   ds
                int   21h

                mov   ax,0
                int   16h

                pop ds
                pop dx
                pop cx
                pop bx
                pop ax

                jmp   dword ptr cs:old_int2Fh_off


; Если код функции 0FF00h, то возвращаем
; в регистре AX значение 00FFh. Это признак
; того, что программа уже загружена в память

installed:
                mov   ax,00FFh
                iret

new_int2Fh  endp

;==============================

; Точка входа в программу

begin proc

; Проверяем, не загружена ли уже программа
; в память

                mov   ax,0FF00h
                int   2Fh

                cmp   ax,00FFh
                jne   first_start

                mov   dx,offset msg_load1
                mov   ah,9
                int   21h

                .EXIT

; Первоначальный запуск программы

first_start:

; Запоминаем адрес старого обработчика прерывания 2Fh

                mov   ax,352Fh
                int   21h
                mov   cs:old_int2Fh_off,bx
                mov   cs:old_int2Fh_seg,es

                push  cs
                pop     ds

; Выводим сообщение

                mov   dx,offset msg_load
                mov     ah,9
                int   21h


                mov   dx,OFFSET new_int2Fh
                mov   ax,252Fh
                int   21h

; Завершаем программу и оставляем резидентно
; в памяти часть программы, содержащую новые
; обработчики прерываний

                mov   dx,OFFSET begin
                int   27h

begin endp

msg_load      db 'Резидентная программа NOWINTSR загружена$'
msg_load1     db 'Резидентная программа NOWINTSR уже загружена$'

                end



[Назад] [Содеожание] [Дальше]