Вопрос

Модель памяти C, с использованием арифметического указателя и все, кажется, моделирует плоское адресное пространство. 16-битные компьютеры использовали сегментированный доступ к памяти. Как по этому вопросу имел 16-битные компиляторы C компиляров и моделируют плоский адресной площадкой с точки зрения программиста C? Например, примерно о том, какая инструкция по языку сборки будет соответствовать следующему коду на 8086?

long arr[65536];  // Assume 32 bit longs.
long i;
for(i = 0; i < 65536; i++) {
    arr[i] = i;
}
Это было полезно?

Решение

Как по этому вопросу имел 16-битные компиляторы C компиляров и моделируют плоский адресной площадкой с точки зрения программиста C?

Они этого не сделали. Вместо этого они сделали сегментацию, видимую для программиста в C, расширяя язык, имея несколько типов указателей: near, far, и huge. Отказ А. near Указатель был только смещением, в то время как far и huge Указатели были комбинированным сегментом и смещением. Был возможность компилятора, чтобы установить Модель памяти, что определил, был ли тип указателя по умолчанию был рядом или далеко.

В Windows Code даже сегодня вы часто видите, как Typedefs, как LPCSTR (за const char*). «LP» - это держатель из 16-битных дней; Он стоит за «длинный (дальний) указатель».

Другие советы

Модель памяти C, каким-либо образом не подразумевает плоское адресное пространство. Это никогда не делало. Фактически, Спецификация языка C специально разработана, чтобы разрешить не плоские адресные пространства.

В самой тривиальной реализации с сегментированным адресном пространством размером крупнейшего непрерывного объекта будет ограничен размером сегмента (65536 байт на 16-битной платформе). Это значит, что size_t В такой реализации будет 16 бит, и что ваш код просто не скомпилируется, поскольку вы пытаетесь объявить объект, который имеет больше размера, чем допустимый максимум.

Более сложная реализация будет поддерживать так называемые огромный Модель памяти. Видите ли, вы действительно нет проблем, касающихся непрерывных блоков памяти Любые Размер на сегментированной модели памяти, она просто требует дополнительных усилий в указательной арифметике. Таким образом, в рамках огромной модели памяти реализация приложит эти дополнительные усилия, которые сделают бы код немного медленнее, но в то же время позволил бы выполнить адресные объекты практически любого размера. Итак, ваш код будет скомпилирован идеально в порядке.

Истинные 16-битные среды используют 16 бит-указателей, которые достигают любого адреса. Примеры включают в себя семейство PDP-11, 6800 (6802, 6809, 68HC11) и 8085. Это чистая и эффективная среда, такая же, как простая 32-битная архитектура.

Семья 80x86 вынуждена нам гибридным 16-битным / 20-битным адресном пространством в так называемом «реальном режиме» - родное пространство 8086. Обычный механизм для решения этого был усиливает типы указателей на два основных типа, near (16-битный указатель) и far (32-битный указатель). По умолчанию для кода и указателей данных могут быть установлены на большую массу «моделью памяти»: tiny, small, compact, medium, far, и huge (Некоторые компиляторы не поддерживают все модели).

То tiny Модель памяти полезна для небольших программ, в которых все пространство (Code + Data + Stack) составляет менее 64K. Все указатели (по умолчанию) 16 бит или near; Указатель неявно связан со значением сегмента для всей программы.

То small Модель предполагает, что стек данных + составляет менее 64 кк и в том же сегменте; Сегмент кода содержит только код, поэтому может также иметь до 64K, для максимальной точки памяти 128K. Указатели кода near и неявно связан с CS (сегмент кода). Указатели данных также near и связан с ds (сегмент данных).

То medium Модель имеет до 64К стека данных + (как маленький), но может иметь любое количество кода. Указатели данных являются 16 битами и неявно связаны с сегментом данных. Указатели кода 32 бит far Указатели и имеют значение сегмента в зависимости от того, как линкер настроил группы кодовых групп (бухгалтерия Yucky Hassle).

То compact Модель - это дополнение среды: менее 64К кода, но любое количество данных. Указатели данных есть far и указатели кода near.

В large или huge Модель, подтип указов по умолчанию составляет 32 бит или far. Отказ Главное отличие состоит в том, что огромные указатели всегда нормализуются автоматически, так что увеличение их избежать проблем с 64 КБ. Видеть это.

В DOS 16 бит я не помню, чтобы быть в состоянии сделать это. У вас могут быть несколько вещей, которые были каждаями 64ями (байтами) (потому что сегмент может быть скорректирован, а смещение обнулена), но не помните, если вы можете пересечь границу одним массивом. Плоское пространство памяти, в котором вы могли бы видеть Nilly выделять все, что вы хотите, и добрались до глубины, так как вам понравилось, в массив не произошел, пока мы не могли составлять 32-битные DOS-программы (на процессорах 386 или 486). Возможно, другие операционные системы и компиляторы, отличные от Microsoft, и Borland, могут генерировать плоские массивы, превышающие 64кбайт. Win16 Я не помню эту свободу до того, как Win32 не ударил, возможно, моя память становится ржавым ... В любом случае, вам повезло или богатую мегабайт памяти, машина 256KBYTE или 512KBYTE не было неслыханным. В конце концов, ваша флешпильская фракция мега до 1,44 мега.

