DOS, функция 4Bh Выполнить или загрузить программу
DS:DX — адрес строки ASCIZ с именем файла, содержащего программу
ES:BX — адрес ЕРВ (блока параметров ЕХЕС)
AL=°OOh — загрузить и выполнить
AL=01h — загрузить, но не выполнять
AL=03h — загрузить программный оверлей
CF=0, если функция выполнена успешно
ВХ, DX не сохранены
СЕ=1, если при выполнении функции возникли ошибки
Данная функция загружает в память и запускает программу, имя кото-
рой указано в регистрах DS:DX. Запущенная программа после заверше-
ния работы возвратит управление запускаемой. Если диск или путь
не указаны, принимаются значения по умолчанию. ES:BX указывает
на блок памяти, подготовленный как ЕРВ, формат которого зависит
MS-DOS для программиста
3.4. Запуск программ из программ
Ваша программа может при необходимости запустить другую exe- или com-программу.
Программа, составленная на языке ассемблера, запускает другую программу с помощью функции 4Bh прерывания INT 21h . Для выполнения той же задачи из программ, составленных на языке С, следует использовать разнообразные функции, входящие в состав стандартной библиотеки системы разработки.
Сначала рассмотрим процедуру запуска программы при помощи функции 4Bh прерывания INT 21h .
Перед вызовом прерывания вы должны загрузить регистры процессора следующим образом:
Регистр | Содержимое |
AH | 4Bh |
AL | Код подфункции (0, 1, 2, 3, 5) |
DS:DX | Указатель на текстовую строку в формате ASCIIZ , содержащую путь к запускаемой программе |
ES:BX | Указатель на блок параметров EPB |
После возврата из прерывания флаг переноса CF устанавливается в 0, если ошибок не было, и в 1 — при обнаружении ошибок. Если произошла ошибка, ее код записывается в регистр AX:
Код ошибки | Описание |
1 | Неверный код подфункции |
2 | Не найден файл запускаемой программы |
3 | Указанный путь не найден |
4 | Слишком много открытых файлов |
5 | Нет доступа |
8 | Нет памяти для загрузки программы |
10 | Длина блока среды больше 32 Кбайт |
11 | Неправильный формат запускаемого exe-файла |
Функция 4Bh прерывания INT 21h имеет несколько подфункций:
Код | Описание |
Загрузить и выполнить программу | |
1 | Загрузить, но не выполнять программу |
2 | Загрузить, но не выполнять программу (недокументированная подфункция) |
3 | Загрузить программу как оверлей (не создавая при этом блок PSP ) |
5 | Подготовить программу для выполнения |
Опишем эти подфункции более подробно.
Загрузка и выполнение программы
Для функции 0 регистры DS:DX должны указывать на полный путь запускаемой программы в формате ASCIIZ (т. е. на текстовую строку, закрытую двоичным нулем). Блок параметров EPB (Exec Parameter Block ) в этом случае имеет следующий формат:
Смещение, байт | Размер, байт | Имя поля | Описание |
2 | seg_env | Сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы | |
2 | 4 | cmd | Дальний адрес строки параметров для запускаемой программы. Эта строка должна иметь такой же формат, как и в PSP , т. е. в начале строки находится байт со значением, равным количеству символов в строке параметров, а затем — сама строка параметров |
6 | 4 | fcb1 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 5Ch |
10 | 4 | fcb2 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 6Ch |
Запущенной программе доступны все файлы, открытые родительской программой.
Если родительская программа сама формирует среду для дочерней программы, она должна подготовить новую среду на границе параграфа и поместить значение сегментного адреса в поле seg_env блока EPB .
Для примера приведем исходный текст простой программы SPARM (листинг 3.5), которая запускает программу с именем parm.com из текущего каталога. Программу parm.com мы уже рассматривали (листинг 3.2). Эта программа выводит на экран параметры, полученные ей при запуске через командную строку.
Листинг 3.5. Файл sparm\sparm.asm
Программа 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 имеет следующий формат:
Смещение, байт | Размер, байт | Имя поля | Описание |
2 | seg_env | Сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы | |
2 | 4 | cmd | Дальний адрес строки параметров для запускаемой программы |
6 | 4 | fcb1 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 5Ch |
10 | 4 | fcb2 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 6Ch |
14 | 4 | ss_sp | В это поле после завершения работы запускаемой программы будет записано содержимое регистров SS:SP |
18 | 4 | entry_p | Адрес точки входа в загруженную программу, который нужно записать в регистры CS:IP при запуске программы |
Формат блока EPB для подфункции 2:
Смещение, байт | Размер, байт | Имя поля | Описание |
2 | seg_env | Сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы | |
2 | 4 | cmd | Дальний адрес строки параметров для запускаемой программы |
6 | 4 | fcb1 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 5Ch |
10 | 4 | fcb2 | Адрес блока FCB . Этот адрес будет записан в блок PSP со смещением 6Ch |
Загрузка программного оверлея
Подфункция 3 используется для загрузки программных оверлеев . Оверлей загружается в адресное пространство родительской программы, поэтому MS-DOS не заказывает дополнительной памяти и не строит PSP . Формат EPB для этой подфункции:
Смещение, байт | Размер, байт | Имя поля | Описание |
2 | seg_env | Сегментный адрес, по которому загружается программа | |
2 | 4 | reloc | Фактор перемещения. Для exe-программ обычно содержит то же значение, что и поле seg_env, для com-программ в этом поле находится значение 0 |
Следующий фрагмент программы загружает программу parm.com как оверлей без передачи ей управления (программа загружается в буфер buff):
Подготовка программы для выполнения
Подфункция 5 используется для загрузки и предварительной подготовки программы к выполнению . Она впервые появилась в MS-DOS версии 5.0. Вы можете использовать ее вместо недокументированных подфункций 1 и 2.
Если программа, запущенная с помощью подфункции 5, попытается определить версию MS-DOS, ей будет предоставлен не истинный номер версии, а определенный с учетом действия драйвера setver.
Напомним, что с помощью драйвера setver MS-DOS может «обмануть» программу, сообщив ей, что работает MS-DOS, например, версии 3.31 или любой другой версии, указанной пользователем. Такая возможность требуется в тех случаях, когда программа была рассчитана на конкретную версию MS-DOS, но, тем не менее, способна работать и в новой версии.
Для подфункции 5 указатель, расположенный в регистрах DS:DX, должен указывать на структуру EXECSTATE, описанную ниже:
Смещение, байт | Размер, байт | Имя поля | Описание |
2 | Reserved | Зарезервировано | |
2 | 2 | Flags | Тип программы: 0 — com-программа, 1 — exe-программа, 2 — оверлей |
4 | 4 | ProgName | Указатель на текстовую строку ASCIIZ , содержащую имя программы |
8 | 2 | PSP | Сегмент блока PSP новой программы |
10 | 4 | StartAddr | Стартовый адрес CS:IP новой программы |
14 | 4 | ProgSize | Общий размер программы с учетом размера блока PSP |
Запуск программ из программ, составленных на языке С
Пользователи языка С имеют в своем распоряжении несколько возможностей запустить программу.
Самый простой способ — использовать функцию system . Эта функция может выполнить любую команду MS-DOS или любую программу, а также пакетный файл. Например:
При использовании этой функции должен быть доступен файл command.com .
К сожалению, хотя функция system и возвращает код завершения, по нему нельзя сделать вывод о том, как была выполнена запускаемая программа. Если в качестве аргумента функции будет передано имя несуществующей программы, на экране появится сообщение:
Код возврата в этом случае будет 0 — как будто все хорошо!
Другая возможности запустить программу — использовать функции spawn и exec.
Функция spawn и ее разновидности запускают программу как дочерний процесс. Функция exec загружает новую программу как оверлей на место старой и передает ей управление без возврата. После завершения дочерней программы управление будет передано программе command.com или программе, которая запустила родительскую программу.
Семейство функций spawn обеспечивает запуск дочерней программы, передавая ей родительскую или с специально сформированную среду. Кроме того, в файле process.h описаны параметры, которые можно передать функции spawn:
Параметр | Описание |
P_WAIT | Выполнение родительской программы задерживается до завершения дочерней программы |
P_NOWAIT | Родительская программа продолжает выполнение сразу после запуска дочерней программы. Этот параметр имеет смысл только для мультизадачных операционных систем |
P_OVERLAY | Загружает программу как оверлей и передает ей управление. Этот режим соответствует функции exec в том смысле, что родительская программа не получит управления после завершения дочерней |
Ниже мы привели исходный текст программы SPARM1 (листинг 3.6), которая запускает программу parm.com с помощью функции spawnlpe. Эта функция входит в стандартную библиотеку Borland C++ и позволяет не только запустить программу, но и сформировать для нее среду, а также передать параметры.
Листинг 3.6. Файл sparm1\sparm1.cpp
3. Управление программами
Теперь, когда мы знаем структуру памяти на момент завершения загрузки операционной системы, можно посмотреть, а что же происходит дальше, когда оператор запускает какую-нибудь программу.
Оператор может запустить два типа программ (если не считать командных файлов, которые, вообще говоря, не являются программами, состоящими из машинных кодов) — программы, имеющие расширение имени .COM и .EXE. Эти файлы имеют различный формат и загружаются по-разному, однако, когда загрузка завершена, в памяти компьютера эти два типа программ выглядят совершенно одинаково.
COM-файл — это двоичный образ Вашей программы, состоящий из кода и данных. То есть это файл, содержащий программу в «чистом» виде. Такая программа (как и EXE-программа) может загружаться в любое место памяти. DOS выполняет ее привязку к физическим адресам при загрузке с помощью установки сегментных регистров. Существенным ограничением COM-программы является то, что она не может занимать больше одного сегмента (соответственно, файл .COM не может быть по длине больше 64К).
Программа в формате EXE может иметь любой размер. В самом начале файла программы содержится заголовок (у COM-файла заголовка нет). Этот заголовок используется операционной системой в процессе загрузки программы в память для правильной установки сегментных регистров. Заголовок EXE-файла нужен только при загрузке; когда программа загружена и готова к работе, самого заголовка уже нет в памяти.
Заголовок EXE-файла состоит из форматированной зоны и таблицы расположения сегментов (Relocation Table). Форматированная зона выглядит следующим образом:
(0) 2 | signature | два байта ‘MZ’ (4Dh, 5Ah), индентифицирующие файл в формате EXE |
(+2) 2 | part_pag | длина последней страницы программы в байтах (страница содержит 512 байт) |
(+4) 2 | file_size | размер программы в страницах по 512 байт |
(+6) 2 | rel_item | число элементов в таблице расположения сегментов |
(+8) 2 | hdr_size | размер заголовка файла в параграфах (длина параграфа — 16 байт) |
(+10) 2 | min_mem | минимальное количество памяти в параграфах, которое нужно зарезервировать в памяти за концом загруженной программы |
(+12) 2 | max_mem | максимальное количество памяти в параграфах, которое нужно зарезервировать в памяти за концом загруженной программы |
(+14) 2 | ss_reg | величина смещения от начала программы, которая используется для загрузки сегментного регистра стека SS |
(+16) 2 | sp_reg | величина смещения от начала программы, которая используется для загрузки регистра SP |
(+18) 2 | chk_summ | контрольная сумма всех слов в файле |
(+20) 2 | ip_reg | значение для регистра IP, которое будет использовано при начальном запуске программы |
(+22) 2 | cs_reg | смещение от начала программы для установки сегментного регистра кода CS |
(+24) 2 | relt_off | смещение от начала файла таблицы расположения сегментов программы |
(+26) 2 | overlay | номер оверлея, равен 0 для основного модуля |
Таблица расположения сегментов программы начинается сразу после форматированной области и состоит из четырехбайтовых значений в формате «смещение:сегмент».
Область файла после таблицы расположения сегментов выравнивается на границу параграфа с помощью байта-заполнителя, и дальше начинается сама программа.
В файле sysp.h есть описание заголовка файла и таблицы расположения сегментов, которые вы можете использовать при обработке заголовка EXE-файла:
В качестве примера приведем программу, которая считывает форматированную часть заголовка EXE-файла, проверяет наличие в его первых двух байтах признака EXE-формата (‘MZ’). Если признак имеется, программа выводит на экран расшифрованное содержимое заголовка и таблицу перемещений, если такая таблица присутствует. В качестве параметра программе надо при запуске передать имя исследуемого EXE-файла.
Приведенная выше программа для чтения заголовка EXE-файла пользуется функцией get-exeh:
Загрузка COM- и EXE-программ происходит по-разному, однако есть некоторые действия, которые операционная система выполняет в обоих случаях одинаково.
- Определяется наименьший сегментный адрес свободного участка памяти для загрузки программы (обычно DOS загружает программу в младшие адреса памяти, если при редактировании не указана загрузка в старшие адреса).
- Создаются два блока памяти (и, следовательно, два блока MCB, описанные ранее) — блок памяти для переменных среды и блок памяти для PSP и программы.
- Для DOS версии 3.х и старше в блок памяти переменных среды помещается путь файла программы.
- Заполняются поля префикса сегмента программы PSP в соответствии с характеристиками программы (количество памяти, доступное программе, адрес сегмента блока памяти, содержащего переменные среды и т.д.)
- Устанавливается адрес области Disk Transfer Area (DTA) на вторую половину PSP (PSP:0080).
- Анализируются параметры запуска программы на предмет наличия в первых двух параметрах идентификаторов дисковых устройств. По результатам анализа устанавливается содержимое регистра AX при входе в программу. Если первый или второй параметры не содержат правильного идентификатора дискового устройства, то соответственно в регистры AL и AH записывается значение FF.
А дальше действия системы по загрузке программ форматов COM и EXE будут различаться.
Для COM-программ, которые представляют собой двоичный образ односегментной программы, выполняется чтение файла программы с диска и запись его в память по адресу PSP:0100. Вообще говоря, программы типа COM могут состоять из нескольких сегментов, но в этом случае они должны сами управлять содержимым сегментных регистров, используя в качестве базового адреса адрес PSP.
После загрузки файла операционная система для COM-программ выполняет следующие действия:
- сегментные регистры CS, DS, ES, SS устанавливаются на начало PSP;
- регистр SP устанавливается на конец сегмента PSP;
- вся область памяти после PSP распределяется программе;
- в стек записывается слово 0000;
указатель команд IP устанавливается на 100h (начало программы) с помощью команды JMP по адресу PSP:100.
Загрузка EXE-программ происходит значительно сложнее, так как связана с настройкой сегментных адресов:
- Считывается во внутренний буфер DOS форматированная часть заголовка файла.
- Определяется размер загрузочного модуля по формуле:
- Определяется смещение начала загрузочного модуля в EXE-файле как hdr_size*16.
- Вычисляется сегментный адрес для загрузки START_SEG, обычно используется значение PSP+10h.
- Загрузочный модуль считывается в память по адресу START_SEG:0000.
- Сканируются элементы таблицы перемещений, располагающейся в EXE-файле со смещением relt_off.
- Для каждого элемента таблицы:
1. Считывается содержимое элемента таблицы как два двухбайтных слова (OFF,SEG).
2. Вычисляется сегментный адрес ссылки перемещения
3. Выбирается слово по адресу REL_SEG:OFF, к этому слову прибавляется значение START_SEG, затем сумма записывается обратно по тому же адресу.
- Заказывается память для программы, исходя из значений min_mem и max_mem.
- Инициализируются регистры, и программа запускается на выполнение.
При инициализации регистры ES и DS устанавливаются на PSP, регистр AX устанавливается так же, как и для COM-программ, в сегментный регистр стека SS записывается значение START_SEG + ss_reg, а в SP записывается sp_reg.
Для запуска программы в CS записывается START_SEG+cs_reg, а в IP — ip_reg. Такая запись невозможна напрямую, поэтому операционная система сначала записывает в свой стек значение для CS, затем значение для IP и после этого выполняет команду дальнего возврата RETF (команда возврата из дальней процедуры).
Теперь займемся вплотную префиксом программного сегмента PSP. Формат PSP уже был описан ранее, для удобства приведем его еще раз вместе со структурой из файла sysp.h:
(0) 2 | int 20h | двоичный код команды int 20h (программы могут использовать эту команду для завершения своей работы) |
(+2) 2 | mem_top | нижняя граница доступной памяти в системе в параграфах |
(+4) 1 | reserv1 | зарезервировано |
(+5) 5 | call_dsp | команда вызова FAR CALL диспетчера MS-DOS |
(+10) 4 | term_adr | адрес завершения (Terminate Address) |
(+14) 4 | cbrk_adr | адрес обработчика Ctrl-Break |
(+18) 4 | crit_err | адрес обработчика критической ошибки |
(+22) 2 | parn_psp | сегмент PSP программы, запустившей данную программу (программы-родителя) |
(+24) 20 | file_tab | таблица открытых файлов, если здесь находятся байты 0FFH, то таблица не используется |
(+44) 2 | env_seg | сегмент блока памяти, содержащего переменные среды |
(+46) 4 | ss_sp | адрес стека SS:SP программы |
(+50) 2 | max_open | максимальное число открытых файлов |
(+52) 4 | file_tba | адрес таблицы открытых файлов |
(+56) 24 | reserv2 | зарезервировано |
(+80) 3 | disp | диспетчер функций DOS |
(+83) 9 | reserv3 | зарезервировано |
(+92) 16 | fcb1 | форматируется как стандартный FCB, если первый аргумент командной строки содержит правильное имя файла |
(+108) 20 | fcb2 | заполняется для второго аргумента командной строки аналогично fcb1 |
(+128) 1 | p_size | число значащих символов в неформатированной области параметров, либо буфер обмена с диском DTA, назначенный по умолчанию |
(+129) 127 | parm | неформатированная область параметров, заполняется при запуске программы из командной строки |
Программы могут получить из PSP такую информацию, как параметры командной строки при запуске, размер доступной памяти, найти сегмент области переменных среды и т.д.
Как программе узнать адрес своего PSP? Очень просто сделать это для программ, написанных на языке ассемблера: при запуске программы этот адрес передается ей через регистры DS и ES. То есть этот адрес равен DS:0000 или ES:0000 (для COM-программ на PSP указывают также регистры CS и SS).
Для программ, составленных на языке Си, доступна глобальная переменная _psp типа unsigned. Эта переменная содержит сегментный адрес PSP.
В качестве примера приведем текст программы на языке ассемблера, которая выводит на экран передаваемые ей через PSP параметры запуска:
Приведенная ниже программа, составленная на языке Си, определяет адрес своего PSP, затем показывает содержимое некоторых полей из PSP:
Используя поле parn_psp, можно определить адрес PSP родительской программы, то есть программы, запустившей Вашу программу.
Немного о назначении полей term_adr, cbrk_adr, crit_err.
Поле term_adr содержит значение, полученное из таблицы векторов прерываний для вектора 22h. Это адрес программы, которая получает управление, когда текущая программа завершает свою работу. Это может быть, например, COMMAND.COM. Программа может создать свою собственную подпрограмму, которая будет получать управление при завершении работы основной программы. Она может записать свой собственный адрес в вектор 22h, затем запустить другую программу. В таком случае в запущенной программе это поле в ее PSP будет содержать адрес родительской программы. Когда основная программа завершает свою работу, DOS восстанавливает адрес программы завершения в векторе 22h из поля term_adr PSP.
Поле cbrk_adr содержит адрес программы обработки прерывания по нажатию Ctrl-Break из вектора 23h таблицы векторов прерываний. Так как программа может устанавливать свою собственную программу обработки прерывания по Ctrl-Break, DOS при завершении работы программы восстанавливает оригинальное значение из поля cbrk_adr.
Аналогично поле crit_err предназначено для восстановления содержимого вектора 24h — адреса обработчика критических ошибок.
Способы переназначения векторов будут приведены в разделе, посвященном прерываниям.
Конечно, программы, составленные на языке Си, не обязательно должны использовать PSP для доступа к параметрам командной строки и переменным среды. Для этого есть параметры функции main и набор функций типа getenv, putenv и т.п., предназначенных для работы со средой. Но ведь PSP содержит и другую информацию!
Ваша программа может при необходимости запустить другую программу формата EXE или COM. Для ассемблерных программ существует функция 4Bh прерывания INT 21h, для программ, составленных на языке Си — разнообразные функции, входящие в состав стандартной библиотеки. Сначала рассмотрим запуск программ при помощи функции 4Bh прерывания INT 21h.
Содержимое регистров перед вызовом прерывания:
После возврата из прерывания флаг CF устанавливается в 0, если ошибок не было, и в 1 при обнаружении ошибок. Регистр AX в случае наличия ошибок содержит код ошибки:
1 | неверный код подфункции; |
2 | файл запускаемой программы не найден; |
3 | путь не найден; |
4 | слишком много открытых файлов; |
5 | нет доступа; |
8 | нет памяти для загрузки программы; |
10 | длина блока среды больше 32 килобайт; |
11 | плохой формат запускаемого EXE-файла. |
Функция 4Bh прерывания 21h имеет четыре подфункции с номерами от 0 до 3:
загрузить и выполнить программу; | |
1 | загрузить, но не выполнять программу (внутренняя подфункция для DOS 3.х); |
2 | загрузить, но не выполнять программу (внутренняя подфункция для DOS 2.х); |
3 | загрузить программу как оверлей (не создавать PSP). |
Для функции 0 регистры DS:DX должны указывать на полный путь запускаемой программы в формате ASCIIZ ( т.е. текстовая строка, закрытая двоичным нулем). Блок параметров EPB (Exec Parameter Block) в этом случае имеет следующий формат:
(0) 2 | seg_env | сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы |
(+2) 4 | cmd | FAR-адрес строки параметров для запускаемой программы. Эта строка должна иметь такой же формат, как и в PSP, т.е. вначале идет байт со значением, равным количеству символов в строке параметров, а затем — сама строка параметров |
(+6) 4 | fcb1 | адрес блока FCB, который будет помещен в PSP со смещением 5Ch (в PSP помещается блок, а не адрес!) |
(+10) 4 | fcb2 | адрес блока FCB, который будет помещен в PSP со смещением 6Ch. |
Запущенной программе доступны все файлы, открытые родительской программой.
Если родительская программа сама формирует среду для дочерней программы, она должна подготовить новую среду на границе параграфа и поместить значение сегментного адреса в поле seg_env блока EPB.
Приведем простую программу, которая запускает программу с именем PARM.COM из текущего каталога. Программу PARM.COM мы только что рассматривали, эта программа выводит на экран полученные ей в командной строке параметры.
Эта программа использует модель памяти SMALL, и ее загрузочный модуль имеет формат EXE. При редактировании был указан стандартный для Quick C 2.01 размер памяти, требуемый для программы. Если попытаться использовать формат COM в модели TINY, то окажется, что вся память распределена COM-программе и для дочерней программы не осталось места.
Следующая программа освобождает всю неиспользуемую ей память, после чего на освободившееся место загружает программу PARM.COM:
Для изменения размера выделенного программе блока памяти мы использовали функцию 4Ah прерывания 21h.
Подфункции 1 и 2 прерывания 4Bh используются DOS (это внутренние подфункции DOS). Мы приведем недокументированный формат блока EBP для этих функций.
Для подфункнкции 1:
(0) 2 | seg_env | сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы |
(+2) 4 | cmd | FAR-адрес строки параметров для запускаемой программы. |
(+6) 4 | fcb1 | адрес блока FCB, который будет помещен в PSP со смещением 5Ch |
(+10) 4 | fcb2 | адрес блока FCB, который будет помещен в PSP со смещением 6Ch. |
(+14) 4 | ss_sp | это поле будет содержать значение SS:SP после возврата |
(+18) 4 | entry_p | адрес точки входа в загруженную программу (CS:IP) |
Для подфункции 2:
(0) 2 | seg_env | сегментный адрес среды, которая создается родительской программой для запускаемой программы. Если в этом поле находится 0, то для запускаемой программы копируется среда родительской программы |
(+2) 4 | cmd | FAR-адрес строки параметров для запускаемой программы. |
(+6) 4 | fcb1 | адрес блока FCB, который будет помещен в PSP со смещением 5Ch |
(+10) 4 | fcb2 | адрес блока FCB, который будет помещен в PSP со смещением 6Ch. |
Подфункция 3 используется для загрузки программных оверлеев. Оверлей загружается в адресное пространство родительской программы, поэтому DOS не заказывает дополнительной памяти и не строит PSP. Формат EPB для этой подфункции:
(0) 2 | seg_env | сегментный адрес, по которому загружается программа |
(+2) 4 | reloc | фактор перемещения, аналогичен элементу таблицы перемещений в заголовке EXE-файла |
Следующая демонстрационная программа загружает программу PARM.COM_как оверлей без передачи ей управления:
Программа загружается в буфер buff.
Пользователи языка Си имеют в своем распоряжении три возможности запустить программу.
Самый простой способ — использовать функцию system(). Эта функция может выполнить любую команду DOS или любую программу, пакетный файл. Например:
При использовании этой функции должен быть доступен COMMAND.COM. К сожалению, хотя system и возвращает код завершения, по нему нельзя сделать вывод о том, как была выполнена запускаемая программа. Если в качестве аргумента функции будет передано неправильное имя, на экране появится сообщение:
Код возврата в этом случае будет 0 — как будто все нормально!
Другие две возможности запустить программу — использовать функции spawn и exec. Функция spawn и ее разновидности запускают программу как дочерний процесс. Функция exec загружает новую программу как оверлей на место старой и передает ей управление без возврата. После завершения дочерней программе управление будет передано COMMAND.COM или программе, которая запустила родительскую программу.
Семейство функций spawn обеспечивает запуск дочерней программы с родительской или со специально сформированной средой. Кроме того, в файле process.h описаны параметры, которые можно передать функции spawn:
P_WAIT | выполнение родительской программы задерживается до завершения дочерней программы. |
P_NOWAIT | родительская программа продолжает выполнение сразу после запуска дочерней. Этот параметр имеет смысл только для операционных систем OS/2, UNIX, в которых поддерживается мультизадачность. |
P_OVERLAY | загружает программу как оверлей и передает ей управление. Этот режим соответствует функции exec в том смысле, что родительская программа не получит управления после завершения дочерней. |
В качестве примера использования функций запуска программы рассмотрим возможное решение проблемы создания HELP-системы для прикладной программы.
С помощью текстового редактора можно создать справочную базу данных в формате утилиты Microsoft HELPMAKE, затем, запуская в нужный момент диалоговую утилиту работы с базой данных Microsoft Quick Help QH.EXE, можно получить нужную справку.
Утилита QH использует базы данных, описанные в переменной среды HELPFILES. Мы будем использовать либо родительскую среду, где находится значение переменной HELPFILES по умолчанию, либо указывать новое значение для этой переменной.
Приведенная ниже программа используется для получения справки о функции стандартной библиотеки printf, поиск производится в HELP-базе QuickC:
Подробная информация об использовании утилит HELPMAKE и QH приводится в документации на Microsoft C 6.0.
Старые версии DOS (до 2.0) требовали выполнения достаточно сложной процедуры для завершения программы. В начале работы программы необходимо было сохранить адрес PSP, затем, перед завершением работы поместить этот адрес в стек, поместить туда же слово 0000 и выполнить команду дальнего возврата. Управление при этом передается в начало PSP, где находится команда INT 20h.
Для версий DOS, начиная с 2.0, существуют более удобные способы — использование напрямую команды INT 20h или функции 0 прерывания 21h (CS при этом должен указывать на PSP, поэтому этот способ хорош для COM-программ), или функции 4Ch прерывания 21h в любое время и с любым содержимым регистров.
Последний способ рекомендуется для использования и имеет еще то преимущество, что позволяет передать родительской программе (например, COMMAND.COM) код завершения. Этот код доступен для анализа в пакетных файлах командой IF ERRORLEVEL.
Приведенные в книге примеры программ на языке ассемблера содержат директиву .EXIT. Эта директива завершает выполнение программы с помощью функции 4Ch и позволяет передать код завершения.
Если Ваша программа запустила дочернюю программу и та завершилась с передачей кода возврата, то родительская программа может определить этот код с помощью функции 4Dh прерывания 21h. Эта функция возвращает код в регистре AX.
Программа, написанная на языке Си, может завершаться с помощью return в функции main или с помощью exit в любом месте программы. При этом также возможна передача кода возврата.
Существуют еще способы завершения работы программы, при которых программа (или ее часть) остается резидентной в памяти. Это вызов прерывания INT 27H или функции 31h прерывания INT 21h. Об этом будет подробно рассказано в разделе, посвященном резидентным программам.
Dos fn 4bh: выполнить или загрузить программу exec
Выпуск № 231
от 06.09.2005, 22:00
Администратор: | Калашников О.А. |
В рассылке: | Подписчиков: 257, Экспертов: 22 |
В номере: | Вопросов: 3, Ответов: 8 |
Вопрос № 25635: ПРивет многоуважаемые эксперты . У меня почему-то не работает одна процедура она должна сохранять нулевую видео страницу переносом в первую видео страницу. ПООМООГИИТЕЕЕ. Ничего немогу понять. Первая процедура Save_Screen переноси. Вопрос № 25638: Уважаемые экперты! Скажите пожалуйста, как на ASM-е работать с CD-ROM (и подобными до DVD-RW), а именно: 1. Узнать буквы у имеющихся CD-ROM; 2. Проверить наличие компакт диска в приводе; 3. Как считать информацию с диска (файла, дорож. Вопрос № 25639: 1. CSEG segment assume CS:CSEG, DS:CSEG, SS:CSEG org 100h BEGIN: MOV AH, 86h MOV DX,1388h ; задержка 5 секунд INT 15h ; проблема такая: задержка не работает, устанавливается флаг CF в 1, т.е. системный.
Вопрос № 25.635 |
ПРивет многоуважаемые эксперты . У меня почему-то не работает одна процедура она должна сохранять нулевую видео страницу переносом в первую видео страницу. ПООМООГИИТЕЕЕ. Ничего немогу понять. Первая процедура Save_Screen переносит байты из 0 страницы в 1 а вторая процедура Restor_Screen обратно последняя возвращяет белеберду какую-то. Приложение прилагается. Конечно алгоритм ни ахти какой но всё-же . Приложение: |
Отправлен: 01.09.2005, 07:55 Вопрос задал: PRiSon (статус: Посетитель) Всего ответов: 3 Мини-форум вопроса >>> (сообщений: 4) |
Отвечает: Sager Здравствуйте, PRiSon! Адрес первой видеостраницы не 0D800h, а 0В900h. Дальше, ты забыл поставить префикс rep перед movsw, в cx ты ложишь 4000, а надо 2000, так как команда movsw сразу передает по два байта — 2000*2=4000 Вроде все, должно работать. |
Ответ отправил: Sager (статус: 6-ой класс) Отправлен: 01.09.2005, 08:59 |
Отвечает: Калашников О.А. Здравствуйте, PRiSon! Используйте префикс REP вместе с MOVSW. Подробней об этом префиксе и командах работы со строками читайте тут: http://kalashnikoff.ru/Assembler/issues/012.htm — Оптимальный пример копирования экрана можно найти тут: http://kalashnikoff.ru/Assembler/issues/encl/028/DISPLAY.asm.htm ——— Всё отлично. |
Ответ отправил: Калашников О.А. (статус: *Админ) Отправлен: 01.09.2005, 10:35 Оценка за ответ: 5 Комментарий оценки: Спасибо !! Я понимаю что у ВАС самый Оптимальный Вариант но понимаете я хочу сам написать сам помыслить так сказать логитмы и тогдалее. |
Отвечает: newinfo2005 Здравствуйте, PRiSon! Так все нормально,но у тебя всего 3 ошибки. 1.0 стр-ob800h 1 стр-0b900h и т.д. 2.вместо movsw надо rep movsw 3.и в cx надо загрузить 2000 а не 4000 так как ты загружаешь слово а не байт. ——— |
Ответ отправил: newinfo2005 (статус: 5-ый класс) Отправлен: 01.09.2005, 13:15 |
Вопрос № 25.638 |
Уважаемые экперты! Скажите пожалуйста, как на ASM-е работать с CD-ROM (и подобными до DVD-RW), а именно: 1. Узнать буквы у имеющихся CD-ROM; 2. Проверить наличие компакт диска в приводе; 3. Как считать информацию с диска (файла, дорожки) Желательно с исходниками =) |
Отправлен: 01.09.2005, 09:21 Вопрос задал: Акулов Андрей Сергеевич (статус: Посетитель) Всего ответов: 2 Мини-форум вопроса >>> (сообщений: 1) |
Отвечает: Евгений Иванов Здравствуйте, Акулов Андрей Сергеевич! для этого используй ASPI. ——— |
Ответ отправил: Евгений Иванов (статус: Профессор) Отправлен: 01.09.2005, 14:53 |
Отвечает: Стас Здравствуйте, Акулов Андрей Сергеевич! Опять — ГДЕ? В Win32? В DOS? К примеру в DOS это можно сделать прямым программированием IDE и (если установлен) через драйвер CD-ROM. |
Ответ отправил: Стас (статус: Практикант) Отправлен: 02.09.2005, 01:01 |
Вопрос № 25.639 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1. CSEG segment assume CS:CSEG, DS:CSEG, SS:CSEG org 100h MOV AH, 86h ; проблема такая: задержка не работает, устанавливается флаг CF в 1, т.е. системный таймер был занят INT 20h 2. Как пользоваться функцией BIOS int 08h Что означает следующее: 3. Можно ли ассемблерной программой зупустить исполнимый файл. 4. Как работает jna, т.е. в каком случае происходит переход? |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Отправлен: 01.09.2005, 10:07 Вопрос задал: Терсков Алексей Николаевич (статус: Посетитель) Всего ответов: 3 Мини-форум вопроса >>> (сообщений: ) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Отвечает: Калашников О.А. Здравствуйте, Терсков Алексей Николаевич! 3. Запустить исполняемый файл можно, воспользовавшись функцией 4Bh прерывания 21h. Функция требует подготовки. Описание и пример можно найти тут: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ответ отправил: Калашников О.А. (статус: *Админ) Отправлен: 01.09.2005, 10:29 Оценка за ответ: 5 Комментарий оценки: Ну и подготовочка! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Отвечает: Sager Здравствуйте, Терсков Алексей Николаевич! 1) mov ah, 86h mov cx, число_секунд mov dx, число_микросекунд int 15h 3)можно. подробнее читай 29 выпуск калшникова, т.к. здесь вызовом одного прерывания не обойтись — нужно много чего сделать. 5) int 20h; srabotaet if you press 0-6 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ответ отправил: Sager (статус: 6-ой класс) Отправлен: 01.09.2005, 11:11 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Отвечает: newinfo2005 Здравствуйте, Терсков Алексей Николаевич! 1.Я точно сам не знаю,но надо еще указать пользовательский байт в es:bx в AL загрузить 0 2.Да-да вызывается примерно 18.2 раз в секунду,его можно использовать для обработки событий зависищях от времени.А то что ты указал это когда прерывание закончен закончено. Магическая последовательность такова: MOV AL, 20h;послать сигнал Конец-Прерывания Программирование в среде однозадачной операционной системыМИНОБРНАУКИ РОССИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования «ПЕНЗЕНСКАЯ ГОСУДАРСТВЕННАЯ ТЕХНОЛОГИЧЕСКАЯ АКАДЕМИЯ Е.В. Грачева Системное программное обеспечение Персональных ЭВМ доктор технических наук, пофессор зав.кафедрой «Вычислительные машины и системы» доктор технических наук, пофессор кафедры «Информационно-вычислительные системы» Пензенского государственного университета Грачева Е.В. Системное программное обеспечение персональных ЭВМ: Учебнле пособие /Е.В. Грачева – Пенза Учебное пособие подготовлено на кафедре «Вычислительные машины и системы» Пензенской государственной технологической академиии и предназначено для студентов высших учебных заведений,обучающихся поспециальности 230101. Программирование в операционной среде Операционной средой называется набор функций ОС, сервисов и правила обращения к ним. Поскольку каждая операционная система имеет свой набор функций и правил обращения к ним, программирование в операционной среде каждой ОС должно рассматриваться отдельно [1]. Программирование в среде однозадачной операционной системы Программы для MS DOS могут быть одного из двух форматов: COM или EXE. Программы типа COM не могут быть размером более 64 Кб и состоят только из одного сегмента – сегмента кода. Размер программы типа EXE может превышать 64 кб. В современных операционных средах приложения пользуются системными вызовами, число которых превышает 2000, в то время как в MS-DOS подобных функций гораздо меньше. Главным входом большинства функций DOS служит прерывание, вызываемое с помощью команды INT 21h. Параметры функциям DOS передаются через регистры микропроцессора: AX (AH и AL), BX, CX, DX; регистровые пары DS:DX и ES:BX используются в основном при передаче адреса ячейки памяти. Через эти же регистры возвращаются результат работы функции DOS, кроме того могут быть установлены флаги в регистре флагов. Как и любая операционная система, DOS загружает и выполняет программы. При загрузке программы в начале отводимого для нее блока памяти (для СОМ-программ это вся свободная на данный момент память) создается структура данных PSP (префикс программного сегмента) размером 256 байт (100h). Затем DOS создает копию текущего окружения для загружаемой программы, помещает полный путь и имя программы в конец окружения, заполняет поля PSP следующим образом: +00h: слово – CDh 20h – команда INT 20h. Если СОМ-программа завершается командой RETN, управление передается на эту команду. +02h: слово – сегментный адрес первого байта после области памяти, выделенной для программы +04h: байт – не используется DOS +05h: 5 байт – 9Ah F0h FEh 1Dh F0h – команда CALL FAR на абсолютный адрес 000C0h, записанная так, чтобы второй и третий байты составляли слово, равное размеру первого сегмента для СОМ-файлов (в этом примере FEF0h). Введено для совместимости с командой СР/М CALL 5. +0Ah: 4 байта – адрес обработчика INT 22h (выход из программы) +0Eh: 4 байта – адрес обработчика INT 23h (обработчик нажатия Ctrl-Break). +12h: 4 байта – адрес обработчика INT 24h (обработчик критических ошибок) +16h: слово – сегментный адрес PSP процесса, из которого был запущен текущий. +18h: 20 байт – JFT – список открытых идентификаторов, один байт на идентификатор, FFh – конец списка. +2Ch: слово – сегментный адрес копии окружения для процесса. +2Eh: 2 слова – SS:SP процесса при последнем вызове INT 21h. +32h: слово – число элементов JFT (по умолчанию 20). +34h: 4 байта – дальний адрес JFT (по умолчанию PSP:0018). +38h: 4 байта – дальний адрес предыдущего PSP. +3Ch: байт – флаг, указывающий, что консоль находится в состоянии ввода 2-байтного символа. +3Dh: байт – флаг, устанавливаемый функцией В711h прерывания 2Fh (при следующем вызове INT 21h для работы с файлом имя файла будет замечено на полное). +3Eh: слово – не используется в DOS. +40h: слово – версия DOS, которую вернет функция DOS 30h (DOS 5.0+). +42h: 12 байт – не используется в DOS. +50h: 2 байта – CDh 21h – команда INT 21h. +54h: 7 байт – область для расширения первого FCB (FCB, FileControlBlok — это метод работы с файлами, являющийся рудиментом от ранних версий DOS’а. При его использовании можно работать только с файлами в текущем каталоге, причем даже нет возможности сменить каталог (точнее, даже понятия «каталог» в момент создания этих функций вообще не было). Современные программы эти функции не используют. MS-DOS обеспечивает две технологии обслуживания файлов. Первая была разработана при создании версий 1.Х. Эта технология основана на использовании структур данных, называемых блоками управления файлом (FCB). В то время подавляющее большинство компьютеров работало под управлением операционной системы CPM. Блоки FCB обеспечивали совместимость файлов MS-DOS с файлами этой системы. При разработке MS-DOS версий 2.Х, когда была предложена иерархическая структура организации файлов, была разработана вторая технология их обслуживания. Она основана на использовании ссылок на управляющую запись файла и не требует организации FCB. После того, как эта технология была опробована на операционной системе UNIX, она получила широкое распространение.). +5Ch: 16 байт – первый FCB, заполняемый из первого аргумента командной строки. +6Ch: 16 байт – второй FCB, заполняемый из второго аргумента командной строки. +7Ch: 4 байта – не используется в DOS. +80h: 128 байт – командная строка и область DTA по умолчанию. Затем DOS записывает программу в память, начиная с адреса PSP:0100h. Если загружается ЕХЕ-программа, использующая дальние процедуры или сегменты данных, DOS модифицирует эти команды так, чтобы используемые в них сегментные адреса соответствовали сегментным адресам, которые получили эти процедуры и сегменты данных при загрузке программы в память. При запуске СОМ-программы регистры устанавливаются следующим образом: AL = FFh, если первый параметр командной строки содержит неправильное имя диска (например, z:/something), иначе – 00h. АН = FFh, если второй параметр содержит неправильное имя диска, иначе 00h. CS = DS = ES = SS = сегментный адрес PSP. SP = адрес последнего слова в сегменте (обычно FFFEh; меньше, если не хватает памяти). При запуске ЕХЕ-программы регистры SS:SP устанавливаются в соответствии с сегментом стека, определенным в программе, затем в любом случае в стек помещается слово 0000h и выполняется переход на начало программы (PSP:0100h для СОМ, собственная точка входа для ЕХЕ). Все эти действия выполняет одна функция DOS – DOS 4Bh – загрузить и выполнить программу. В качестве параметров этой функции передаются: AL = 00h – загрузить и выполнить; AL = 01h – загрузить и не выполнять; DS:DX – адрес ASCIZ-строки с полным именем программы +00h: слово – сегментный адрес окружения, которое будет скопировано для нового процесса (или 0, если используется текущее окружение) AL = 03h – загрузить как оверлей; +00h: слово – сегментный адрес для загрузки оверлея AL = 05h – подготовиться к выполнению (используется в ОС MS DOS начиная с версии 5.0 и выше) +00h: слово – 00h бит 0 – программа – ЕХЕ +04h: 4 байта – адрес ASCIZ-строки с именем новой программы CF = 0, если операция выполнена, ВХ и DX модифицируются, Как уже отмечалось, прерывание INT 21h (сервис DOS) служит главным входом большинства функций DOS. Программа, запрашивающая сервис DOS, должна подготовить всю необходимую информацию в регистрах и управляющих блоках, указать в регистре AH номер желаемой функции DOS и затем вызвать прерывание INT 21H. В таблице 1 приведены функции прерывания INT 21h. Таблица 1 -Функции прерывания INT21h
Сообщений: 9
|
спасибо! все изменил. как будто все изменилось,после перезагрузки все правильно .. что еще можно попробовать изменить? еще раз спасибо за помощь!
Сообщений: 25030
|
Загрузка дополнительного русификатора была отключена? В config.nt дополнительная строка прописана? Вообще говоря, такая русификация через реестр Windows выполнялась на большом числе компьютеров, и мне ни разу не попадались проблемные случаи. Можно проверить работу русификации через реестр на нескольких разных компьютерах. Возможно, проблема связана с конкретной сборкой Windows. Недавно Igor Korolyov что-то писал про «грязные хаки» в реестре Windows. Исправлено: Simple777, 06.04.15 18:28
Сообщений: 9
|
спасибо за быстрый ответ! мне тоже кажется, что все четко прописано ..
Сообщений: 14935
|
Тут важный нюанс — на русский — можно переключить только правой комбинацией клавиш! И наоборот. Т.е. никакой универсальности — как для виндовских программ. Возможно в этом проблема. Потому что все остальное, если оно настроено, на 32-битной системе должно работать.
Сообщений: 25030
|
Сообщений: 9
|
Сообщений: 25030
|
Не исключено, что в autoexec.nt могли остаться какие-нибудь строчки для загрузки старого русификатора. Можно попробовать загружать приложение через индивидуальные config.nt и autoexec.nt Я однажды несколько часов провозился c одним компом, где тоже были глюки с переключением клавиатуры. В дальнейшем выяснилось, что один «заботливый админ» зачем-то поставил в autoexec.nt (или config.nt) загрузку программы tame, притом глючную версию. Проблема ушла после отключения загрузки tame Так что в файлах конфигурации для DOS-сессий может оказаться что угодно. Исправлено: Simple777, 06.04.15 18:52 MS-DOSОперационные системы MS-DOS, Windows 95, Windows 98 и старое железо компьютера — установка, настройка, использование. MS-DOS 6.22 — установка для игр. Часть 4.Файлы MS-DOS Config.sys и autoexec.bat .Данная статья — продолжение цикла статей об установке MS-DOS 6.22 на жёсткий диск для запуска старых-добрых игр. Мы уже произвели минимальную установку системы на жёсткий диск нашего раритетного железного друга, разобрались с основами работы с памятью системы. В данной статье мы детально рассмотрим файлы CONFIG.SYS и AUTOEXEC.BAT . В результате наших действий на жёстком диске компьютера появятся необходимые системные файлы MS-DOS, драйверы, будут осуществлены настройки системы. Файлы config.sys и autoexec.bat . Как и ранее, прежде, чем приступить к рассмотрению темы, предлагаем вам скачать с нашего сайта архив файлов MS-DOS 6.22 OEM ver. 1.1.zip. Конфигурация config.sys и autoexec.bat.Наши цели и задачи :
В результате у нас получится полноценная операционная система MS-DOS 6.22 rus с поддержкой мыши. Работать в системе нам поможет прекрасный менеджер файлов файловый менеджер Dos Navigator. Уже можно запускать игры. Недостаток — отсутствие звука и поддержки привода CD-ROM. Структура и процесс загрузки EXE-программыСтруктура и процесс загрузки EXE-программы В отличие от COM-программ, EXE-программы могут состоять из нескольких сегментов (кодов, данных, стека). Они могут занимать больше 64Кбайт. EXE-файл имеет заголовок, который используется при его загрузке. Заголовок состоит из форматированной части, содержащей сигнатуру и данные, необходимые для загрузки EXE-файла, и таблицы для настройки адресов (Relocation Table). Таблица состоит из значений в формате сегмент: смещение. К смещениям в загрузочном модуле, на которые указывают значения в таблице, после загрузки программы в память должен быть прибавлен сегментный адрес, с которого загружена программа. При запуске EXE-программы системным загрузчиком (вызовом функции DOS 4Bh) выполняются следующие действия: 1. Определяется сегментный адрес свободного участка памяти, размер которого достаточен для размещения программы. 2. Создается и заполняется блок памяти для переменных среды. 3. Создается блок памяти для PSP и программы (сегмент:0000h – PSP; сегмент+0010h:0000h – программа). В поля PSP заносятся соответствующие значения. 4. Адрес DTA устанавливается равным PSP:0080h. 5. В рабочую область загрузчика считывается форматированная часть заголовка EXE-файла. 6. Вычисляется длина загрузочного модуля по формуле: Size=((PageCnt*512)–(HdrSize*16))–PartPag. 7. Определяется смещение загрузочного модуля в файле, равное HdrSize*16. 8. Вычисляется сегментный адрес (START_SEG) для загрузки – обычно это PSP+10h. 9. Считывается в память загрузочный модуль (начиная с адреса START_SEG:0000). 10. Для каждого входа таблицы настройки: a) читаются слова I_OFF и I_SEG; b) вычисляется RELO_SEG=START_SEG+I_SEG; c) читается слово по адресу RELO_SEG:I_OFF; d) к прочитанному слову прибавляется START_SEG; e) результат запоминается по тому же адресу (RELO_SEG:I_OFF). 11. Распределяется память для программы в соответствии с MaxMem и MinMem. 12. Инициализируются регистры, выполняется программа: b) АХ=результат проверки правильности идентификаторов драйверов, указанных в командной строке; |