|
Мы попытались включить некоторые примеры технических
приемов, рассмотренных в главе 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 ; очистка переноса (нет ошибки)
- 3-36 -
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
----------------------------------------------------------------
- 3-37 -
Особенность подпрограммы EXRTL состоит в том, что при выпол-
нении функции Keep Process ("сохранить процесс") отсутствует па-
мять для локального стека. Это должно было бы привести к фаталь-
ной ошибке программы EXRTL, потому что программный стек станет
полностью незащищенным и субъектом разрушения. Однако, этого не
происходит, потому что подпрограмма EXRTL не является автономной
программой, а вызывается другими программами, которые имеют свои
локальные стеки. Подпрограмма EXRTL выполняет все свои операции,
используя стек вызывающей программы.
После написания RTL, необходимо обеспечить некоторые средства
ее использования. В связи с тем, что в процессе работы невозможно
определить, где MS-DOS загрузит процедуру в памяти, нельзя вызы-
вать библиотеку по инструкции CALL из программы, желающей осу-
ществить доступ к RTL. Для этого семейство микропроцессоров 8086
предоставляет одно решение в форме векторов прерываний.
|