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










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

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

Доступ к резидентным подпрограммам через прерывания

В результате выполнения программы, показанной в листинге 3-4, в памяти системы будет установлена резидентная программа. После размещения необязательно вся программа должна находиться в памяти. Для включения этой программы в RTL необходимо передавать ей намерение и сделать ее доступной для других программ.


RTL может содержать любую функцию и сделать любой вызов MS-DOS (например, прерывание int 21h), пока библиотека вызывается только текущей выполняющейся программой. Это ограничение предназначено для предотвращения неумышленного повторного вызова MS-DOS, который приведет к сбою системы. Следующая программа, показанная в листинге 3-5, содержит пример интерфейса для RTL, который может поддерживать много отдельных функций и очень похож на обработчик прерывания MS-DOS int 21h.


Как показано в листинге 3-5, этот пример структуры может быть расширен путем добавления необходимого программного кода для поддержки подпрограмм сравнения, получения справок о таблицах, преобразования ввода-вывода, или, даже, общей области для нескольких программ. Мы попытались включить некоторые примеры технических приемов, рассмотренных в главе 2, такие как использование параметров стека, отчеты об ошибках и т.д. Если эта подпрограмма используется для поддержки большого количества функций, то можно заменить модель макроса таблицей переходов, как демонстрируется в драйвере дискового запоминающего устройства с произвольной выборкой RDISK в главе 6.


Библиотека MACRO, упоминаемая в программе EXRTL, содержит модель макроса, введенного в главе 1, а также макросы dis_chr отобразить символ) и dis_str (отобразить строку), представленные в документе "Technical Reference Manual. @DosCall" (Справочное руководство по техническому обслуживанию. Вызовы DOS), и, конечно же, макрос для прерывания int 21h.



                        Листинг 3-5. Пример установки  RTL
                 (подпрограмма  EXRTL - Example Run-Time Library)
         ----------------------------------------------------------------

         ;====== RTL.ASM - этот файл вырабатывает файл типа .COM ======
         V_NUM   EQU     40h            ; эта RTL использует вектор 40h
         ;
         INCLUDE STDMAC.INC             ; включение файла макробиблиотеки
         ;====== СЕКЦИЯ ПРОГРАММНОГО КОДА ==============================
         ;
         frame   STRUC      ; схема структуры стека вызывающей программы
         old_bp  dw      ?              ; запомненный указатель базы
         ret_IP  dw      ?              ; адрес возврата (IP)
         ret_CS  dw      ?              ; адрес возврата (CS)
         flags   dw      ?              ; флажки вызывающей программы
         funct   dw      ?              ; номер выполняемой функции
         frame   ENDS
         ;
         code_seg SEGMENT
                 ASSUME cs:code_seg
                 ASSUME ds:code_seg
         main    PROC    FAR
                 ORG     0
         seg_org EQU     $
                 ORG     2Ch
         env_adr LABEL   WORD           ; смещение среды в PSP
                 ORG     0100h
         start:  jmp     install
         entry:  push    bp             ; сохранение указателя базы
                 mov     bp,sp          ; получение адреса стека
                 push    ds             ; сохранение сегмента данных
                 push    ax             ; сохранение регистра
                 push    bx
                 mov     ax,cs          ; установка сегмента данных
                 mov     ds,ax
                 mov     ax,[bp].flags  ; передача флажков вызывающ.пр-мы
                 sahf                   ; в AX и в мои флажки
                 clc                    ; очистка переноса (нет ошибки)
                 pushf                  ; и сохранение копии флажков
                 mov     bx,[bp].funct  ; получение кода функции
                 @Case   bl,<1,2>,
                 popf                   ; получение копии флажков
                 stc                    ; установка переноса-непр.функция
                 pushf                  ; сохранение копии флажков
                 jmp     short exit
         f1:     @DisStr f1msg
                 jmp     short exit
         f2:     @DisStr f2msg
         exit:   pop     ax             ; отсылка флажков обратно в стек
                 mov     [bp].flags,ax  ;           через AX
                 pop     bx             ; восстановление регистров
                 pop     ax
                 pop     ds             ; восстановление сегмента данных
                 pop     bp             ; восстановление указателя базы
                 iret                   ; возврат из прерывания
         main    ENDP
         ;
         f1msg   db      'Function # 1 performed',CR,LF,'$'
         f2msg   db      'Function # 2 performed',CR,LF,'$'
         lst_byt:                       ; последний байт для сохранения
         ;
         ; Это программа установки.
         ;
         ; Для объяснения причин удаления блока среды смотри раздел
         ; "Биты управления памятью"
         ;
         ; Удаление блока среды - DS указывает на текущий сегмент
         ; Установка ES для указания на блок среды
         ;
         install:
                 mov     es,env_adr     ; получение адреса среды
                 mov     ah,49h      ; освобождение распределенной памяти
                 @DosCall               ; вызов MS-DOS
                 jnc     setvect        ; переход, если ошибки нет
                 @DisStr fail49         ; информация об ошибке
                 mov     ah,4Ch         ; завершение процесса
                 @DosCall               ; аварийное завершение при ошибке
         ;
         ; Установка вектора - DS указывает на текущий сегмент
         setvect:
                 mov     dx,offset entry ; получение точки входа RTL
                 mov     al,V_NUM       ; установка номера вектора
                 mov     ah,25h         ; установка вектора
                 @DosCall               ; вызов MS-DOS
         ;
         ; Завершение и оставление в памяти резидентной подпрограммы
                 mov     dx,(offset lst_byt - seg_org + 15) shr 4
                 mov     ah,31h         ; сохранить процесс
                 @DosCall               ; вызов MS-DOS
         ;
         fail49  db      'Failed to Free Environment Block',CR,LF'$'
         code_seg ENDS
                 END     start
         ----------------------------------------------------------------

