COM- и EXE-файлы
11.2. COM- и EXE-файлы
Известно, что программные файлы в MS DOS бывают двух видов - файлы с расширениями COM и EXE.
COM-файл - это обязательно программа размером не более 64 Кбайт. Все логические сегменты этой программы (код, данные, стек) помещаются в одном физическом сегменте памяти. COM-файл содержит двоичный код-образ программы, абсолютно идентичный тому образу, который программа будет иметь в оперативной памяти. При загрузке COM-программы система размещает ее сразу вслед за ее PSP (поэтому COM-программа должна начинаться директивой ORG 100h), во все сегментные регистры записывает адрес PSP, и содержимое этих регистров не меняется в ходе выполнения программы.
EXE-программа может иметь любой размер и состоять из нескольких сегментов. Содержимое сегментных регистров меняется в ходе выполнения - в них, как правило, заносятся адреса логических сегментов программы. Поскольку во время трансляции и компоновки не известно, какие абсолютные значения будут иметь эти адреса при размещении программы в памяти, в коде программы эти адреса представляются в виде смещений сегментов относительно начала программы с тем, чтобы при загрузке выполнить настройку обращений к началам сегментов на конкретные адреса памяти. Именно в связи с необходимостью настройки EXE-файл имеет более сложный формат. В начале файла расположен заголовок, который состоит из форматированной части и таблицы перемещений, далее следует сам образ программы. Форматированная часть заголовка EXE-файла описана структурой struct EXEH программы примера 11.3.
Первое слово заголовка содержит обязательно коды букв 'MZ' или 'ZM' - признак EXE-файла (при загрузке программы DOS отличает EXE- от COM-файла не по расширению, а именно по этому признаку). Поле HdrSize определяет размер заголовка (включая таблицу перемещений) в параграфах - смещение в EXE-файле начала программы. Поля PageCnt и LastPage - определяют размер файла программы. Поля ReloCnt и TabOff определяют количество элементов в таблице перемещений и смещение ее начала относительно начала файла.
Поля заголовка MinMem и MaxMem формируются компоновщиками и содержат размер памяти, которую необходимо выделить программе дополнительно к образу, хранящемуся в файле. При загрузке программы система пытается выделить ей MaxMem памяти, если такого ресурса свободной памяти в системе нет - выделяется максимально возможный объем - но не меньше MinMem - иначе загрузка завершается аварийно. (Поскольку COM-файл не имеет заголовка, и система "не знает", сколько памяти ему потребуется, она выделяет такой программе всю свободную память). Поле ChkSum - контрольная сумма всех слов в EXE-файле. Поля ReloSS и ReloCS содержат сегментные смещения относительно начала программы сегментов стека и кода - для установки регистров SS, CS при запуске, поля ExeSP и ExeIP - значения, устанавливаемые при запуске в регистры SP, IP.
Программа примера 11.3. извлекает из собственного заголовка всю необходимую информацию. Чтобы добраться до своего EXE-файла, программа получает адрес своего PSP, из PSP получает адрес своего сегмента окружения, а из окружения - строку вызова, которую и использует как имя файла в операции открытия. Этот файл программа открывает и считывает его начало - форматированную часть заголовка.