Я помню, что конкретная проблема, которую я узнал о DNS, когда вы могли бы загрузить всю базу данных DNS всех зарегистрированных доменных имен на планете, на самом деле вам пришлось поставить свой собственный DNS-сервер, который был почти необходим в то время, чтобы получить веб сайт. Этот файл составлял 35 мегабайт, а мой жесткий диск составлял 100 мэгабайт, плюс DOS и Windows, разжевывая некоторые из них. Вероятно, имел 1 или 2 мега памяти, мог бы сделать 32-битные программы DOS в то время. ЧАСТЬ, если бы я хотел анализировать файл ASCII, который я сделал в нескольких проходах, но каждый пропуск вывод должен был перейти в другой файл, и мне пришлось удалить предыдущий файл, чтобы иметь место на диске для следующего файла. Два дисков на стандартной материнской плате на стандартной материнской плате, один для жесткого диска и один для диска CDROM, здесь снова этот материал не был дешевым, не было много запасных слотов ISA, если бы вы могли позволить себе еще один жесткий диск и карту диска контроллера.

Была даже проблема чтения 64KBYTES с C, с которым вы пропустили Lhead количество байтов, которые вы хотели прочитать в 16 бит, что означало от 0 до 65535 не 65536 байтов, а производительность резко упала, если вы не читали в разных секторах, так что вы Просто прочитайте 32KBYTES за раз, чтобы максимизировать производительность, 64K не пришел до плохо в дос32 дня, когда вы, наконец, были убеждены, что стоимость, передаваемая FREAD, теперь было 32 битовым номером, и компилятор не собирался отрубить верхние 16 битов и только Используйте нижние 16 бит (что часто произошло, если вы использовали достаточно компиляторов / версий). В настоящее время мы страдаем от аналогичных проблем в 32-битном до 64 переходе, поскольку мы с 16 до 32 битного перехода. Что самое интересное, является кодом из таких людей, как я, который узнал, что собирается от 16 до 32 бит, изменял размер, но без знака и без знака и без знаки, поэтому вы адаптировали и редко использовали INT, чтобы ваши программы скомпилировали и работали на И 16 и 32 бит. (Кодекс от людей от этого поколения вроде выделяется другим людям, которые также проживали через него и использовали ту же трюк). Но для 32-64 перехода это наоборот, а код не из-за использования в использовании деклараций типа UINT32 страдают.

Чтение ответа Уоллека, который только что пришел, огромная указатель, которая завернула вокруг, делает звонок в колокол, также не всегда может компилировать для огромных. Маленькая была плоская модель памяти, которой нам удобно сегодня, и, как и с сегодняшним времен, потому что вы не должны беспокоиться о сегментах. Так что это было желаемое для компиляции для маленьких, когда вы могли бы. У вас все еще не было много памяти или диска или дискета, чтобы вы просто не имели дело с данными, которые большими.

И согласиться с другим ответом, сегмент компенсации составлял 8088/8086 Intel. Весь мир еще не доминировал Intel, поэтому были другие платформы, которые просто имели плоское пространство памяти, или использовали другие трюки, возможно, в оборудовании (за пределами процессора), чтобы решить проблему. Из-за сегмента / смещения Intel смогла ездить на 16 бит дольше, чем наверное, должно быть. Сегмент / компенсирование было какое-то крутое и интересное, что вы могли бы сделать с этим, но это было так же большая боль, как и все остальное. Вы либо упростили вашу жизнь и жили в плоском пространстве памяти или постоянно беспокоились о границах сегмента.

Действительно прикрепить размер адреса на старых х86 своего рода хитрый. Вы можете сказать, что его 16 бит, потому что арифметика, которую вы можете выполнить по адресу, должен соответствовать 16 бит-реестре. Вы также можете сказать, что это 32-бит, потому что фактические адреса вычислены против 16-битного регистра общего назначения и 16-битного реестра сегмента (все 32 бита являются значительными). Вы также можете просто сказать, что это 20 бит, потому что регистры сегмента смещены 4 бита влево и добавлены в регистры GP для адресации оборудования.

На самом деле это не имеет значения, что много из них вы выбрали, потому что они все примерно равные приближения аннотации C абстрактной машины. Некоторые компиляторы позволяют выбрать модель памяти, которую вы используете за компиляцию, в то время как другие просто предполагают 32-битные адреса, а затем внимательно проверьте эту операцию, которые могут переоценить 16 битов Emit Inuries, которые обрабатывают этот чехол правильно.

Проверить это Вход в Википедии. О дальних указателях. В основном, можно указать сегмент и смещение, что позволяет перейти в другой сегмент.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top