Особенность подпрограммы EXRTL состоит в том, что при выполнении функции Keep Process ("сохранить процесс") отсутствует память для локального стека. Это должно было бы привести к фатальной ошибке программы EXRTL, потому что программный стек станет полностью незащищенным и субъектом разрушения. Однако, этого не происходит, потому что подпрограмма EXRTL не является автономной программой, а вызывается другими программами, которые имеют свои локальные стеки. Подпрограмма EXRTL выполняет все свои операции, используя стек вызывающей программы.


После написания RTL, необходимо обеспечить некоторые средства ее использования. В связи с тем, что в процессе работы невозможно определить, где MS-DOS загрузит процедуру в памяти, нельзя вызывать библиотеку по инструкции CALL из программы, желающей осуществить доступ к RTL. Для этого семейство микропроцессоров 8086 предоставляет одно решение в форме векторов прерываний. При установке вектора прерывания в точке адресации библиотеки любая программа может осуществить к ней доступ путем использования инструкции INT.


Семейство микропроцессоров 8086 поддерживает 256 векторов прерываний, из которых, по крайней мере, 64 (от 00h до 39h) резервируются для аппаратуры системы или MS-DOS. Частичный список векторов прерываний, используемых фирмой "Интел", стандартами фирмы "ИБМ", базовой системой ввода-вывода (BIOS - Basic Input Output System) фирмы "ИБМ" и MS-DOS приведен в таблице 3-5. Остальные векторы прерываний используются другими изготовителями. Обычно векторы с более высокими номерами являются более надежными для использования, хотя это можно подтвердить только тестированием. В нашем случае выбран вектор 40h, потому что при его использовании система не разрушается.


           ____________________________________________________________
          |                                                            |
          |                      ПРЕДОСТЕРЕЖЕНИЕ                       |
          |                                                            |
          |    Многие системы могут использовать векторы прерываний,   |
          |    отличающиеся от определенных  для  MS-DOS.  Перед ис-   |
          |    пользованием  любого  вектора  проверьте  Руководство   |
          |    системы.  В  результате  изменения  уже используемого   |
          |        вектора может произойти полный отказ системы !      |
          |____________________________________________________________|


                                                         Таблица 3-5
              Векторы прерываний стандартов фирмы "ИБМ", процессора,
                         аппаратных средств, BIOS и MS-DOS
         ________________________________________________________________
                       |            |
           Прерывание  | Определено |            Использование
         (шестн.знач.) |            |
         ______________|____________|____________________________________
         Int 0         |   Интел    | Прерывание из-за ошибки деления на
                       |            | нуль
         Int 1         |   Интел    | Прерывание "прослеживания" одного
                       |            | шага
         Int 2         |   Интел    | Немаскируемое прерывание аппаратных
                       |            | средств
         Int 3         |   Интел    | Прерывание контрольной точки
         Int 4         |   Интел    | Прерывание из-за переполнения при
                       |            | умножении
         Int 5         |   Интел    | Исключительная ситуация "граница
                       |            | 80x86"
                       |   BIOS     | Функция печати экрана
         Int 6         |   Интел    | Исключительная ситуация "неопреде-
                       |            | ленный код операции"
         Int 7         |   Интел    | Исключительная ситуация "код опера-
                       |            | ции ESC"
         Int 8 / IRQ 0 |   ИБМ      | Аппаратные средства системного тай-
                       |            | мера
         Int 9 / IRQ 1 |   ИБМ      | Аппаратные средства клавиатуры
         Int A / IRQ 2 |   ИБМ - XT | Запасной запрос аппаратных средств
         Int A / IRQ 2 |   ИБМ - AT | IRQ 8 - IRQ F
         Int B / IRQ 3 |   ИБМ      | Аппаратные средства последователь-
                       |            | ного порта 2
         Int C / IRQ 4 |   ИБМ      | Аппаратные средства последователь-
                       |            | ного порта 1
         Int D / IRQ 5 |   ИБМ - XT | Аппаратные средства фиксированного
                       |            | диска
         Int D / IRQ 5 |   ИБМ - AT | Параллельный порт 2
         Int E / IRQ 6 |   ИБМ      | Аппаратные средства дискового конт-
                       |            | роллера
         Int F / IRQ 7 |   ИБМ      | Аппаратные средства параллельного
                       |            | порта 1
         Int 10        |   BIOS     | Обслуживание видео и экрана
         Int 11        |   BIOS     | Список аппаратуры считывания
         Int 12        |   BIOS     | Размер отчета памяти
         Int 13        |   BIOS     | Обслуживание дискового ввода-вывода
         Int 14        |   BIOS     | Обслуживание последовательного
                       |            | ввода-вывода
         Int 15        |   BIOS     | Обслуживание кассетной ленты и
                       |            | расширенное обслуживание
         Int 16        |   BIOS     | Обслуживание ввода-вывода клавиату-
                       |            | ры
         Int 17        |   BIOS     | Обслуживание ввода-вывода принтера
         Int 18        |   BIOS     | Загрузчик Бэйсика
         Int 19        |   BIOS     | Программа начальной загрузки (на-
                       |            | чальный загрузчик)
         Int 1A        |   BIOS     | Обслуживание системного таймера и
                       |            | часов
         Int 1B        |   BIOS     | Клавиши Control-Break клавиатуры
                       |            | (из Int 9)
         Int 1C        |   BIOS     | Часы таймера пользователя
                       |            | (из Int 08)
         Int 1D - 1F   |   Интел    | Зарезервировано
         Int 20        |   MS-DOS   | Функция завершения старой (OLD)
                       |            | программы
         Int 21        |   MS-DOS   | Вызов функции MS-DOS
         Int 22        |   MS-DOS   | Адрес завершения программы
         Int 23        |   MS-DOS   | Адрес выхода Control-C
         Int 24        |   MS-DOS   | Адрес аварийного завершения из-за
                       |            | фатальной ошибки
         Int 25        |   MS-DOS   | Функция чтения по абсолютному ад-
                       |            | ресу на диске
         Int 26        |   MS-DOS   | Функция записи по абсолютному ад-
                       |            | ресу на диске
         Int 27        |   MS-DOS   | Функция "завершить и оставить
                       |            | резидентной"
         Int 28        |   MS-DOS   | Цикл клавиатуры/Простой DOS (заре-
                       |            | зервировано)
         Int 29        |   MS-DOS   | Быстрый вывод консоли (зарезервиро-
                       |            | но)
         Int 2A        |   MS-DOS   | Интерфейс MS-NET (зарезервировано)
         Int 2B - 2D   |   MS-DOS   | Зарезервировано для MS-DOS (IRET)
         Int 2E        |   MS-DOS   | Команда "выполнить" (зарезервиро-
                       |            | вано)
         Int 2F        |   MS-DOS   | Управление принтером MS-DOS вер-
                       |            | сии 3
         Int 30 - 3E   |   MS-DOS   | Зарезервировано для MS-DOS
         Int 3F        |   MS-DOS   | Управление оверлейным компоновщи-
                       |            | ком
         Int 4A        |   BIOS     | Часы реального времени (от int 70)
         Int 67        |   EMS 4.0  | Спецификация расширяемой памяти
         *Int 70/IRQ 8 |   ИБМ      | Аппаратные средства часов реального
                       |            | времени
         *Int 71/IRQ 9 |   ИБМ      | Прерывания аппаратных средств IRQ 2
         *Int 72/IRQ A |   ИБМ      | Зарезервированные аппаратные
                       |            | средства
         *Int 73/IRQ B |   ИБМ      | Зарезервированные аппаратные
                       |            | средства
         *Int 74/IRQ C |   ИБМ      | Зарезервированные аппаратные
                       |            | средства
         *Int 75/IRQ D |   ИБМ      | Аппаратные средства сопроцессора
         *Int 76/IRQ E |   ИБМ      | Аппаратные средства фиксированного
                       |            | диска
         *Int 77/IRQ F |   ИБМ      | Зарезервированные аппаратные
                       |            | средства
         ______________|____________|____________________________________
         * - только шины типа AT

