Что такое ближние, далекие и огромные указатели?

Кто-нибудь может объяснить мне мне эти указатели с подходящим примером ... и когда эти указатели используются?

27
задан bolov 29 December 2014 в 20:07
поделиться

5 ответов

В прежние времена, согласно руководству Turbo C, ближний указатель состоял всего из 16 бит, когда весь ваш код и данные помещались в один сегмент. Дальний указатель состоял из сегмента и смещения, но нормализация не выполнялась. И огромный указатель автоматически нормализовался. Два дальних указателя предположительно могут указывать на одно и то же место в памяти, но быть разными, тогда как нормализованные огромные указатели, указывающие на одно и то же место в памяти, всегда будут равны.

13
ответ дан 28 November 2019 в 04:33
поделиться

Все материалы этого ответа относятся только к старой модели сегментированной памяти 8086 и 80286.

near: 16-битный указатель, который может адресовать любой байт в 64-килобайтном сегменте.

far: 32-битный указатель, содержащий сегмент и смещение. Обратите внимание, что поскольку сегменты могут перекрываться, два разных дальних указателя могут указывать на один и тот же адрес.

огромный: 32-битный указатель, в котором сегмент «нормализован», так что никакие два дальних указателя не указывают на один и тот же адрес, если только они не имеют одинаковое значение.

ти: напиток с джемом и хлебом.

Это вернет нас к тому, о-о-о-о

и когда эти указатели использовались?

в 1980-х и 90-х годах, пока 32-битная Windows не стала повсеместной,

3
ответ дан 28 November 2019 в 04:33
поделиться

В некоторых архитектурах указатель, который может указывать на каждый объект в системе, будет больше и работать с ним будет медленнее, чем указатель, который может указывать на полезное подмножество вещей. Многие люди дали ответы, связанные с 16-битной архитектурой x86. Различные типы указателей были обычным явлением в 16-битных системах, хотя в 64-битных системах могут снова появиться различия между почти/страхом, в зависимости от того, как они реализованы (я не удивлюсь, если многие системы разработки перейдут на 64-битные указатели для все, несмотря на то, что во многих случаях это будет очень расточительно).

Во многих программах довольно легко разделить использование памяти на две категории: мелкие задачи, которые в сумме составляют довольно небольшое количество данных (64 КБ или 4 ГБ), но будут часто использоваться, и более крупные задачи, которые в сумме могут занимать до гораздо большее количество, но к которым не нужно обращаться так часто. Когда приложению необходимо поработать с частью объекта в области «крупных вещей», оно копирует эту часть в область «мелких вещей», работает с ней и при необходимости записывает обратно.

Некоторые программисты жалуются на необходимость различать «ближнюю» и «дальнюю» память, но во многих случаях такое различие может позволить компиляторам создавать гораздо лучший код.

