§ Заголовок файла
Формат хорошо описан в разных источниках, например в Википедии, но я продублирую информацию на сайте.Структура заголовка EXE-файла (все значения 16 битные):
0x00 Signature 0x5A4D ("MZ") 0x02 Extra bytes Кол-во байт в последней странице 0x04 Pages Кол-во полных (или неполных) страниц по 512 байт 0x06 Relocation items Кол-во элементов в таблице релокации 0x08 Header size Размер заголовка в параграфах (16 байт) 0x0A Minimum alloc Кол-во параграфов (исключая PSP и программу), минимальное для работы программы 0x0C Maximum alloc Запрошенное программой количество максимальных параграфов 0x0E Initial SS Сегмент (перемещаемый) для SS 0x10 Initial SP Значение SP после загрузки программы 0x12 Checksum Когда добавляется сумма всех оставшихся слов в файле, результат должен быть 0 0x14 Initial IP Значение IP после запуска 0x16 Initial CS Сегмент (перемещаемый) для CS 0x18 Relocation tbl Абсолютное смещение таблицы релокации 0x1A Overlay word Значение, которые используется для оверлеев. Если равно 0, это главная программа. ---------------------- 0x1C Reseved Зарезервировано 8 байт 0x24 OemId 0x26 OemInfo 0x28 Reserved Зарезервировано 20 байт 0x3C LFANew Адрес Portable Executable заголовкаНачиная с 0x1C, может идти любая информация, которая касается оверлея. Оверлей - это такая программа, которая подгружается по время исполнения основной программы. То есть, как работает оверлей: когда загружается основная программа (у нее overlay word равно 0), то она вызывает особую DOS-функцию, которая может подгружать оверлейные программы.
Таким самым образом, вычисляется CS и SS относительно стартового сегмента (который находится сразу после PSP-блока), а DS и ES устанавливаются на сегмент PSP.
Файл с программой состоит из трех частей:
- Заголовок (занимает 28 байт)
- Таблица релокации
- Образ с программой
- Сначала создается блок PSP (программный сегментный префикс)
- Последовательно в память загружается весь образ с программой
- Из таблицы релокации берутся смещения в образе и проставляются в загруженном образе программы
§ Таблица релокации
Эта таблица содержит элементы, которые состоят из двух машинных слов (16 битное смещение и 16 битный сегмент).Допустим, в заголовке в поле 0x06 содержится число 5. Это значит, что в таблице релокации 5 элементов. Каждый элемент занимает 4 байта (пара смещение и сегмент):
0 offset:segment 1 offset:segment 2 offset:segment 3 offset:segment 4 offset:segmentАбсолютный адрес относительно образа программы (а образ программы идет сразу же за заголовком), вычисляется так: segment*16 + offset. Когда этот адрес вычислен, туда добавляется СЛОВО (16 бит) стартового сегмента. В общем-то, и всё.
§ Пример загрузки программы
Разберем все поля:
Размер файла: 81 Длина образа: 49 Длина в блоках (x 512): 1 Длина образа % 512: 81 Старт данных: 0x20 (32) Min памяти x byte: 512 Max памяти x byte: 1048560 SS: + 0x14 CS: + 0x2 SP: 0x200 IP: 0x0 CRC: 0x0 Адрес таблицы настройки: 0x1c Кол-во эл-тов настройки: 1 Сегмент оверлея: 0x0 0000:0021 == 00000041Каким способом вычисляется длина образа:
- Берется "длина в блоках" (Pages), если же "длина образа" (Extra bytes) != 0, то тогда "длина в блоках" (Pages) уменьшается на 1
- Умножается на 512 полученная длина в блоках
- Добавляется "длина образа" (Extra bytes)
1IF Extra = 0 THEN Size = Pages*512 ELSE Size = (Pages-1)*512 + ExtraВ "Старт данных" записан адрес (0x20), откуда начинается образ данных.
Допустим, что хотим загрузить программу, начиная с базового сегмента 0x2335. Загружаем по адресу:
2335:0000 256 байт PSP 2345:0000 - образ программы -Устанавливается
DS = 2335
, ES = 2335
.Ставится SP = 200h, IP = 0000h.
Вычисляется SS = 14h + (2335h + 10h) = 2359h
Вычисляется CS = 2h + (2335h + 10h) = 2347h