DOS вставляет адреса сегментов во время выполнения

Я заметил потенциальную ошибку в коде, который я пишу.

Я думал, что если бы я использовал mov ax, seg segment_name, программа могла бы быть непереносимой и работать только на одной машине в определенной конфигурации, поскольку место загрузки может варьироваться от машины к машине.

Поэтому я решил разобрать программу, содержащую только одну эту инструкцию, на двух разных машинах под управлением DOS, и обнаружил, что проблема волшебным образом решена.

Вывод отладки на первой машине: 0C7A:014C B8BB0C MOV AX,0CBB

Вывод отладки на второй машине: 06CA:014C B80B07 MOV AX,070B

После шестнадцатеричного сброса программы я обнаружил, что неизмененные байты на самом деле B84200.

Ручная вставка этих байтов обратно в программу приводит к mov ax, 0042

Значит, формат PE хранит ссылки на эти инструкции и обновляет их во время выполнения?


person My life is a bug.    schedule 18.05.2020    source источник
comment
Это может быть исправлено во время загрузки. В ассемблере это, вероятно, адрес сегмента.   -  person cup    schedule 18.05.2020
comment
Теперь, когда я думаю об этом, это, вероятно, причина, по которой он называется переносимым исполняемым файлом.   -  person My life is a bug.    schedule 18.05.2020
comment
Как DOS загружает программу в память? упоминает этап применения перемещений на основе метаданных объектного файла, но не более подробно, чем ссылка на вики, так что не дубликат.   -  person Peter Cordes    schedule 18.05.2020
comment
16-разрядные файлы DOS .exe не являются переносимыми исполняемыми файлами, они re исполняемые файлы MZ. PE расширяет этот формат, делая его 32- или 64-битным, и, таким образом, предполагает плоскую модель памяти. Исправления во время выполнения в PE относятся к 32- или 64-битным смещенным частям адресов, а не к сегментным частям. (IDK детали формата, возможно, перемещение сегментов все еще поддерживается, но обычно никогда не используется.) Stack Overflow не имеет тега для исполняемых файлов MZ, поэтому я оставлю это для кого-то другого, чтобы разобраться с тегами.   -  person Peter Cordes    schedule 18.05.2020


Ответы (1)


Как заметил Питер Кордес, MS-DOS не использует исполняемый формат PECOFF, который использует Windows. Он имеет собственный формат исполняемого файла "MZ", названный в честь первых двух байтов исполняемого файла, идентифицировать как в этом формате.

Формат MZ поддерживает использование нескольких сегментов через таблицу перемещений, содержащую перемещения. Эти перемещения представляют собой просто значения сегмента:смещения, которые указывают расположение 16-битных значений сегмента, которые необходимо скорректировать в зависимости от того, где в памяти был загружен исполняемый файл. MS-DOS выполняет эти настройки, просто добавляя фактический сегмент загрузки программы к значению, содержащемуся в исполняемом файле. Это означает, что без применения перемещений исполняемый файл будет работать только в том случае, если он загружен в сегмент 0, что невозможно.

Обратите внимание, что это необходимо не только для того, чтобы программа работала на нескольких машинах, но и для того, чтобы одна и та же программа надежно работала на одной и той же машине. Адрес загрузки может меняться в зависимости от различных деталей конфигурации, а также других программ и драйверов, которые уже были загружены в память, поэтому адрес загрузки исполняемого файла MS-DOS практически непредсказуем.

Работая в обратном направлении от вашего примера, мы можем сказать, где ваша примерная программа была загружена в память на обеих машинах. Поскольку 0042h был перемещен в 0CBBh на первой машине и в 070Bh на второй машине, мы знаем, что MS-DOS загрузила вашу программу на две машины в сегментах 0C79h и 06C9h соответственно:

0CBB - 0042 = 0C79
070B - 0042 = 06C9

Исходя из этого, мы можем определить, что исполняемый файл вашего примера имеет запись 0001:014D или эквивалентное значение сегмента: смещение в таблице перемещений:

0C7A:014D - 0C79:0000 = 0001:014D
06CA:014D - 06C9:0000 = 0001:014D

Эта запись указывает на неперемещенное расположение 16-битного непосредственного операнда инструкции mov ax, seg segname, которое необходимо настроить.

person Ross Ridge    schedule 18.05.2020