В MS-DOS векторы прерывания могут быть установлены посредством использования функции MS-DOS с кодом 25h "Установить вектор прерывания". Операция установки очень проста: в регистр AL заносится номер вектора, а адрес для загрузки в вектор заносится в пару регистров DS:DX (сегмент:смещение). В связи с тем, что в программах типа .COM регистр DS устанавливается в то же самое значение, что и регистр CS, содержимое регистра DS уже является правильным для вызова. Затем загружаются оставшиеся регистры и делается вызов с помощью следующего программного кода:



             mov       dx,offset entry    ; получение точки входа RTL
             mov       al,v_num           ; установка номера вектора
             mov       ah,25h             ; установка вектора прерывания
             doscall                      ; вызов MS-DOS

После того, как подпрограмма EXRTL установлена в памяти и осуществляет доступ к вектору прерывания, установленному в таблице векторов прерываний, RTL готова для использования. Для ее вызова подпрограмма использует инструкцию 40h и управление передается к подпрограмме EXRTL. Программа RTL_TEST, показанная в листинге 3-6, является одним из примеров подпрограммы, осуществляющей доступ к этой отдельной RTL.


Интерфейс между подпрограммами EXRTL и RTL_TEST полностью обеспечивается через стек. Подпрограмма RTL_TEST помещает в стек код функции и выполняет инструкцию int 40h. Заметим, что схема стека в RTL отличается от такого интерфейса в инструкции CALL (вызов), в котором прерывание помещает флажки в стек, а также сегмент возврата и смещение.


