Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Различные авторы Весь текст 2311.07 Kb

Программирование и кодирование

Предыдущая страница Следующая страница
1 ... 56 57 58 59 60 61 62  63 64 65 66 67 68 69 ... 198
         Если версия некорректна,  то TSR должна осуществить выход с выда-
         чей соответствующего сообщения об ошибке.
             DOS записывает  номер  версии своей системы в глобальной пере-
         менной и делает доступным это значение через запрос к BIOS с функ-
         цией 30h. При выполнении этого запроса диспетчер int 21h не выпол-
         няет переключение стеков или изменение любых  глобальных  перемен-
         ных.  Хотя этот запрос всегда безопасен, правила хорошего тона при
         программировании требуют, чтобы этот запрос выдавался бы среди ко-
         дов, выполняющих в программе инициализацию. Пример определения но-
         мера версии  используемой  операционной  системы  показан  ниже  в
         листинге 4-18.

                         Листинг 4-18. Проверка версии DOS
         ----------------------------------------------------------------

          VersionID   EQU   0a03h         ; DOS 3.10 (заметим, что млад-
                                          ; шая часть номера в MCB)
                      mov   ah,30h        ; ah <== функция для проверки
                                          ; версии DOS
                      int   21h           ; выдача запроса
                      cmp ax,VersionID    ; версия  возвращается  в  ax
                      jnz WrongVersion    ; версия ошибочна
         ----------------------------------------------------------------

                       Размещение резидентных копий TSR

             Управление некоторыми действиями  DOS  и  работой  аппаратных
         средств предписывает использование входа IVT. TSR также использу-
         ет прерывания и входы IVT TSR для  размещения  резидентных  копий
         своих программ.  При этом может возникнуть необходимость размеще-
         ния в памяти нескольких копий резидентных программ TSR или  необ-
         ходимость  размещения данных,  записываемых с помощью резидентной
         программы.  Если при выполнении TSR выбирает некоторый вход  IVT,
         то  последовательность  выполняемых  программ активации размещает
         резидентную программу путем выполнения инструкции INT или провер-
         ки программного кода, указываемого входом IVT.
             Какой вход IVT следует выбрать?  Это,  прежде всего, определя-

                                      - 4-31 -
         ется тем,  что  выбор прерывания для размещения резидентной прог-
         раммы зависит от автора TSR.  Абсолютно простой механизм  отсутс-
         твует.
             DOS и аппаратные средства персонального компьютера используют
         только некоторые из имеющихся в распоряжении входов IVT. Теорети-
         чески можно выбрать любой неиспользуемый вход.  Если TSR действи-
         тельно выполняет инструкцию INT,  то вход IVT должен указывать на
         допустимую программу обработки прерывания (ISR). Однако, гарантия
         того,  что вход IVT ее содержит, если TSR не инициализировала ее,
         отсутствует.  Один  из путей выхода из этой  дилеммы  "Catch  22"
         ("Ловушка 22") состоит в проверке входа IVT.
             DOS загружает все программы на границу сегмента.  Если вектор
         прерывания  "захватила"  предыдущая копия программы,  то значение
         смещения (младшее слово) во входе IVT должно соответствовать сме-
         щению ISR в текущей программе.  Так как надежда на то,  что прог-
         раммы обработки прерываний (ISR) для двух различных  программ TSR
         используют  один  и  тот же вход IVT и имеют одинаковое смещение,
         довольно слабая, то необходимо выполнить некоторую дополнительную
         проверку. Пример этого приведен в листинге 4-19.
             В этом примере ищется строка ASCII UniqueID;  мы могли бы вы-
         полнить в программе ISR сравнение строк. Недостатком этого спосо-
         ба является то, что он не разрешает проблему "конфликтующих" пре-
         рываний. Если две программы TSR решили использовать один и тот же
         вход IVT,  то  практически  не существует способа определения то-
         го, какую TSR загружать первой.
             Начиная с версии 3.0 DOS,  фирма  "Майкрософт"  документирует
         многократные прерывания,  что является ее первой попыткой решения
         проблемы  "конфликтующих"  прерываний.  Многократные   прерывания
         обеспечивают  гарантируемые  правильные  входы  IVT для int 2Fh и
         протокол размещения программ TSR.  Начальные входы IVT этого пре-
         рывания int 2Fh указывают на инструкцию IRET. Каждая TSR, ожидаю-
         щая использования мультиплексируемого  прерывания,  сначала  ищет
         предыдущие загруженные копии своей программы,  а затем устанавли-
         вает свою собственную программу ISR прерывания int 2Fh.

                Листинг 4-19.  Размещение  TSR  путем использования
                     произвольно выбранного вектора прерывания
         ----------------------------------------------------------------

         NewISRVector  EQU  ??  ; заполнение номера вектора
         OldISRxx   DD  0       ; здесь программа сохраняет старый вектор
         UniqueID   DB 'уникальная строка' ;  для идентификации ISR
         IDLength      EQU $-UniqueID ; длина строки
         NewISRxx PROC FAR      ; устанавливается программой инициализации
         ;
         ;            ...           ; все, что выполняет ISR
         ;
                      iret
         NewISRxx     ENDP
         LocateISR    PROC  NEAR
                      mov al,NewISRVector ; al <== номер вектора
                      mov ah,35h        ; ah <== получение функции вектора
                                        ; прерывания
                      int 21h ;  запрос к DOS для вектора прерывания
                       ret    ;   es:bx имеет адрес ISR
         LocateISR    ENDP
         CheckISR     PROC  NEAR
                      cmp   bx,OFFSET NewISRxx ; существующее смещение

                                      - 4-32 -
                                    ; хорошее
                      jnz   done    ; если не 0 -- нет
                      mov si,OFFSET UniqueID ;  si <==  смещение  UniqueID
                      mov di,si              ; di <== смещение UniqueID
                      mov cx,IDLength     ;  cx <== длина идентификатора
                      cld
                      repnz  cmpsb  ; сравнение идентификаторов
         done:        ret           ; возврат :
                                    ; zr=1 ==> результат установлен
         CheckISR     ENDP     ;  zr=0 ==> результат не установлен

         TSRResdnt    PROC   NEAR ; определяет резидентная ли TSR
                      call LocateISR ;  получение адреса ISR
                      call CheckISR  ; проверяет идентификатор ID
                      ret            ; и возвращает:
                                     ; zr=1 ==> результат установлен
                                     ; zr=0 ==> результат не установлен
         TSRResdnt    ENDP
         ----------------------------------------------------------------

             TSR сама  осуществляет поиск резидентных копий путем загрузки
         уникального идентификатора в регистр AH,  нуля в регистр AL и вы-
         полнения инструкции int 2Fh. Программа ISR 2Fh проверяет значение
         в регистре AH. Если ISR распознает идентификатор, то она устанав-
         ливает AL=00fh и возвращает управление по инструкции IRET; в про-
         тивном случае она переходит к ранее сохраненной ISR  int  2Fh.  В
         конце концов,  либо будет достигнут конец этой цепочки,  либо ISR
         распознает значение в регистре AH.
             Снова возможны  конфликты.  Для их разрешения TSR должна выб-
         рать дополнительные проверки.  Для облегчения этой проверки можно
         расширить протокол прерывания int 2Fh,  но при этом следует иметь
         в виду, что стандарты на дополнительные проверки отсутствуют. Не-
         обходимо защищать программу. Один из возможных подходов иллюстри-
         рует листинг 4-20.
             Фактически, получение положительного ответа на запрос int 2Fh
         AL=0 означает,  что ответила некоторая TSR. ISR int 2Fh, показан-
         ная  в листинге,  отвечает на функцию AL=1 путем возврата ее сег-
         мента кодов в регистре ES. TSR, сделавшая начальный запрос, может
         использовать  это  значение  для  нахождения некоторой уникальной
         строки.  Если строки совпадают между собой, то можно быть уверен-
         ным, что найдена правильная ISR.
             Такое расширение протокола многократного прерывания не  явля-
         ется стандартным. Отсутствует гарантия того, что некоторая другая
         TSR будет выполняться в ответ на запрос int 2Fh  AL=1.  Обнуление
         регистра ES перед выполнением этого второго запроса позволяет, по
         крайней мере, знать, что ответившая TSR возвращает некоторое зна-
         чение  в  регистре ES.  (Вам конечно известно,  что TSR не должна
         загружаться в сегмент 0).

                 Листинг 4-20.  Размещение TSR путем использования
                           мультиплексируемых прерываний
         ----------------------------------------------------------------

         OurID EQU   81h       ;  TSR выбирает значение AH
         OldISR2f  LABEL  FAR  ;здесь  сохраняется старый вектор int 2Fh

         UniqueID    DB   'уникальная строка' ;для идентификации TSR

                                      - 4-33 -
         IDLength    EQU     $-UniqueID ; длина строки
         OldInt2f    DD      0       ; здесь программа инициализации запи-
                                     ; сывает начальный адрес ISR
         NewISR2f    PROC    FAR     ; новая ISR int 2Fh
                     cmp     ah,OurID  ; запрос для нас?
                     jz      ItsMe     ; если 0 -- для нас
                     jmp     cs:OldInt2f ; передача запроса
         ItsMe:      or      al,al      ; загрузка проверена?
                     jnz     GetAddress ; если не 0 -- нет
                     mov     al,0ffh    ; загружена
                     iret               ; возврат
         GetAddress:
                     cmp     al,1    ; проверен ли адрес?
                     jnz BadFunction ; если не 0 -- нет
                     push cs ; возврат сегмента в ES
                     pop es
                     iret
         BadFunction:  stc             ; индуцирует ошибку
                     iret
         NewISR2f    ENDP
         LocateISR   PROC    NEAR
                     mov ax,OurID SHL 8 ;  ожидание чего-либо?
                     int 2fh
                     cmp al,0ffh ;  проверка выдаваемого ответа
                     jnz NotFound ; не  0  ==> нет ответа
                     xor ax,ax ;  затирание сегмента
                     mov es,ax ; проверка выдаваемого ответа
                     mov ax,(OurID SHL  8) OR 1
                               ;  запрос сегмента
                     int 2fh
                     jc NotFound ;если cy=1,  то это не нам
                     xor ax,ax  ;  изменения  ES проводились?
                     mov bx,es ; если изменения ES не проводились
                     cmp bx,ax
                     jz  NotFound ; изменения ES не проводились
                     lea bx,NewISR2f ; ES:BX имеет адрес ISR
                     clc              ; индикация успешна
                     ret              ; возврат
         NotFound:   stc
                     ret
         LocateISR   ENDP
         TSRResdnt PROC  NEAR  ;  определяет  резидентная  ли   TSR
                     call LocateISR  ;  получает  адрес  TSR
                     jc  NotLoaded
                     call CheckISR ; проверяет идентификатор ID
                     ret              ; возврат
                                      ; zr=1 ==> установлена
Предыдущая страница Следующая страница
1 ... 56 57 58 59 60 61 62  63 64 65 66 67 68 69 ... 198
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама