MS-DOS для программиста© Александр Фролов, Григорий ФроловТом 18, М.: Диалог-МИФИ, 1995, 254 стр. 3.4. Запуск программ из программВаша программа может при необходимости запустить другую exe- или com-программу. Программа, составленная на языке ассемблера, запускает другую программу с помощью функции 4Bh прерывания INT 21h . Для выполнения той же задачи из программ, составленных на языке С, следует использовать разнообразные функции, входящие в состав стандартной библиотеки системы разработки. Сначала рассмотрим процедуру запуска программы при помощи функции 4Bh прерывания INT 21h . Перед вызовом прерывания вы должны загрузить регистры процессора следующим образом:
После возврата из прерывания флаг переноса CF устанавливается в 0, если ошибок не было, и в 1 - при обнаружении ошибок. Если произошла ошибка, ее код записывается в регистр AX:
Функция 4Bh прерывания INT 21h имеет несколько
подфункций:
Опишем эти подфункции более подробно. Загрузка и выполнение программыДля функции 0 регистры DS:DX должны указывать на
полный путь запускаемой программы в формате ASCIIZ
(т. е. на текстовую строку, закрытую двоичным
нулем). Блок параметров EPB (Exec Parameter Block ) в этом
случае имеет следующий формат:
Запущенной программе доступны все файлы, открытые родительской программой. Если родительская программа сама формирует среду для дочерней программы, она должна подготовить новую среду на границе параграфа и поместить значение сегментного адреса в поле seg_env блока EPB . Для примера приведем исходный текст простой программы SPARM (листинг 3.5), которая запускает программу с именем parm.com из текущего каталога. Программу parm.com мы уже рассматривали (листинг 3.2). Эта программа выводит на экран параметры, полученные ей при запуске через командную строку. Листинг 3.5. Файл sparm\sparm.asm .MODEL tiny DOSSEG .DATA path db "PARM.COM",0 command_line db 11,"Parm1 Parm2" 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 Программа SPARM освобождает всю неиспользуемую ей память, после чего на освободившееся место загружает программу parm.com. Такая процедура необходима потому, что MS-DOS выделяет всю имеющуюся память в распоряжение запускаемой com-программы. Поэтому при попытке запустить программу без предварительного освобождения части памяти функция 4Bh вернет код ошибки 8 (нет памяти для загрузки программы). Для изменения размера блока памяти, выделенного программе, мы использовали функцию 4Ah прерывания INT 21h . Загрузка программы без выполненияПодфункции 1 и 2 прерывания INT 4Bh используются операционной системой MS-DOS для собственных нужд (это внутренние подфункции MS-DOS). Они также необходимы для создания программ-отладчиков, таких как, например, debug.com или td.exe. Мы приведем недокументированный формат блока EBP для этих функций. Для подфункции 1 блок EBP имеет следующий формат:
Формат блока EPB для подфункции 2:
Загрузка программного оверлеяПодфункция 3 используется для загрузки программных оверлеев . Оверлей загружается в адресное пространство родительской программы, поэтому MS-DOS не заказывает дополнительной памяти и не строит PSP . Формат EPB для этой подфункции:
Следующий фрагмент программы загружает программу parm.com как оверлей без передачи ей управления (программа загружается в буфер buff): .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 Подготовка программы для выполненияПодфункция 5 используется для загрузки и предварительной подготовки программы к выполнению . Она впервые появилась в MS-DOS версии 5.0. Вы можете использовать ее вместо недокументированных подфункций 1 и 2. Если программа, запущенная с помощью подфункции 5, попытается определить версию MS-DOS, ей будет предоставлен не истинный номер версии, а определенный с учетом действия драйвера setver. Напомним, что с помощью драйвера setver MS-DOS может "обмануть" программу, сообщив ей, что работает MS-DOS, например, версии 3.31 или любой другой версии, указанной пользователем. Такая возможность требуется в тех случаях, когда программа была рассчитана на конкретную версию MS-DOS, но, тем не менее, способна работать и в новой версии. Для подфункции 5 указатель, расположенный в регистрах DS:DX, должен указывать на структуру EXECSTATE, описанную ниже:
Запуск программ из программ, составленных на языке СПользователи языка С имеют в своем распоряжении несколько возможностей запустить программу. Самый простой способ - использовать функцию system . Эта функция может выполнить любую команду MS-DOS или любую программу, а также пакетный файл. Например: system("FORMAT A:"); При использовании этой функции должен быть доступен файл command.com . К сожалению, хотя функция system и возвращает код завершения, по нему нельзя сделать вывод о том, как была выполнена запускаемая программа. Если в качестве аргумента функции будет передано имя несуществующей программы, на экране появится сообщение: Bad command or file name Код возврата в этом случае будет 0 - как будто все хорошо! Другая возможности запустить программу - использовать функции spawn и exec. Функция spawn и ее разновидности запускают программу как дочерний процесс. Функция exec загружает новую программу как оверлей на место старой и передает ей управление без возврата. После завершения дочерней программы управление будет передано программе command.com или программе, которая запустила родительскую программу. Семейство функций spawn обеспечивает запуск дочерней программы, передавая ей родительскую или с специально сформированную среду. Кроме того, в файле process.h описаны параметры, которые можно передать функции spawn:
Ниже мы привели исходный текст программы SPARM1 (листинг 3.6), которая запускает программу parm.com с помощью функции spawnlpe. Эта функция входит в стандартную библиотеку Borland C++ и позволяет не только запустить программу, но и сформировать для нее среду, а также передать параметры. Листинг 3.6. Файл sparm1\sparm1.cpp #include <stdio.h> #include <conio.h> #include <process.h> int main(void) { char *env[] = { "PARMVAR=d:\\VARS", NULL }; int rc; rc = spawnlpe(P_WAIT ,"parm","parm", "Parm1", "Parm2", NULL, env); if(rc == -1) printf("Невозможно запустить процесс"); else printf("\nПроцесс завершен"); return rc; } |