Читайте также:
|
|
COM и EXE программы. Исполняемые программные файлы в MS DOS делятся на два класса:
- многосегментные (.EXE) файлы;
- односегментные (.COM) файлы.
Приведем сравнение этих файлов по четырем характеристикам (табл. 6.1). Загрузка COM программы осуществляется по следующему алгоритму.
1. Распознав.COM файл, настраивающий загрузчик MS DOS запрашивает свободную память.
2. В предоставленную память он размещает PSP.
3. Читает COM файл в PSP + 100h.
4. Устанавливает указатель стека SP в конец сегмента. Если объем сегмента не меньше 64 Кбайт, то в SP будет установлен адрес FFFE.
5. В вершину стека заносится нулевое слово.
6. В DS, ES, SS заносится начало PSP и выдается команда перехода jmp на адрес начала программы (100h). По этой команде в CS будет помещен адрес начала PSP и в IP запишется 100h, что вызовет выполнение команды по CS:100h. Этот адрес, являющийся началом программы, должен содержать выполнимую команду.
Таблица 6.1
Характеристика | EXE файл | COM файл |
Размер | Зависит от количества доступной памяти. При одинаковых командах длина файла.EXE больше длины.COM из-за наличия заголовка в первом | 64 Кбайта, определяемый максимальным значением одного сегмента. |
Точка входа | Где угодно | 100h (конец PSP) |
Стековый сегмент | Требуется | Не допустим. Выделяется от начала PSP. SP устанавливается на конец сегмента. |
Содержимое стекового сегмента при входе | Пусто | Нулевое слово для обеспечения возврата на int 20h |
Атрибут точки входа | FAR | NEAR |
Сегмент данных | Обычно существует отдельный сегмент | Поля данных в кодовом сегменте располагаются обычно после jmp, обходящее эти поля. |
PSP | Вне программы и находится по DS: 0 и ES: 0 | В первых 256 байтах адресуемых через CS, DS, SS и ES. |
Такой способ загрузки позволяет при окончании программы командой RET NEAR (так как PROC выдается с атрибутом NEAR) передать управление на нулевое слово в PSP, где находится команда int 20h, обеспечивающая выход в DOS.
Заголовок EXE файла имеет минимальный размер в 512 байтов. Заголовок состоит из двух частей:
описание EXE файла;
таблица перемещений.
Таблица перемещения предназначена для настройки адресов сегментов во всех полях, где используются длинные адреса (<сегмент>:<смещение> - по записи на Ассемблере, <смещение>:<сегмент> - по расположению в ОП). Эту таблицу создает линкер и размещает перед программными сегментами.
Структура описания EXE файла представляет первый сектор файла (табл. 6.2). Таблица перемещения содержит элементы из двух полей: смещение (смещ.) и относительный адрес сегмента от начала программы в параграфах (смещение). Поскольку EXE файл может быть загружен с любого параграфа памяти, все абсолютные ссылки между сегментами:
- CALL FAR и JMP FAR;
- далекие ссылки (DD <имя переменной в другом сегменте>);
- ссылки типа MOV AX,< имя сегмента >,
в которых присутствует параграф сегмента, должны быть приведены к адресам памяти, соответствующим загрузке.
Линкер на месте адреса сегмента формирует только смещение его от начала размещения модуля в памяти. В элементе перемещения указан относительный адрес в файле сегмента и смещение внутри сегмента расположения сегментной части адресной ссылки.
Загрузка EXE программы осуществляется по следующему алгоритму.
1. Распознав EXE файл, настраивающий загрузчик MS DOS запрашивает свободную память.
2. Создает PSP в начале запрашиваемой памяти.
3. Читает описание EXE файла (первые 1ch байтов) в локальную область памяти.
4. Определяет размер модуля в байтах (число 512-байтовых страниц):
{(смещ.4) * 512 - (смещ.8) * 16 - (смещ.2)},
где (смещ.х) - содержимое поля со смещением х от начала описания.EXE файла; 512 - длина заголовка в параграфах, 16 - число байтов в последнем блоке.
Таблица 6.2
Смещение | Длина | Описание поля |
"Подпись" файла.EXE ('MZ' = 4Dh, 5ah) | ||
Число байтов в последнем блоке.EXE файла | ||
Число 512 - байтовых блоков (страниц), включая заголовок | ||
Число элементов в таблице перемещения | ||
Длина заголовка в параграфах (16-и байтовых блоков) | ||
0ah | Минимум требуемой памяти за концом программы в параграфах | |
0ch | Максимум требуемой памяти за концом программы в параграфах. Если максимум равен 0, то программа загружается в старшие адреса доступной памяти, обеспечивая минимум требуемой памяти за концом программы. Если максимум равен FFFF, то программа загружается с младших адресов. Иные значения обеспечивают максимальное число параграфов за концом программы | |
0eh | Относительный адрес сегмента стека в выполняемом модуле (в параграфах) задает начало стека. Используется для установки SS | |
10h | Значение регистра SP (указателя стека) при запуске. Задает его конец (начальную вершину, которая при записи в стек убывает в направлении SS) | |
12h | Контрольная сумма (отрицательная сумма всех слов в файле) | |
14h | Значение регистра IP (указателя команд) при запуске. Назначается по директиве END | |
16h | Относительный адрес 1-го исполняемого кодового сегмента в параграфах. Используется для установки CS | |
18h | Смещение в файле таблицы перемещения (часто 1ch) | |
1ah | Номер оверлея (0 для главного сегмента, являющегося резидентным) | |
1ch | ? | Обычно начало таблицы перемещения. Начало указано по смещению 18h. Имеет число элементов, указанное по смещению 6 |
? | ? | Пропуск до границы параграфа |
? | ? | Начало образа программы |
5. Определяет начало образа программы в файле в виде файлового смещения (смещение от начала файла): (длина заголовка в параграфах) * 16.
6. Фиксирует стартовый сегмент для загрузки программы (обычно адрес за PSP в параграфах: параграф(PSP) + 10h).
7. Читает образ программы с файлового смещения в ОП по адресу: стартовый сегмент: 0000.
8. Подводит файл на начало таблицы перемещения.
9. Для каждого элемента перемещения:
считывает элемент перемещения как два 16-битных слова (I_смещ, I_сегмент, где I-отличительный признак обозначения);
вычисляет сегмент перемещаемой ссылки в параграфах: стартовый сегмент + I_сегмент;
извлекает слово по адресу: сегмент перемещаемой ссылки:I_смещение, т.е. читает текущее значение;
прибавляет стартовый сегмент к этому слову (выполняет привязку сегмента);
помещает результат обратно по адресу: сегмент перемещаемой ссылки:I_смещение;
10. Распределяет память для программы согласно минимуму и максимуму требуемой памяти за концом программы.
11. Инициализирует регистры и запускает программу:
ES = DS - параграф PSP;
AX - отражает корректность идентификаторов дисков в командной строке;
SS - стартовый сегмент + относительный адрес сегмента стека в параграфах;
SP - значение регистра SP из смещения 10h;
стартовый сегмент + относительный адрес кодового сегмента помещает в стек;
значение регистра IP помещает в стек;
выдает команду RETF, по которой будет передано управление программе, так как эта команда из верхушки стека пересылает слово в IP, следующее слово - в CS и заканчивает выполнение команды.
Эти действия выполняются следующей последовательностью команд ОС:
PUSH сегмент
PUSH OFFSET точка входа
RETF
Распределение стандартной памяти в MS DOS. В младших адресах ОП размещается MD DOS. Затем размещаются резидентные программы по командам DEVICE= из CONFIG.SYS. Далее следует резидентная часть COMMAND.COM. При загрузке программы MS DOS помещает программы, как правило, в младшую область памяти. Обычно это сразу за резидентной частью COMMAND.COM. Чаще всего вся память до верхней границы ОП будет отведена программе (до 640 Кбайт), если в справочнике EXE не указана верхняя граница программы.
Лишнюю часть можно освободить и использовать ее для своих нужд (например, загрузить и запустить другую программу). Драйверы и резидентные программы обязаны всегда освобождать неиспользуемую память, чтобы было куда загружать другие программы. Для этого надо знать необходимую память для своей программы вместе с блоком PSP. Способ определения истинного размера необходимой памяти различен для EXE и COM программ.
Для EXE программы следует включить в программу пустой сегмент, расположив его после всех сегментов. Многие линкеры упорядочивают между собой сегменты по их имени. Поэтому дополнительному пустому сегменту лучше дать имя ZZZ.
После загрузки программы в ОП в ES и DS находится сегментный адрес PSP. Если ES не был модифицирован, то его можно использовать как нижнюю границу программы. Если и DS и ES были модифицированы, адрес PSP можно узнать через функцию 62h прерывания 21h.
Для определения размера программы понадобятся следующие строки:
…
mov AX,ZZZ; сегментный адрес конца программ
mov BX,ES; или mov BX,DS или mov AH,62h и int 21h
sub AX,BX; в AX размер программы в параграфах.
ZZZ Segment; фиктивный сегмент
Дата добавления: 2015-10-02; просмотров: 67 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Загрузка программ для ЭВМ с неявной сегментной адресацией | | | Оверлейные программы |