|
|
|
|
Доступ к резидентным подпрограммам через прерывания
В результате выполнения программы, показанной в листинге 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)
|
|
|