ОГЛАВЛЕНИЕ

 

1.3.2 Запуск одной программы из другой.

MS DOS обеспечивает функцию EXEC (номер 4BH прерывания 21H),
реализующую вызов одной программы из другой. Первая программа
называется "родителем", а загружаемая и запускаемая - "потомком".
Высокий уровень.
В Бейсик версии 3.0 введена команда SHELL. Со значительными
ограничениями она позволяет бейсиковской программе загрузить и
выполнить другую программу. Формат этой команды SHELL ком_строка.
Командная строка может быть просто именем программы или она может
содержать кроме имени параметры, которые обычно следуют за именем
программы в командной строке. Если ком_строка не указана, то
загружается копия COMMAND.COM и появляется запрос операционной
системы. В этот момент можно выполнить любую команду MS DOS, а по
завершению вернуть управление бейсиковской программе, введя ко-
манду EXIT.
Имеется ряд ограничений при использовании SHELL. Если загру-
жаемая программа меняет режим работы дисплея, то он не будет
автоматически восстановлен при возврате. Перед загрузкой програм-
мы все файлы должны быть закрыты, и это не может быть программа,
которая остается резидентной после завершения. Обсуждение ряда
других проблем содержится в руководстве по Бейсику.
Средний уровень.
Функция 4BH более сложна, чем остальные, требуя четырех подго-
товительных шагов:
1. Подготовить в памяти место, доступное программе.
2. Создать блок параметров.
3. Построить строку, содержащую накопитель, путь и имя прог-
раммы.
4. Сохранить значения регистров SS и SP в переменных.
Поскольку при загрузке программы MS DOS выделяет ей всю дос-
тупную память, то необходимо освободить место в памяти. Если не
освободить часть памяти, то не будет места для загрузки второй
программы. В [1.3.1] объяснено как это сделать с помощью функции
SETBLOCK. После того как память освобождена, Вы должны просто
поместить в BX требуемое число 16-байтных параграфов, заслать 4AH
в AH и выполнить прерывание 21H, делая доступным программе именно
то число параграфов, которое ей требуется.
Блок параметров, на который должны указывать ES:BX это
14-байтный блок блок памяти, в который Вы должны поместить сле-
дующую информацию:
DW сегментный адрес строки среды
DD сегмент и смещение командной строки
DD сегмент и смещение первого FCB
DD сегмент и смещение второго FCB
Строка среды - это строка, состоящая из одной или более специ-
фикаций, которым следует MS DOS при выполнении программы. Элемен-
ты строки среды такие же, как и те что можно обнаружить в диско-
вом файле CONFIG.SYS. Например, в строку может быть помещено
VERIFY = ON. Просто начните строку с первого элемента, завершив
его символом ASCII 0, потом запишите следующий и т.д. За послед-
ним элементом должны следовать два символа ASCII 0. Строка должна
начинаться на границе параграфа (т.е. ее адрес по модулю 16 дол-
жен быть равен нулю). Это вызвано тем, что соответствующий вход в
блоке параметров, указывающий на строку, содержит только 2-байт-
ное сегментное значение. Все это не нужно, если новая программа
может работать с той же строкой среды, что и программа "роди-
тель". В этом случае надо просто поместить два символа ASCII 0 в
первые 2 байта блока параметров.
Следующие 4 байта блока параметров указывают на командную
строку для загружаемой программы. "Командная строка" - это сим-
вольная строка, определяющая способ работы программы. При загруз-
ке программы из DOS она может иметь вид вроде EDITOR A:CHAPTER1\
NOTES.MS. При этом вызывается редактор и ему передается имя файла
в подкаталоге накопителя A для немедленного открытия. Когда Вы
подготавливаете командную строку для EXEC, то надо включать толь-
ко последнюю часть информации, но не имя загружаемой программы.
Перед командной строкой должен стоять байт, содержащий длину этой
строки, и она должна завершаться символом <ВК> (ASCII 13).
Последние 8 байтов блока параметров указывают на управляющие
блоки файлов (FCB). FCB содержит информацию об одном или двух
файлах, указанных в командной строке. Если открываемых файлов
нет, то надо заполнить все 8 байт символом ASCII 0. В [5.3.5]
объяснено, как работает FCB. Начиная с версии MS DOS 2.0, исполь-
зование FCB необязательно и Вы можете не включать информацию FCB,
вместо этого используя новую конвенцию дескриптора файлов (file
handler), в которой доступ к файлу предоставляется по кодовому
номеру, а не через FCB (также обсуждается в [5.3.5]).
Наконец, Вы должны построить строку с указанием накопителя,
пути и имени файла. Эта строка именует загружаемую программу.
DS:DX указывает на эту строку при выполнении EXEC. Эта строка -
стандартная строка ASCIIZ, т.е. ничего более, чем стандартная
спецификация файла, завершаемая кодом ASCII 0. Например, это
может быть B:\NEWDATA\FILER.EXE, где символом обозна-
чен код ASCII 0.
После того как вся указанная информация подготовлена, остается
последняя задача. Поскольку все регистры будут изменены вызывае-
мой задачей, то надо сохранить сегмент стека и указатель стека, с
тем чтобы они могли быть восстановлены, когда управление будет
возвращено вызвавшей задаче. Для их сохранения создайте перемен-
ные. Поскольку значение регистра DS также будет изменено, то эти
переменные не могут быть найдены, до тех пор пока не будут повто-
рены операторы MOV AX,DSEG и MOV DS,AX. После того как SS и SP
сохранены, поместите 0 в AL, для выбора операции "загрузка и
запуск" (EXEC используется также для оверлеев [1.3.5]). Затем
поместите 4AH в AH и вызовите прерывание 21H. В этот момент запу-
щены две программы, причем программа "родитель" находится в оста-
новленном состоянии. MS DOS предоставляет возможность программе
потомку передать родителю код возврата, таким образом могут быть
переданы ошибки и статус. В [7.2.5] объяснено как это сделать.
Что касается самой функции запуска, то при возникновении ошибки
устанавливается флаг переноса, а регистр AX в этом случае будет
возвращать 1 - для неправильного номера функции, 2 - если файл не
найден, 5 - при дисковой ошибке, 8 - при нехватке памяти, 10 -
если неправильна строка среды и 11 - если неверен формат.

