Операционная система 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. |