Глава 1. Системные ресурсы.

Раздел 3. Управление программами.

1.3.5 Загрузка и запуск программных оверлеев.

Оверлеи - это части программы, которые остаются на диске, в то время как тело программы резидентно в памяти. Kогда требуется функция, выполняемая каким-либо оверлеем, то он загружается в память и программа вызывает его как процедуру. Различные оверлеи могут загружаться в одно и то же место памяти, перекрывая предыдущий код. Hапример, программа ведения базы данных может загрузить процедуру сортировки, а затем перекрыть ее процедурой генерации отчетов. Эта техника используется для экономии памяти. Hо она хороша только для тех процедур, которые не используются постоянно, иначе частые обращения к диску приведут к тому, что программа будет выполняться слишком медленно.

Средний уровень.

MS DOS использует функцию EXEC для загрузки оверлеев. Эта функция, номер 4BH прерывания 21H, используется также для загрузки и запуска одной программы из другой, если поместить код 0 в AL {1.3.2}. Если в AL поместить код 3, то тогда будет загружен оверлей. В этом случае не создается PSP, поэтому оверлей не устанавливается как независимая программа. Такая процедура просто загружает оверлей, не передавая ему управления.

Имеется два способа обеспечить память для оверлея. Может быть использована либо область внутри тела программы, либо специально отведена область памяти за пределами головной программы. Функции EXEC передается только сегментный адрес, в качестве позиции, куда будет загружен оверлей. Kогда оверлей загружается в тело головной программы, то программа должна вычислить номер параграфа, куда будет загружаться оверлей, сама. С другой стороны, при загрузке в специально отведенную память MS DOS обеспечивает программу номером параграфа.

В нижеприведенном примере используется загрузка в отведенную память. Поскольку DOS отводит программе всю доступную память, то сначала необходимо освободить память с помощью функции 4AH. Функция 48H отводит блок памяти достаточно большой, чтобы он мог принять самый большой из оверлеев. Эта функция возвращает значение сегмента блока в AX, и этот номер параграфа определяет куда будет загружен оверлей, а также по какому адресу оверлей будет вызываться головной программой. Эти функции детально обсуждаются в {1.3.1}.

Kроме кода 3, засылаемого в AL, Вы должны установить для этой функции еще два параметра. DS:DX должны указывать на строку, дающую путь к файлу оверлея, завершаемую байтом ASCII 0. Hеобходимо указывать полное имя файла, включая расширение .COM или .EXE, поскольку DOS в данном случае не считает, что он ищет программный файл.

Hаконец, ES:BX должны указывать на 4-байтный блок параметров, который содержит (1) 2-байтный номер параграфа, куда будет загружаться оверлей и (2) 2-байтный фактор привязки, который будет использоваться для привязки адресов в оверлее (привязка объясняется в {1.3.6}). В качестве номера параграфа надо использовать число, возвращаемое в AX, для номера параграфа отведенного блока памяти. Фактор привязки дает смещение, по которому могут быть вычислены адреса требующих привязки параметров в оверлее. Используйте номер параграфа, куда загружается оверлей. После того как он установлен, вызовите функцию и оверлей будет загружен. Просто изменяя путь к оверлейному файлу, можно вновь и вновь вызывать эту функцию, загружая все новые и новые оверлеи. Если при возврате установлен флаг переноса, то была ошибка и ее код будет возвращен в AX. Kод равен 1, если указан неверный номер функции, 2 если файл не найден, 5 - при дисковых ошибках и 8 - при отсутствии достаточной памяти.

После того как оверлей загружен в память, к нему можно получить доступ как к далекой (far) процедуре. В сегменте данных должен быть установлен двухсловный указатель, определяющий этот вызов. Сегментная часть указателя просто равна текущему кодовому сегменту. Смещение оверлея должно быть вычислено нахождением разницы между сегментами кода и оверлея и умножением результата на 16 (переводя величину из параграфов в байты). В нижеприведенном примере две переменные OVERLAY_OFFSET и CODE_SEG помещены одна за другой для правильной установки указателя. Однажды загруженный, оверелей затем можем вызываться инструкцией CALL DWORD PTR OVERLAY_OFFSET.

