Программы размером более 64 КБ при использовании реального сегментированного режима со сборкой x86 и DOS (16-бит) - PullRequest
2 голосов
/ 08 сентября 2010

Я хотел знать, как вам нужно обрабатывать программы сборки, размер которых превышает 64 КБ, когда вы выполняете 16-битное программирование (сборка) в реальном сегментированном режиме для DOS.В книге, за которой я следую («Язык ассемблера, шаг за шагом» Джеффа Дюнтманна), автор упоминает кое-что об использовании более чем одного сегмента кода (но, к сожалению, не вдаваясь в детали).Я просто хотел знать, как это сделать.Я знаю, что эта модель памяти устарела сейчас, но я просто из любопытства хотела узнать, как вы этого добьетесь.

Ответы [ 4 ]

1 голос
/ 22 января 2013

Сегментный регистр смещает основание доступа к памяти.Адрес в 16-битном режиме рассчитывается следующим образом:

address = ((twenty_bit_t)segment << 4) + offset

, где (мнимый) fifty_bit_t - это тип, длина которого не менее 20 бит.

Адресное пространство в 16-битном вещественномрежим составляет 1 МБ или 20 бит.Сегмент позволяет вам влиять на эти верхние четыре бита и делает это с детализацией 16 байтов (часто называемой «абзацем» в те дни).При добавлении единицы к значению сегмента указатель помещается в память на 16 байт впереди.

Ваше смещение ограничено 16-разрядным значением, поэтому для доступа к нему необходимо было использовать «дальние указатели».Дальний указатель имеет длину 32 бита.Но на самом деле не 32-битные, старшие 16 бит - это просто сегмент, который перекрывает смещение.

Дальние указатели значительно дороже обычных указателей, потому что (с типичными для того времени компиляторами) каждый раз, когда они разыменовываютсядругой указатель он должен был загрузить регистр сегмента.Часто компилятор просто загружал регистры сегментов каждый раз.

Было несколько «моделей» (как мы их тогда называли).В основном это была матрица всех комбинаций указателей на ближний / дальний код, указатели на ближний / дальний данные (и IIRC - способ иметь> 64 КБ глобальных переменных).

Компиляторы обеспечивали детальный контроль над тем, является ли каждый указательдалеко или близко.Это была оптимизация, позволяющая использовать ближний код и близкие данные для кода / данных с большим доступом и добавлять дополнительные директивы расширения для объявления определенных указателей или функций по мере необходимости.

Дальние вызовы и возвраты не были такими серьезнымивлияют на данные, так как указатели разыменовываются гораздо чаще, чем функции.

x86 ЦП имеют специальные инструкции (и префиксы) для обработки дальних вызовов и возвратов и дальних указателей.Даже 32-битные ОС должны как минимум инициализировать регистры сегментов.Некоторые системные инструкции x86 требуют использования сегментных регистров.Однако в 32-битном режиме значение регистров сегмента имеет совершенно другое значение, чем все, что я описал выше.

Связывание и загрузка

Объектные файлыиметь блоки кода и данных, каждый из которых предназначен для входа в определенный сегмент (по имени).Каждый сегмент также помечается как код или данные и т. Д. Компоновщик выясняет, что необходимо, вычисляет, насколько велик каждый сегмент, вычисляет адрес для всего и запоминает расположение любых указателей, которые находятся в исполняемом файле.Операнды дальнего вызова и инициализированные дальние указатели будут вычисляться так, как будто адрес загрузки исполняемого файла равен нулю, и для каждого из них создается запись о перемещении.

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

(Начиная с 286, вычисление адреса фактически стало почти 21-битным - с регистром сегмента с FFFF + смещение FFFF, адрес будет 10FFEF- (1 МБ + 64 КБ - 16 В). HIMEM.SYS на самом деле имеет вызов API для выделения большой памяти, полностью или ничего. Обычно люди позволяют DOS получить ее, поставив DOS = HIGH в свой файл config.sys.)

1 голос
/ 08 сентября 2010

Использование более 64 КБ памяти само по себе не очень сложно (за исключением случаев, когда вам нужно иметь дело со структурами данных, пересекающими границы сегментов - это может быть «забавно»). Если вам нужна только динамическая память, просто используйте указатели FAR 16:16 (seg: ofs).

Вы можете держать DS направленным на ваш основной сегмент данных и использовать ES (или, если выполняется на 80386 или новее, даже в реальном режиме) сегменты данных FS или GS, чтобы удерживать часть сегмента ваших дальних указателей. Вы можете использовать любой регистр общего назначения, который вы хотите для смещенной части, DS: SI и ES: DI являются специальными только при работе со строковыми инструкциями (lods / movs / stos). Кроме того, имейте в виду, что BP и SP по умолчанию используют сегмент SS, если вы не используете явное переопределение сегмента!

Если вам нужно более 64 КБ статических данных программы (вау!), Вам нужен ассемблер с поддержкой сегментов / разделов, и вам, скорее всего, также понадобится выполнить сборку в формате объекта и до ссылка на .exe. Как обрабатывать статические данные далеко указатели будут зависеть от вашего выбора ассемблера, но, скорее всего, будет какое-то ключевое слово для ссылки на часть сегмента переменной.

1 голос
/ 08 сентября 2010

Ну, вы просто пишете верхнее слово вашего рабочего адреса в DS, и вы можете использовать его через DS: DI. Таким образом, вы можете использовать больше до 300-500 КБ оперативной памяти.

0 голосов
/ 24 сентября 2010

Это просто.У вас есть несколько сегментов кода, вероятно распределенных между несколькими оверлейными файлами (обычно .OVL .OVR или .BIN).Вы загружаете нужные вам оверлеи и переходите к ним с помощью быстрого перехода / вызова, который изменяет CS: IP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...