Передача управления между двумя секциями показана на Рис.3-12. Инструкция int 40h передает управление через таблицу векторов прерываний в подпрограмму EXRTL. Затем подпрограмма EXRTL выбирает код функции из стека, используя блок описания структуры стека. Подпрограмма EXRTL анализирует правильность кода функции и, если он правилен, передает управление к соответствующему драйверу функции путем использования макроса case. После выполнения функции подпрограмма EXRTL возвращает управление в подпрограмму RTL_TEST по инструкции IRET (Return from Interrupt - возврат из прерывания).


Стековая структура frame (смотри листинг 3-5) также обеспечивает подпрограмме EXRTL доступ к флажкам вызывающей программы, которые хранятся в стеке рядом с вектором. Путем копирования флажков из стека в свой собственный регистр флажков подпрограмма EXRTL может изменить значение бита переноса; затем, перед выходом, она может скопировать флажки обратно в стек (включая новое значение флажка переноса). Эти операции позволяют подпрограмме EXRTL использовать флажок переноса для сигнализации условий ошибки для вызывающей программы, используя инструкцию IRET для восстановления флажков из стека.



                     Листинг 3-6. Выполнение программы для RTL
         ----------------------------------------------------------------
         ;====== RTL_TEST.ASM - Этот файл вырабатывает .COM файл ========
         V_NUM   EQU     40h          ; эта RTL использует вектор 40h
         INCLUDE STDMAC.INC           ; включение файла макробиблиотеки
         ;====== СЕКЦИЯ ПРОГРАММНОГО КОДА ===============================
         code_seg SEGMENT
                 ASSUME cs:code_seg
                 ASSUME ds:code_seg
         main    PROC    FAR
                 ORG     0100h
         start:  mov     cx,3         ; начало при неправильном значении
         loop:   push    cx           ; код функции
                 int     V_NUM        ; вызов RTL
                 pop     cx           ; очистка параметра возврата
                 jnc     nxt          ; переход, если ошибки нет
                 @DisStr caserr       ; показать ошибку
         nxt:    dec     cx
                 jge     loop         ; цикл через 0
                 mov     ah,4Ch       ; завершение процесса
                 @DosCall
         caserr  db      'Case Error - Illegal Function Code',CR,LF,'$'
         main    ENDP
         code_seg ENDS
                 END     start