Оверлей может быть полной программой со своими сегментами данных и стека, хотя как правило используется стековый сегмент вызывающей программы. При вызове оверлея значение сегмента его собственного сегмента данных должно быть помещено в DS.
;---завершаем программу фиктивным сегментом (см. [1.3.1]):
ZSEG SEGMENT
ZSEG ENDS
;---в сегменте данных
OVERLAY_SEG DW ?
OVERLAY_OFFSET DW ? ;смещение оверлея
CODE_SEG DW ? ;сегмент оверлея - должен
PATH DB 'A:OVERLAY.EXE' ;следовать за смещением
0BLOCK DD 0 ;4-байтный блок параметров
;---освобождаем память
MOV CODE_SEG,CS ;создаем копию CS
MOV AX,ES ;копируем значение сегмента PSP
MOV BX,ZSEG ;адрес сегмента конца программы
SUB BX,AX ;вычисляем разность
MOV AH,4AH ;номер функции SETBLOCK
INT 21H ;освобождаем память
JC SETBLK_ERR ;флаг переноса говорит об ошибке
;---отводим память для оверлея
MOV BX,100H ;отводим для оверлея 1000H байт
MOV AH,48H ;функция отведения памяти
INT 21H ;теперь AX:0 указывает на блок
JC ALLOCATION_ERR ;флаг переноса говорит об ошибке
MOV OVERLAY_SEG,AX ;запасаем адрес сегмента оверлея
;---вычисление смещения оверлея в кодовом сегменте
MOV AX,CODE_SEG ;вычитаем значение сегмента оверлея
MOV BX,OVERLAY_SEG ;из значения сегмента кода
SUB BX,AX ;BX содержит число параграфов
MOV CL,4 ;сдвигаем это число на 4 бита влево
SHL BX,CL ;чтобы получить величину в байтах
MOV OVERLAY_OFFSET,BX ;запоминаем смещение
;---загрузка первого оверлея
MOV AX,SEG BLOCK ;ES:BX указывает на блок параметров
MOV ES,AX ;
MOV BX,OFFSET BLOCK ;
MOV AX,OVERLAY_SEG ;помещаем адрес сегмента оверлея в
MOV [BX],AX ;первое слово блока параметров
MOV [BX]+2,AX ;сегмент оверлея - фактор привязки
LEA DX,PATH ;DS:DX указывает на путь к файлу
MOV AH,48H ;номер функции EXEC
MOV AL,3 ;код загрузки оверлея
INT 21H ;загружаем оверлей
JC LOAD_ERROR ;флаг переноса говорит об ошибке
;---теперь программа занимается своими делами
.
.
CALL DWORD PTR OVERLAY_OFFSET ;вызов оверлея
. ;нужно указывать DWORD PTR, так как оверлей -
. ;далекая процедура
;---посмотрите эту структуру, когда будете писать оверлей
DSEG SEGMENT ;как обычно, устанавливаем сегмент данных
. ;опускаем стековый сегмент (используется
. ;стек вызывающей программы)
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
OVERLAY PROC FAR ;всегда "далекая" процедура
ASSUME CS:CSEG,DS:DSEG
PUSH DS ;храним DS вызывающей программы
MOV AX,DSEG;устанавливаем DS оверлея
MOV DS,AX
.
.
POP DS ;восстанавливаем DS при завершении
RET
OVERLAY ENDP
CSEG ENDS
END


<~-1.3.4 Сохранение программы в памяти после завершения.
Содержание
1.3.6 Преобразование программ из типа .EXE в тип .COM.-~>

Сайт управляется системой uCoz