Приводимый пример - простейший из возможных, но часто больше
ничего и не надо. Здесь оставлен нулевым блок параметров и не
создана строка среды. Это означает, что загружаемой программе не
будет передаваться командная строка и что среда будет такой же,
как и для вызывающей программы. Вы должны только изменить распре-
деление памяти, создать имя и (пустой) блок параметров и сохра-
нить значения SS и SP.
;---в сегменте данных
FILENAME DB 'A:TRIAL.EXE',0 ;загружаем TRIAL.EXE
PARAMETERS DW 7DUP(0) ;нулевой блок параметров
KEEP_SS DW 0 ;переменная для SS
KEEP_SP DW 0 ;переменная для SP
;---перераспределение памяти
MOV BX,ZSEG ;получить # параграфа конца
MOV AX,ES ;получить # параграфа начала
SUB BX,AX ;вычислить размер программы
MOV AH,4AH ;номер функции
INT 21H ;перераспределение
;---указываем на блок параметров
MOV AX,SEG PARAMETERS ;в ES - сегмент
MOV ES,AX ;
MOV BX,OFFSET PARAMETERS ;в BX - смещение
;---сохранить копии SS и SP
MOV KEEP_SS,SS ;сохраняем SS
MOV KEEP_SP,SP ;сохраняем SP
;---указываем на строку имени файла
MOV DX,OFFSET FILENAME ;смещение - в DX
MOV AX,SEG FILENAME ;сегмент - в DS
MOV DS,AX ;
;---загрузка программы
MOV AH,4BH ;функция EXEC
MOV AL,0 ;выбираем "загрузку и запуск"
INT 21H ;запускаем задачу
;---впоследствии, восстанавливаем регистры
MOV AX,DSEG ;восстанавливаем DS
MOV DS,AX ;
MOV SS,KEEP_SS ;восстанавливаем SS
MOV SP,KEEP_SP ;восстанавливаем SP
;---в конце программы создаем фиктивный сегмент
ZSEG SEGMENT ;см. [1.3.1]
ZSEG ENDS