Сегментация
Микропроцессор 8086 для формирования 20-разряного физического адреса использует 16-разрядные селекторы сегментов и смещения.
Селекторы сегментов
хранятся в сегментных регистрах (см. подраздел 2.3.2 “Сегментные регистры”). В зависимости от того, с какой целью выполняется обращение к памяти, процессор использует один из четырёх имеющихся селекторов сегментов. Так, если обращение производится для выборки кода команды, используется селектор сегмента кода, хранящийся в регистре CS, а если происходит запись данных в стек – селектор сегмента стека из регистра SS.
Смещение
формируется в процессе выполнения команды и определяет местоположение требуемой информации внутри сегмента. Например, при выборке кода команды производится чтение байта памяти, хранящегося по смещению из регистра IP (см. подраздел 2.3.4 “Указатель инструкции”) в сегменте кода, селектор которого находится в регистре CS. Поскольку смещение является 16-разрядным, размер сегмента ограничен 64 Кбайтами.
Физический адрес
вычисляется путём сложения 16-разрядного смещения с селектором соответствующего сегмента, сдвинутым влево на четыре разряда. Так как селектор сегмента является 16-разрядной величиной, сдвиг преобразует его в 20-разрядное число, младшие четыре разряда которого содержат нули. Схематически это можно представить следующим образом:
-----T----T----T----¬
¦ с м е щ е н и е ¦
L----+----+----+-----
+
-----T----T----T----T----¬
¦ с е л е к т о р ¦0000¦
L----+----+----+----+-----
--------------------------
-----T----T----T----T----¬
¦ физический адрес ¦
L----+----+----+----+-----
Перенос, который может возникнуть из старшего (19-го) разряда физического адреса в процессе сложения, игнорируется[1]. Таким образом, при доступе к слову памяти, расположенному по смещению 000F16 в сегменте с селектором FFFF16, физический адрес младшего байта этого слова будет равен FFFFF16, а старшего – 0000016.
Легко заметить, что для доступа к одной и той же физической ячейке памяти могут использоваться различные комбинации селекторов и смещений.
Например, физический адрес 0100016 может быть получен при селекторе 000016 и смещении 100016, селекторе 010016 и смещении 000016, а также при множестве других значений селекторов и смещений. Подобный подход к формированию физического адреса оказался весьма неудобным и способствует возникновению трудноуловимых ошибок.
Программист работает с логическими адресами, состоящими из селекторов и смещений. Логический адрес записывается в виде “селектор :
смещение”. Большинство машинных инструкций, обращающихся к памяти, позволяют задать только смещение требуемого операнда, а селектор находится в том или ином сегментном регистре. Смещение в таких инструкциях называется эффективным адресом и вычисляется в процессе выполнения команды. Подробно правила вычисления эффективного адреса описаны в подразделе 2.4.1 “Адресация операндов”.
Если данные размещаются в сегменте, селектор которого не загружен в требуемый сегментный регистр, перед выполнением доступа к этим данным необходимо загрузить селектор содержащего их сегмента в тот или иной сегментный регистр.
Команды переходов позволяют указать либо только смещение инструкции, которая должна выполняться следующей, либо и селектор сегмента, и смещение следующей инструкции. В первом случае говорят о ближнем (near) переходе – новая инструкция находится в том же сегменте, что и команда перехода. Во втором случае переход будет дальним (far) – новая инструкция находится в другом сегменте.
В языках высокого уровня имеются понятия ближних и дальних указателей. Ближние указатели состоят только из смещения; подразумевается, что это смещение относится к текущему сегменту данных. Дальние указатели состоят из селектора сегмента и смещения; компилятор, обрабатывая дальние указатели, должен обеспечить загрузку селектора в требуемый сегментный регистр.