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










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

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

Доступ к программному оверлею из порождающей программы

После загрузки программного оверлея порождающая программа должна осуществить к нему доступ. Так как порождающая программа знает адрес, по которому был загружен программный оверлей, то для доступа к оверлею она может выдать инструкцию CALL или инструкцию перехода JMP. Обращаться к оверлею по инструкции CALL рекомендуется по той причине, что оверлей затем сможет возвратиться в порождающую программу путем использования инструкции RET, чем запоминать адрес возврата в порождающую программу для инструкции JMP. Если же возвращать управление в порождающую программу не нужно, то предпочтительнее использование инструкции JMP. Оверлей, в таком случае, содержит вызов функции завершения программы.


Все способы доступа к оверлею (либо по инструкции CALL, либо по инструкции JMP) должны быть ссылками far (далекий). Программный код, загружаемый в оверлей, является относительным по отношению к собственному адресу сегмента и не может располагаться в том же самом сегменте, что и порождающая программа (хотя он может быть загружен в тот же самый участок памяти). Кроме того, с помощью функции "загрузить оверлей" не строится блок PSP. Так как отсутствует дополнительная информация, помещаемая в память загрузчиком, программные коды и данные из оверлейного файла загружаются, начиная точно с указанного адреса загрузки.


Рассмотрим простейший случай : оверлей, загружаемый из файлов формата .COM. Все файлы формата .COM имеют начало 100 (шестнадцатиричное значение). Т.е. коды этих файлов начинаются с адреса 100 относительно их сегментов. Все ссылки, содержащиеся в программе, являются относительными к этому адресу. Т.к. файл .COM загружается прямо по адресу загрузки, можно некорректно использовать адрес загрузки в качестве значения сегмента для оверлея. Рис.3-15 показывает, что если адрес загрузки используется в качестве адреса сегмента, то значения смещений в программном коде смещаются на 100 (шестнадцатиричное значение). Правильный адрес сегмента для использования есть адрес загрузки минус 10 (шестнадцатиричное значение), который перемещает смещения программного кода на 100 (шестнадцатиричное значение).


Для программных файлов формата .EXE существуют другие проблемы. Когда файл формата .EXE загружается для выполнения, MS-DOS инициализирует программный и стековый сегменты для указания на надлежащий сегмент и указатель инструкции для указания на первую инструкцию программы. Когда файл формата .EXE загружается как оверлей, MS-DOS не обеспечивает эти значения. Как тогда порождающая программа узнает, куда вводить программу?



                              /\/\/\/\/\/\/\/\/\/\/\/\
                             | Младшие адреса памяти |    АДРЕС СЕГМЕНТА
                             |-----------------------|<---    ОВЕРЛЕЯ
                             |            ^          |   Segment:CS_RUN
                             |            |          |   CS_LOAD:10(hex)
                             |         100 (hex)     |
                             |            |          |
          АДРЕС ЗАГРУЗКИ     |            V          |    АДРЕСА ПАМЯТИ
         Segment:CS_LOAD---->|-----------------------|<---
                             |Программный код оверлея| CS_LOAD:0000(hex)
                             |          ...          | CS_RUN: 0100(hex)
                             |-----------------------|
                             |     Данные оверлея    |
                             |          ...          |
                             |-----------------------|
                             | Старшие адреса памяти |
                             |/\/\/\/\/\/\/\/\/\/\/\/

              Рис.3-15. Взаимосвязь адреса сегмента и адреса загрузки
                                для оверлея формата .COM

Так как файлы формата .EXE имеют нулевое начало, то какую инструкцию CALL или JMP использовать для перехода к адресу загрузки? Это будет зависеть от того, как написана программа. Для файлов типа .EXE, созданных из одного исходного файла, компоновщик LINK и MS-DOS загружают сегменты в память в том же самом порядке, в котором они появляются в исходной программе! Общим порядком для определения сегментов является следующий: стековый сегмент, затем сегмент данных, затем программный сегмент. (По причине минимизации ссылок вперед в программном сегменте). Для возможности вызова программ формата .EXE по инструкции CALL по адресу их загрузки, программный сегмент должен быть первым сегментом в файле .ASM, а точка входа должна быть первой инструкцией в программном сегменте. Макроассемблер MASM и компоновщик LINK не имеют с этим никаких проблем, хотя в некоторых случаях для MASM может появиться необходимость использования директив замещения для разрешения ссылок вперед.


Листинг 3-10 показывает как должна появляться последовательность загрузки и вызова, когда используется функция загрузки оверлея для файлов формата .COM. Последовательность для программ формата .EXE проще. Не нужно перемещение от адреса загрузки к адресам при выполнении. Мы предположили, что все регистры сегментов в порождающей программе уже инициализированы и что уже была вызвана функция модификации распределения памяти для освобождения достаточного пространства для загрузчика файла COMMAND.COM.



               Листинг 3-10. Загрузка и доступ к программе типа .COM
                          с помощью функции 4Bh (AL = 3)
         -----------------------------------------------------------------

                 ...                               ...
         ; Распределение памяти для оверлея
                 mov   ah,48h         ; функция распределения памяти
                 mov   bx,1000h       ; предполагается сегмент в 64 кбайт
                 int   21h            ; вызов MS-DOS
                 jc    error          ; переход, если произошла ошибка
                 mov   params,ax      ; сохранение адреса памяти
         ; Загрузка оверлея
                 mov   dx,offset params ; доступ к блоку параметров
                 mov   bx,offset filename ; доступ к имени файла в ASCIIZ
                 mov   ax,4B03h       ; функция загрузки оверлея
                 int   21h            ; вызов MS-DOS
                 jc    error          ; переход, если произошла ошибка
         ; Вызов оверлея
                 mov   ax,params      ; получение адреса загрузки
                 sub   ax,10h         ; трансляция для адреса выполнения
                 mov   run_seg,ax     ; и сохранение его
                 push  ds             ; сохранение сегмента данных
                 call  dword ptr run_adr ; вызов оверлея
         ; Освобождение памяти, которая использована для оверлея
                 pop   ds             ; восстановление сегмента данных
                 mov   ah,49h         ; функция освобождения памяти
                 mov   as,params      ; получение адреса блока памяти
                 int   21h            ; вызов MS-DOS
                 jc    error          ; переход, если произошла ошибка
                 ...                               ...
         params  dw    ?              ; адрес загрузки
                 dw    0              ; значение настройки
         run_adr dw    0100h          ; новый указатель инструкции
         run_seg dw    ?              ; новое значение кодового сегмента
         -----------------------------------------------------------------

Пример программы распределяет память для размещения программного кода оверлея. Он резервирует эту область памяти так, что если и оверлей распределяет память, то получается чистая область. Напротив, оверлей может распределить память, которую он уже занимает, и перезаписать сам себя. Действительное резервируемое пространство памяти может быть установлено для фактического размера оверлея.


Оверлей может изменяться так часто, как необходимо для выполнения программы. При различных вариантах использования функции загрузки оверлея следует иметь в виду, что MS-DOS ничего не предпринимает для предотвращения загрузки оверлея в верхней части текущего выполнения программы или в другом месте памяти, включая саму систему! Хотя отдельные программисты могут найти такой трюк полезным, его применение не рекомендуется, и более того необходимо следить за тем, чтобы он не мог возникнуть случайно.


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

Hosted by uCoz