(примечание: даже во многих 32-битных системах к некоторым областям памяти можно обращаться напрямую без дополнительных инструкций, а к другим областям нельзя.Если, например, на 68000 или ARM один регистр указывает на хранилище глобальных переменных, можно будет напрямую загрузить любую переменную в пределах первых 32 КБ (68000) или 2 КБ (ARM) этого регистра. Для извлечения переменной, хранящейся в другом месте, потребуется дополнительная инструкция для вычисления адреса. Размещение более часто используемых переменных в предпочтительных областях и информирование об этом компилятора позволит более эффективно генерировать код.

2
ответ дан 28 November 2019 в 04:33
поделиться

Первичный пример: Архитектура Intel X86.

Intel 8086 был внутренне 16-битным процессором: все его регистры были 16-битными. Однако адресная шина имела ширину 20 бит (1 МБ). Это означало, что вы не могли хранить весь адрес в регистре, ограничивая вас первыми 64 КБ.

Решение Intel состояло в том, чтобы создать 16-битные «сегментные регистры», содержимое которых будет сдвигаться влево на четыре бита и добавляться к адресу. Например:

DS ("Data Segment") register:  1234 h
DX ("D eXtended") register:   + 5678h
                              ------
Actual address read:           179B8h

Это создало концепцию сегмента 64 КБ. Таким образом, «ближний» указатель будет просто содержимым регистра DX (5678h) и будет недействительным, если регистр DS уже не установлен правильно, в то время как «дальний» указатель будет 32-битным (12345678h, DS, за которым следует DX) и всегда будет работать (но будет медленнее, так как вам нужно будет загрузить два регистра, а затем восстановить регистр DS, когда закончите).

(Как отмечает supercat ниже, смещение для DX, которое переполнилось, будет «перевернуто» до того, как будет добавлено в DS для получения окончательного адреса.Это позволило 16-битным смещениям получить доступ к любому адресу в сегменте 64 КБ, а не только к той части, которая находилась на расстоянии ± 32 КБ от того места, где указывал DX, как это делается в других архитектурах с 16-битной адресацией относительного смещения в некоторых инструкциях.)

Однако обратите внимание, что у вас может быть два «дальних» указателя, которые имеют разные значения, но указывают на один и тот же адрес. Например, дальний указатель 100079B8h указывает на то же место, что и 12345678h. Таким образом, сравнение указателей на дальних указателях было некорректной операцией: указатели могли различаться, но все же указывать на одно и то же место.

Именно здесь я решил, что компьютеры Mac (с процессорами Motorola 68000 в то время) не так уж и плохи, поэтому я упустил важные подсказки. IIRC, они были просто дальними указателями, которые гарантировали, что все перекрывающиеся биты в сегментных регистрах были равны 0, как во втором примере.

У Motorola не было этой проблемы с их процессорами серии 6800, поскольку они были ограничены 64 КБ. или огромные указатели. (Вместо этого их проблема заключалась в том, что на самом деле имели значение только младшие 24 бита адреса, поэтому некоторые программисты (известные как Apple) использовали старшие 8 бит в качестве «флагов указателя», вызывая проблемы, когда адресные шины расширялись до 32 бит (4 ГиБ) .)

Линус Торвальдс просто продержался до 80386, который предлагал «защищенный режим», где адреса были 32-битными, а сегментные регистры были старшей половиной адреса, и никаких дополнений не требовалось, и написал Linux с сначала использовать только защищенный режим, никаких странных сегментов, и именно поэтому у вас нет поддержки ближнего и дальнего указателя в Linux (и почему ни одна компания, разрабатывающая новую архитектуру, никогда не вернется к ним, если им нужна поддержка Linux). И они ели менестрелей Робина, и было много радости. (Ура...)

29
ответ дан 28 November 2019 в 04:33
поделиться

Эта терминология использовалась в 16-битных архитектурах.

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

Указатель NEAR был указателем с 16-битной памятью и ссылался на данные (только) в текущем сегменте данных модулей.

16-битные программы, которым требовалось более 64 КБ данных, могли получить доступ к специальным распределителям, которые возвращали бы указатель FAR, который был идентификатором сегмента данных в старших 16 битах, и указателем на этот сегмент данных в младших 16 битах. биты.

Тем не менее, более крупные программы должны иметь дело с более чем 64 КБ смежных данных. ОГРОМНЫЙ указатель выглядит точно так же, как дальний указатель — он имеет 32-битное хранилище, — но распределитель позаботился о том, чтобы упорядочить диапазон сегментов данных с последовательными идентификаторами, так что, просто увеличивая селектор сегмента данных, можно получить следующий фрагмент данных размером 64 КБ. достиг.

Базовые стандарты языков C и C++ никогда официально не признавали эти концепции в своих моделях памяти — предполагается, что все указатели в программах на C или C++ должны быть одинакового размера. Таким образом, атрибуты NEAR, FAR и HUGE были расширениями, предоставляемыми различными поставщиками компиляторов.

2
ответ дан 28 November 2019 в 04:33
поделиться