COMMAND.COM может выдавать команды через командную строку тексто-
вого буфера, то можно увидеть, что из программы пользователя мож-
но вызывать встроенные команды MS-DOS. Кроме того, командная
строка, передаваемая файлом COMMAND.COM, может содержать переназ-
начения, каналы и фильтры. Формат текста команды, используемый
при этом способе, почти такой же, какой используется в начальной
командной строке, за исключением того, что при вызове файла
COMMAND.COM из программы, текст команды должен начинаться с сим-
волов /c.
Загрузка двух программных файлов (COMMAND.COM и прикладной
программы) для выполнения только одного программного файла не яв-
ляется высокоэффективным способом выполнения программ. Однако,
следует принять во внимание большую гибкость и производитель-
ность, достигаемые при использовании этого способа.
Важное предупреждение
Механизм функции загрузки и выполнения программ в версии 2.0
MS-DOS имеет серьезный технический недостаток. При выполнении
функции "захламляются" все регистры сегментов (за исключением ко-
дового сегмента), разрушается указатель стека и разрушается боль-
- 3-51 -
шинство общих регистров. Если эта функция используется с любой
подверсией MS-DOS версии 2.0 (т.е. 2.00 или 2.10), то перед вызо-
вом функции необходимо сохранять в памяти указатель стека и любые
общие регистры, необходимые для дальнейшего использования; и
восстанавливать из памяти регистры сегментов, указатель стека и
необходимые общие регистры после выполнения функции. Пример по-
следовательности программных кодов, предназначенный для выполне-
ния этих действий для программного файла типа .COM, показан в
листинге 3-9.
Для программных файлов типа .EXE можно восстановить надлежа-
щие значения сегмента из значений, установленных компоновщиком
LINK (например, mov ss,stack), или из памяти, размещаемой внутри
программного сегмента. Для защиты стека необходимо помнить о том,
что последовательность восстановления стекового сегмента и указа-
теля стека должна быть такой, что сначала указывается указатель
стека, а затем стековый сегмент.
Начиная с версии MS-DOS 3.0, этот недостаток устранен. Функ-
ция загрузки и выполнения программы возвращает все регистры "нет-
ронутыми".
Листинг 3-9. Восстановление необходимых элементов при выполнении
функции загрузки и выполнения программы для прог-
раммного файла типа .COM в MS-DOS версии 2.XX
-----------------------------------------------------------------
...
<установка параметров вызывающей программой>
...
mov spoint,sp ; сохранение указателя стека в памяти
mov ax,4B00h ; функция загрузки и выполнения пр-мы
int 21h ; вызов MS-DOS
; регистры не изменятся, если произойдет сбой при загрузке --
; восстановление не выполнять
jc error ; переход при ошибке
mov ax,cs ; получение общего сегмента
mov ds,cx ; для сегмента данных
mov es,cx ; для внешнего сегмента
mov ss,ax ; и для стекового сегмента
mov sp,spoint ; стек теперь повторно выровнен
...
<восстановление общих регистров>
...
----------------------------------------------------------------
Загрузка программного оверлея (перекрытия) посредством MS-DOS
(код функции 4Bh с AL = 3)
Возможность выполнения одной программы из другой является на
самом деле огромным достижением, но при этом имеет место сущест-
венный недостаток, заключающийся в том, что после выполнения вы-
зываемой программы происходит ее завершение. Однако, во многих
случаях разработчики программ хотят вызывать другую программу для
выполнения некоторых функций, но при этом дополнительно хотят
иметь большую степень управления порожденной программой, или
большую степень связи с порожденной программой, или даже возмож-
ность неоднократного вызова порождаемой программы без ее повтор-
ной перезагрузки. Для этих случаев для функции 4Bh MS-DOS предос-
тавляет опцию Load Overlay (загрузка оверлея).
- 3-52 -
Одним из отличий функции загрузки оверлея от функции загрузки
и выполнения программы является то, что при загрузке оверлейной
программы порождающая программа не предназначена для модификации
параметров порождаемой программы. Это имеет место потому, что по-
рождающая и порождаемая программы, на самом деле, являются частя-
ми одной и той же программы. Все, что выполняет функция загрузки
программного оверлея, это загрузка дополнительного программного
кода (и/или данных программы) в память.
Другим отличием загрузки оверлея от загрузки и выполнения яв-
ляется то, что загрузка оверлея не требует блок памяти его вла-
дельца. Загрузка оверлея не передает блок среды или блок началь-
ного распределения, как функция загрузки и выполнения программы.
Функция загрузки оверлея просто загружает запрашиваемый файл в
память, настраивая значения сегментов программы в соответствии с
параметрами, обеспечиваемыми при вызове функции (как показано на
Рис.3-14). Полученный программный код может быть выполнен как
подпрограмма, но не должен выполняться как отдельная программа.
Если оверлей завершается посредством одной из функций завер-
шения MS-DOS, то завершается и оверлей и порождающая программа.
Если для выхода используется функция 31h или функция 27h ("завер-
шить и оставить резидентной"), то модифицируется блок начального
распределения порождающей подпрограммы, а порождающая программа
остается в памяти. Порожденная программа останется резидентной
только тогда, когда блок запрошенной памяти является достаточно
большим, вмещающим и порождающую и порожденную программы. Если
выполняется одна из функций завершения программ, то обе программы
удаляются из памяти.
Рис.3-14 показывает, что фактор настройки, указываемый как
часть функции загрузки оверлея, не воздействует на адрес загрузки
оверлея. Вместо фактора настройки используется модификация смеще-
ния ссылок внутри загружаемой программы. Если оверлей загружается
в формате .COM, то фактор настройки не воздействует на загружае-
мый оверлей и должен быть установлен в нулевое значение.
Для программных файлов типа .EXE фактор настройки добавляется
к значениям ссылок сегментов, которые появились в файле загрузки.
При загрузке большинства оверлейных программ типа .EXE (которые
обычно первоначально по умолчанию 0000:0000) фактор настройки
должен быть установлен в то же самое значение, что и адрес заг-
рузки.
Доступ к программному оверлею из порождающей программы
После загрузки программного оверлея порождающая программа
должна осуществить к нему доступ. Так как порождающая программа
знает адрес, по которому был загружен программный оверлей, то для
доступа к оверлею она может выдать инструкцию CALL или инструкцию
перехода JMP. Обращаться к оверлею по инструкции CALL рекоменду-
ется по той причине, что оверлей затем сможет возвратиться в по-
рождающую программу путем использования инструкции RET, чем запо-
минать адрес возврата в порождающую программу для инструкции JMP.
Если же возвращать управление в порождающую программу не нужно,
то предпочтительнее использование инструкции JMP. Оверлей, в та-
ком случае, содержит вызов функции завершения программы.
Все способы доступа к оверлею (либо по инструкции CALL, либо
по инструкции JMP) должны быть ссылками far (далекий). Програм-
мный код, загружаемый в оверлей, является относительным по отно-
шению к собственному адресу сегмента и не может располагаться в
- 3-53 -
том же самом сегменте, что и порождающая программа (хотя он может
быть загружен в тот же самый участок памяти). Кроме того, с по-
мощью функции "загрузить оверлей" не строится блок 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. Взаимосвязь адреса сегмента и адреса загрузки