Последний вопрос, насколько полно может использовать подпрограмма EXRTL операционную систему MS-DOS, когда получает управление непосредственно из другой программы? В некоторых других резидентных программах, представленных в следующих разделах этой книги, это происходит не так. Эти программы получают управление через прерывания аппаратных средств или прерывания MS-DOS.



                    Адрес   .----------------------.
                            |/\/\/\/\/\/\/\/\/\/\/\| Таблица векторов
                             /\/\/\/\/\/\/\/\/\/\/\  семейства микро-
                            |                      | процессора 8086
                            |----------------------|<---------------.
                   0000:0100|     IP или CS RTL    |--------------. |
                            |----------------------|              | |
                             \/\/\/\/\/\/\/\/\/\/\/               | |
                            |\/\/\/\/\/\/\/\/\/\/\/|              | |
                            |----------------------|<-------------  |
                            |     Элемент RTL      | Установленная  |
                             \/\/\/\/\/\/\/\/\/\/\/       RTL       |
                            |\/\/\/\/\/\/\/\/\/\/\/|                |
                 .----------|         IRET         |                |
                 |          |----------------------|                |
                 |           \/\/\/\/\/\/\/\/\/\/\/                 |
                 |          |\/\/\/\/\/\/\/\/\/\/\/| Программа      |
                 |          |----------------------|пользователя    |
                 |          |/\/\/\/\/\/\/\/\/\/\/\|                |
                 |           /\/\/\/\/\/\/\/\/\/\/\                 |
                  --------->|       Int 40h        |----------------
                            |/\/\/\/\/\/\/\/\/\/\/\|
                             /\/\/\/\/\/\/\/\/\/\/\
                            |----------------------|
                            |/\/\/\/\/\/\/\/\/\/\/\|
                             /\/\/\/\/\/\/\/\/\/\/\
                            |                      |
                             ----------------------

             Рис. 3-12. Доступ к библиотеке исполняющей системы (RTL)

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

Hosted by uCoz