Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книги 1-2, М.: Диалог-МИФИ, 1991. 3.4. Запуск программ из программВаша программа может при необходимости запустить другую программу формата EXE или COM. Для ассемблерных программ существует функция 4Bh прерывания INT 21h, для программ, составленных на языке Си - разнообразные функции, входящие в состав стандартной библиотеки. Сначала рассмотрим запуск программ при помощи функции 4Bh прерывания INT 21h. Содержимое регистров перед вызовом прерывания: AH = 4BH AL - код подфункции (0, 1, 2, 3) DS:DX - указатель на путь к запускаемой программе ES:BX - указатель на блок параметров EPB После возврата из прерывания флаг CF устанавливается в 0, если ошибок не было, и в 1 при обнаружении ошибок. Регистр AX в случае наличия ошибок содержит код ошибки:
Функция 4Bh прерывания 21h имеет четыре подфункции с номерами от 0 до 3:
Для функции 0 регистры DS:DX должны указывать на полный путь запускаемой программы в формате ASCIIZ ( т.е. текстовая строка, закрытая двоичным нулем). Блок параметров EPB (Exec Parameter Block) в этом случае имеет следующий формат:
Запущенной программе доступны все файлы, открытые родительской программой. Если родительская программа сама формирует среду для дочерней программы, она должна подготовить новую среду на границе параграфа и поместить значение сегментного адреса в поле seg_env блока EPB. Приведем простую программу, которая запускает программу с именем PARM.COM из текущего каталога. Программу PARM.COM мы только что рассматривали, эта программа выводит на экран полученные ей в командной строке параметры.
.MODEL small
DOSSEG
.STACK 100h
.DATA
path db "PARM.COM",0
command_line db 8,"Parm Str"
epb dw 0
cmd_off dw ?
cmd_seg dw ?
fcb1 dd ?
fcb2 dd ?
.CODE
.STARTUP
mov bx,OFFSET command_line ; адрес командной
mov cmd_off,bx ; строки для блока EPB
mov cmd_seg,ds
mov ax,ds
mov es,ax
mov bx,OFFSET epb ; ES:BX указывают на EPB
mov dx,OFFSET path ; DS:DX указывают на путь
; запускаемой программы
mov ax, 4B00h ; AH = 4Bh
; AL = 0 загрузить и выполнить
int 21h
.EXIT 0
END
Эта программа использует модель памяти SMALL, и ее загрузочный модуль имеет формат EXE. При редактировании был указан стандартный для Quick C 2.01 размер памяти, требуемый для программы. Если попытаться использовать формат COM в модели TINY, то окажется, что вся память распределена COM-программе и для дочерней программы не осталось места. Следующая программа освобождает всю неиспользуемую ей память, после чего на освободившееся место загружает программу PARM.COM:
.MODEL tiny
DOSSEG
.STACK 100h
.DATA
path db "PARM.COM",0
command_line db 8,"Parm Str"
epb dw 0
cmd_off dw ?
cmd_seg dw ?
fcb1 dd ?
fcb2 dd ?
.CODE
.STARTUP
;
; Освобождаем лишнюю память за концом программы
;
mov bx,OFFSET last ; смещение конца
; программы
mov cl,4 ; вычисляем длину в
; параграфах
shr bx,cl
add bx,17 ; добавляем 1 параграф для
; выравнивания и 256 байт
; для стека
mov ah, 4Ah ; изменяем размер выделенного
int 21h ; блока памяти
mov ax,bx ; установка нового значения
shl ax,cl ; указателя стека
dec ax
mov sp,ax
mov bx,OFFSET command_line ; адрес командной
mov cmd_off,bx ; строки для
; блока EPB
mov cmd_seg,ds
mov ax,ds
mov es,ax
mov bx,OFFSET epb ; ES:BX указывают на EPB
mov dx,OFFSET path ; DS:DX указывают на путь
; запускаемой программы
mov ax, 4B00h ; AH = 4Bh
; AL = 0 загрузить и
; выполнить
int 21h
.EXIT 0
last: db ?
END
Для изменения размера выделенного программе блока памяти мы использовали функцию 4Ah прерывания 21h. Подфункции 1 и 2 прерывания 4Bh используются DOS (это внутренние подфункции DOS). Мы приведем недокументированный формат блока EBP для этих функций. Для подфункнкции 1:
Для подфункции 2:
Подфункция 3 используется для загрузки программных оверлеев. Оверлей загружается в адресное пространство родительской программы, поэтому DOS не заказывает дополнительной памяти и не строит PSP. Формат EPB для этой подфункции:
Следующая демонстрационная программа загружает программу PARM.COM_как оверлей без передачи ей управления:
.MODEL small
DOSSEG
.STACK 100h
.DATA
path db "PARM.COM",0
epb dw 0
reloc dd 0
.CODE
.STARTUP
mov ax,ds
mov es,ax
mov bx,SEG buff
mov epb,bx
mov bx,OFFSET epb ; ES:BX указывают на EPB
mov dx,OFFSET path ; DS:DX указывают на путь
; загружаемой программы
mov ax, 4B03h ; AH = 4Bh
; AL = 0 загрузить оверлей
int 21h
.EXIT 0
buff: dd 100 dup(?)
END
Программа загружается в буфер buff. Пользователи языка Си имеют в своем распоряжении три возможности запустить программу. Самый простой способ - использовать функцию system(). Эта функция может выполнить любую команду DOS или любую программу, пакетный файл. Например:
system("FORMAT A:");
При использовании этой функции должен быть доступен COMMAND.COM. К сожалению, хотя system и возвращает код завершения, по нему нельзя сделать вывод о том, как была выполнена запускаемая программа. Если в качестве аргумента функции будет передано неправильное имя, на экране появится сообщение: Bad command or file name Код возврата в этом случае будет 0 - как будто все нормально! Другие две возможности запустить программу - использовать функции spawn и exec. Функция spawn и ее разновидности запускают программу как дочерний процесс. Функция exec загружает новую программу как оверлей на место старой и передает ей управление без возврата. После завершения дочерней программе управление будет передано COMMAND.COM или программе, которая запустила родительскую программу. Семейство функций spawn обеспечивает запуск дочерней программы с родительской или со специально сформированной средой. Кроме того, в файле process.h описаны параметры, которые можно передать функции spawn:
В качестве примера использования функций запуска программы рассмотрим возможное решение проблемы создания HELP-системы для прикладной программы. С помощью текстового редактора можно создать справочную базу данных в формате утилиты Microsoft HELPMAKE, затем, запуская в нужный момент диалоговую утилиту работы с базой данных Microsoft Quick Help QH.EXE, можно получить нужную справку. Утилита QH использует базы данных, описанные в переменной среды HELPFILES. Мы будем использовать либо родительскую среду, где находится значение переменной HELPFILES по умолчанию, либо указывать новое значение для этой переменной. Приведенная ниже программа используется для получения справки о функции стандартной библиотеки printf, поиск производится в HELP-базе QuickC:
#include <stdio.h>
#include <conio.h>
#include <process.h>
main()
{
int r;
// Получаем справку о функции printf,
// справочная база данных расположена
// в каталоге d:\qc2\bin
r = help("HELPFILES=d:\\qc2\\bin;","printf");
if( r == -1 )
printf( "Невозможно запустить процесс" );
else
printf( "\nПроцесс завершен" );
exit(r);
}
/**
*.Name help
*
*.Title Получить справку по заданному контексту
*
*.Descr Функция получает в качестве параметров
* переменную среды, указывающую на путь
* к справочной базе данных и указатель
* на строку контекста для поиска в базе.
* Затем запускается как дочерний процесс
* утилита Microsoft Quick Help QH.EXE, для
* которой формируются среда и параметры.
*
*.Params int help(char *help_file, char *help_topic);
*
* help_file - переменная среды, указывающая
* на путь к справочной базе
*
* help_topic - контекст для поиска в базе
*
*
*.Return 0 при успешном запуске процесса
* -1 не удалось запустить процесс
**/
int help(char *help_file, char *help_topic) {
char *env[] = { "", NULL }; // Среда, которую
// получит QH при запуске
if(*help_file != 0) {
env[0] = help_file; // Формируем среду для QH
// Запускаем утилиту
return(spawnlpe(P_WAIT,"QH","QH",
"-u",help_topic,NULL,env));
}
else {
// Если переменная среды не задана,
// используем родительскую среду
return(spawnlp(P_WAIT,"QH","QH",
"-u",help_topic,NULL));
}
}
Подробная информация об использовании утилит HELPMAKE и QH приводится в документации на Microsoft C 6.0. |

