Адресация памяти в реальном режиме. Логический и физический адреса.
Адреса бывают логические и физические. Разберем, что это значит.
Адреса в основной памяти, характеризующие реальное расположение данных в физической памяти, называются физическими адресами. Набор физических адресов, с которым работает программа, называют физическим адресным пространством. Иными словами физический адрес это адрес, по которому процессор (или другое устройство) обращаются к RAM, используя шину адреса. Совсем просто можно сказать, что физический адрес это номер байта, к которому мы обращаемся, в адресном пространстве.
Пользовательская программа, которая загружается в память для исполнения, не видит реальных физических адресов, а имеет дело с, так называемыми, логическими адресами. Это нужно, потому что одна и та же программа может быть загружена в разные области памяти, в зависимости от того какие другие программы к этому моменту уже загружены в память. Логические адреса обычно образуются на этапе создания загрузочного модуля программы. Т.е. логический адрес это адрес, который «знает» программа. Набор адресов, используемый программой, называют логическим адресным пространством
В процессоре должен быть особый узел – блок преобразования адреса (БПА). Программа указывает свой (логический) адрес, он попадает в этот блок, блок что-то с ним делает такое, чтобы из этого адреса сделать физический, и лишь затем такой преобразованный адрес попадает на шину адреса. Это называется отображение логического адреса на физический, или трансляция логического адреса в физический. Способ отображения зависит от режима работы процессора отдельно для реального и отдельно для защищенного режима работы.
Сегментная адресация в реальном режиме.
Реальный режим работы процессора это режим, в котором работало первое поколение процессоров (i8086, i8088), любой современный процессор после включения питания начинает работать в реальном режиме и только потом программно переводится в защищенный режим.
Для работы с памятью используются две шины — шина адреса и шина данных. Физически память устроена таким образом, что возможна адресация как 16-битовых слов, так и отдельных байтов памяти. Кроме того, процессоры начиная с i80386 могут адресовать 32-битовые слова памяти.
В любом случае так называемый физический адрес передаётся из процессора в память по шине адреса. Ширина шины адреса определяет максимальный объём физической памяти, непосредственно адресуемой процессором. Для 20-разрядной адресной шины процессора i8086 используется двадцать двоичных (или пять шестнадцатеричных) разрядов. Однако все регистры этого процессора являются 16-разрядными. Возникает проблема представления 20-разрядного физического адреса памяти при помощи содержимого 16-разрядных регистров. Максимальное число (данное или адрес), которое можно записать в 16-разрядный регистр, составляет всего 2 16 — 1 = 65535, или 64Кб-1 из нужного нам одного мегабайта.
Для разрешения этой проблемы используется двухкомпонентный логический адрес. Логический адрес состоит из двух 16-разрядных компонент. Такой способ называется сегментной адресацией памяти.
Суть сегментной адресации заключается в следующем. Обращение к памяти осуществляется исключительно с помощью сегментов. Сегментом называется условно выделенная область адресного пространства определённого размера. В реальном режиме процессора всё адресное пространство делится на одинаковые сегменты размером 64Кб.
Физический адрес любой ячейки памяти вычисляется процессором путем сложения начального адреса сегмента (базы сегмента), в котором располагается эта ячейка, со смещением к ней (в байтах) от начала сегмента (рис. 17). Это смещение иногда называют относительным адресом.

Рисунок 17 Образование физического адреса из сегментного адреса и смещения.
Покажем как вычисляется физический адрес–для получения 20-разрядного физического адреса к сегментной компоненте (заносящейся в сегментный регистр) приписывается справа четыре нулевых бита (для расширения до 20 разрядов), затем полученное число складывается с компонентой смещения. Перед сложением к компоненте смещения слева дописывается четыре нулевых бита (также для расширения до 20 разрядов). Эту процедуру иллюстрирует рисунок 18
Р
исунок 18. Вычисление физического адреса в реальном режиме.
Логический адрес принято записывать в шестнадцатеричной форме в виде <сегмент : смещение>.
Например, пусть у нас есть логический адрес 1234h:0123h. Содержимое базового регистра равно 1234h, регистра смещения — 0123h. Вычислим физический адрес, соответствующий нашему логическому адресу:
расширяем до 20 бит сегментную компоненту, дописывая справа 4 нулевых бита, получаем число 12340h;
расширяем до 20 бит компоненту смещения, дописывая слева 4 нулевых бита, получаем число 00123h;
для получения физического адреса складываем полученные числа: 12340h + 00123h = 12463h.
Очевидно, что одному физическому адресу может соответствовать несколько логических. Например, физическому адресу 12463h соответствует логический адрес 1246h:0003h.
Фактически в схеме адресации памяти реального режима вся память как бы разбивается на перекрывающиеся сегменты размером 64Кб. Физический адрес начала сегмента (базовый адрес) равен расширенной до 20 бит сегментной компоненте адреса (расширение выполняется дописыванием справа 4 нулевых бит).
Сегмент может начинаться не с любого физического адреса, а только с такого, который кратен 16 байтам. Деление адресного пространства на фрагменты по 16 байт с которых может начинаться сегмент называется делением на параграфы, поэтому обычно говорят, что сегмент может начинаться только с границы параграфа.
Содержимое сегментного регистра при такой схеме адресации определяет номер сегмента, а компонента смещения является смещением внутри сегменты памяти. Рисунок 19 иллюстрирует сказанное выше.
Рисунок 19. Соответствие логического и физического адресов.
На этом рисунке показано соответствие логического адреса 0002h:0028h физическому адресу 00048h.
Использование сегментной адресации дает дополнительное преимущество при программировании.
Каждой программе выделяется свой собственный сегмент (или даже несколько). Внутри каждого сегмента начинается собственная адресация от нуля — смещение. Таким образом, программист во время кодирования может вообще не заботиться, где именно физически будет размещена программа в памяти.
Операционная система управляет загрузкой и выгрузкой программ примерно так. Свободный сегмент выделяется программе во время загрузки. А после того, как программа завершилась, операционная система снова помечает сегмент как незанятый.
Адреса памяти: физические, виртуальные, логические, линейные, эффективные, гостевые
Мне периодически приходится объяснять разным людям некоторые аспекты архитектуры Intel® IA-32, в том числе замысловатость системы адресации данных в памяти, которая, похоже, реализовала почти все когда-то придуманные идеи. Я решил оформить развёрнутый ответ в этой статье. Надеюсь, что он будет полезен ещё кому-нибудь.
При исполнении машинных инструкций считываются и записываются данные, которые могут находиться в нескольких местах: в регистрах самого процессора, в виде констант, закодированных в инструкции, а также в оперативной памяти. Если данные находятся в памяти, то их положение определяется некоторым числом — адресом. По ряду причин, которые, я надеюсь, станут понятными в процессе чтения этой статьи, исходный адрес, закодированный в инструкции, проходит через несколько преобразований.

На рисунке — сегментация и страничное преобразование адреса, как они выглядели 27 лет назад. Иллюстрация из Intel 80386 Programmers’s Reference Manual 1986 года. Забавно, что в описании рисунка есть аж две опечатки: «80306 Addressing Machanism». В наше время адрес подвергается более сложным преобразованиям, а иллюстрации больше не делают в псевдографике.
Начнём немного с конца — с цели всей цепочки преобразований.
Физический адрес
Эффективный адрес
Эффективный адрес — это начало пути. Он задаётся в аргументах индивидуальной машинной инструкции, и вычисляется из значений регистров, смещений и масштабирующих коэффициентов, заданных в ней явно или неявно.
Например, для инструкции (ассемблер в AT&T-нотации)
addl %eax, 0x11(%ebp, %edx, 8)
эффективный адрес операнда-назначения будет вычислен по формуле:
eff_addr = EBP + EDX * 8 + 0x11
Логический адрес
Без знания номера и параметров сегмента, в котором указан эффективный адрес, последний бесполезен. Сам сегмент выбирается ещё одним числом, именуемым селектором. Пара чисел, записываемая как selector:offset , получила имя логический адрес. Так как активные селекторы хранятся в группе специальных регистров, чаще всего вместо первого числа в паре записывается имя регистра, например, ds:0x11223344.
Здесь обычно у тех, кто столкнулся с этими понятиями впервые, голова начинает идти кругом. Несколько упростить (или усложнить) ситуацию помогает тот факт, что почти всегда выбор селектора (и связанного с ним сегмента) делается исходя из «смысла» доступа. По умолчанию, если в кодировке машинной инструкции не сказано иного, для получения адресов кода используются логические адреса с селектором CS, для данных — с DS, для стека — с SS.
Линейный адрес
Эффективный адрес — это смещение от начала сегмента — его базы. Если сложить базу и эффективный адрес, то получим число, называемое линейным адресом:
lin_addr = segment.base + eff_addr
Преобразование логический → линейный не всегда может быть успешным, так как при его исполнении проверяется несколько условий на свойства сегмента, записанных в полях его дескриптора. Например, проверяется выход за границы сегмента и права доступа.
Сегментация была модной на некотором этапе развития вычислительной техники. В настоящее она почти всюду была заменена другими механизмами, и используется только для специфических задач. Так, в режиме IA-32e (64-битном) только два сегмента могут иметь ненулевую базу. Для остальных четырёх в этом режиме всегда линейный адрес == эффективный.
Что такое виртуальный адрес?
В литературе и в документации других архитектур встречается ещё один термин — виртуальный адрес. Он не используется в документации Intel на IA-32, однако встречается, например, в описании Intel® Itanium, в котором сегментация не используется. Можно смело считать, что для IA-32 виртуальный == линейный.
В советской литературе по вычислительной технике этот вид адресов также именовался математическим.
Страничное преобразование
Однако общая идея всегда одна и та же: линейный адрес разбивается на несколько частей, каждая из которых служит индексом в одной из системных таблиц, хранящихся в памяти. Записи в таблицах — это адреса начала таблицы следующего уровня или, для последнего уровня — искомая информация о физическом адресе страницы в памяти и её свойствах. Самые младшие биты не преобразуются, а используются для адресации внутри найденной страницы. Например, для режима PAE с размером страниц 4 кбайт преобразование выглядит так:

В разных режимах процессора различается число и ёмкость этих таблиц. Преобразование может завершиться неудачей, если очередная таблица не содержит валидных данных, или права доступа, хранящиеся в последней из них, запрещают доступ к странице; например, при записи в регионы, помеченные как «только для чтения», или попытке чтения памяти ядра из непривилегированного процесса.
Гостевой физический
До введения возможностей аппаратной виртуализации в процессорах Intel страничное преобразование было последним в цепочке. Когда же на одной системе работают несколько виртуальных машин, то физические адреса, получаемые в каждой из них, приходится транслировать ещё один раз. Это можно делать программным образом, или же аппаратно, если процессор поддерживает функциональность EPT (англ. Extended Page Table). Адрес, раньше называвшийся физическим, был переименован в гостевой физический для того, чтобы отличать его от настоящего физического. Они связаны с помощью EPT-преобразования. Алгоритм последнего схож с ранее описанным страничным преобразованием: набор связанных таблиц с общим корнем, последний уровень которых определяет, существует ли физическая страница для указанной гостевой физической.
Полная картина
Я попытался собрать все преобразования адреса в одну иллюстрацию. В ней преобразования обозначены стрелками, типы адресов обведены в рамки.

Как уже было сказано выше, каждое из преобразований может вернуть ошибку для адресов, не имеющих представления в следующем по цепочке виде. Устранение подобных проблем — это задача операционных систем и мониторов виртуальных машин, реализующих абстракцию виртуальной памяти.
Адресация памяти
Адресация — осуществление ссылки (обращение) к устройству или элементу данных по его адресу [1] ; установление соответствия между множеством однотипных объектов и множеством их адресов; метод идентификации местоположения объекта [2] .
Содержание
Методы адресации [2]
Адресное пространство
- Простая (англ. flat addressing ) — указание объекта с помощью идентификатора или числа, не имеющего внутренней структуры.
- Расширенная (англ. extended addressing ) — доступ к запоминающему устройству с адресным пространством, бо́льшим диапазона адресов, предусмотренного форматом команды.
- Виртуальная (англ. virtual addressing ) — принцип, при котором каждая программа рассматривается как ограниченное непрерывное поле логической памяти, а адреса этого поля — как виртуальные адреса.
- Ассоциативная (англ. associative addressing ) — точное местоположение данных не указывается, а задаётся значение определённого поля данных, идентифицирующее эти данные (см.: Ассоциативная память).
Исполнение программ
- Статическая (англ. static addressing ) — соответствие между виртуальными и физическими адресами устанавливается до начала и не меняется в ходе выполнения программы.
- Динамическая (англ. dynamic addressing ) — преобразование виртуальных адресов в физические осуществляется в процессе выполнения программы. Программа при этом не зависит от места размещения в физической памяти и может перемещаться в ней в процессе выполнения.
Кодирование адресов
- Явная (англ. explicit addressing ) — адресация путём явного задания адресов в программе.
- Неявная (англ. implied addressing ) — один или несколько операндов или адресов операндов находятся в фиксированных для данной командырегистрах или ячейках памяти и не требуют явного указания в команде.
- Абсолютная (англ. absolute addressing ) — адресная часть команды содержит абсолютный адрес.
- Символическая (англ. symbolic addressing ) — адресная часть команды содержит символический адрес.
Вычисление адресов
- Непосредственная, прямая (англ. immediate (direct) addressing ) — адресная часть команды содержит непосредственный (прямой) адрес; адресация путём указания прямых адресов.
- Косвенная (англ. indirect addressing ) — адресная часть команды содержит косвенный адрес; адресация посредством косвенных адресов.
- Регистровая (англ. register addressing ) — задание адресов операндов в регистрах.
- Базисная (англ. basic addressing ) — вычисление адресов в машинных командах относительно содержимого регистра, указанного в качестве базового.
- Базовая (англ. base-displacement addressing ) — схема вычисления исполнительного адреса, при которой этот адрес является суммой базового адреса и смещения.
- Относительная (англ. relative addressing ) — адресная часть команды содержит относительный адрес.
- Индексная (англ. indexed addressing ) — формирование исполнительного адреса осуществляется путём добавления к базовому адресу содержимого индексного регистра.
- Автодекрементная, автоинкрементная (англ. autodecremental, autoincremental addressing — содержимое регистра индекса изменяется (уменьшается или увеличивается) на некоторое число.
- Постдекрементная, предекрементная, постинкрементная, преинкрементная — автодекрементные и автоинкрементные адресации, при которых уменьшение/увеличение происходит после/до выборки операнда.
- Самоопределяющаяся (англ. self-relative addressing ) — адресная часть команды содержит самоопределяющийся адрес.
- Адресация относительно счётчика команд (англ. program counter relative addressing ) — адреса в команде указываются в виде разности исполнительных адресов и адреса исполняемой команды. Такой способ адресации не требует настройки (см. также: Позиционно-независимый код).
Способы адресации
Подразумеваемый операнд
В команде может не содержаться явных указаний об операнде; в этом случае операнд подразумевается и фактически задается кодом операции команды.
Подразумеваемый адрес
В команде может не содержаться явных указаний об адресе участвующего в операции операнда или адреса, по которому должен быть размещен результат операции, но этот адрес подразумевается.
Непосредственная адресация
В команде содержится не адрес операнда, а непосредственно сам операнд. При непосредственной адресации не требуется обращения к памяти для выборки операнда и ячейки памяти для его хранения. Это способствует уменьшению времени выполнения программы и занимаемого ею объёма памяти. Непосредственная адресация удобна для хранения различного рода констант.
Прямая адресация

Адрес указывается непосредственно в виде некоторого значения, все ячейки располагаются на одной странице. Преимущество этого способа в том, что он самый простой, а недостаток — в том, что разрядность регистров общего назначения процессора должна быть не меньше разрядности шины адреса процессора.
Относительная (базовая) адресация
При этом способе адресации исполнительный адрес определяется как сумма адресного кода команды и базового адреса, как правило хранящегося в специальном регистре — регистре базы.
Относительная адресация позволяет при меньшей длине адресного кода команды обеспечить доступ к любой ячейке памяти. Для этого число разрядов в базовом регистре выбирают таким, чтобы можно было адресовать любую ячейку оперативной памяти, а адресный код команды используют для представления лишь сравнительно короткого «смещения». Смещение определяет положение операнда относительно начала массива, задаваемого базовым адресом.
Укороченная адресация
В адресном поле командного слова содержатся только младшие разряды адресуемой ячейки. Дополнительный указательный регистр.
- Адресация с регистром страницы является примером сокращённой адресации. При этом вся память разбивается на блоки-страницы. Размер страницы диктуется длиной адресного поля.
Регистровая адресация
Регистровая адресация является частным случаем укороченной. Применяется, когда промежуточные результаты хранятся в одном из рабочих регистров центрального процессора. Поскольку регистров значительно меньше чем ячеек памяти, то небольшого адресного поля может хватить для адресации.
Косвенная адресация
Адресный код команды в этом случае указывает адрес ячейки памяти, в которой находится адрес операнда или команды. Косвенная адресация широко используется в малых и микроЭВМ, имеющих короткое машинное слово, для преодоления ограничений короткого формата команды (совместно используются регистровая и косвенная адресация).
Адресация слов переменной длины
Эффективность вычислительных систем, предназначенных для обработки данных, повышается, если имеется возможность выполнять операции со словами переменной длины. В этом случае в машине может быть предусмотрена адресация слов переменной длины, которая обычно реализуется путем указания в команде местоположения в памяти начала слова и его длины.
Стековая адресация
Стековая память, реализующая безадресное задание операндов, особенно широко используется в микропроцессорах и Мини-ЭВМ.
Автоинкрементная и автодекрементная адресации
Поскольку регистровая косвенная адресация требует предварительной загрузки регистра косвенным адресом из оперативной памяти, что связано с потерей времени, такой тип адресации особенно эффективен при обработке массива данных, если имеется механизм автоматического приращения или уменьшения содержимого регистра при каждом обращении к нему. Такой механизм называется соответственно автоинкрементной и автодекрементной адресацией. В этом случае достаточно один раз загрузить в регистр адрес первого обрабатываемого элемента массива, а затем при каждом обращении к регистру в нём будет формироваться адрес следующего элемента массива.
При автоинкрементной адресации сначала содержимое регистра используется как адрес операнда, а затем получает приращение, равное числу байт в элементе массива. При автодекрементной адресации сначала содержимое указанного в команде регистра уменьшается на число байт в элементе массива, а затем используется как адрес операнда.
Автоинкрементная и автодекрементная адресации могут рассматриваться как упрощенный вариант индексации — весьма важного механизма преобразования адресных частей команд и организации вычислительных циклов, поэтому их часто называют автоиндексацией.
Индексация
Для реализуемых на ЭВМ методов решения математических задач и обработки данных характерна цикличность вычислительных процессов, когда одни и те же процедуры выполняются над различными операндами, упорядоченно расположенными в памяти. Поскольку операнды, обрабатываемые при повторениях цикла, имеют разные адреса, без использования индексации требовалось бы для каждого повторения составлять свою последовательность команд, отличающихся адресными частями.
Программирование циклов существенно упрощается, если после каждого выполнения цикла обеспечено автоматическое изменение в соответствующих командах их адресных частей согласно расположению в памяти обрабатываемых операндов. Такой процесс называется модификацией команд, и основан на возможности выполнения над кодами команд арифметических и логических операций.
ФОРМИРОВАНИЕ ФИЗИЧЕСКОГО АДРЕСА В РЕАЛЬНОМ РЕЖИМЕ РАБОТЫ
Микропроцессор способен работать в двух основных режимах: реальном и защищенном.
При работе в реальном режиме возможности процессора ограничены: емкость адресуемой памяти составляет 1 Мбайт, отсутствует постраничная организация памяти, сегменты имеют фиксированную длину в 2 16 байт. Этот режим обычно используется на начальном этапе загрузки компьютера для перехода в защищенный режим.
В реальном режиме работы сегментные регистры процессора содержат старшие 16 бит физического адреса начала сегмента. Сдвинутое на 4 разряда влево значение этого регистра дает 20-разрядный базовый адрес сегмента. Физический адрес информации получается путем базового адреса сегмента с 16-разрядным значением смещения в сегменте, формируемого по заданному режиму адресации для операнда или извлекаемому из регистра IP для команды (рис. 3.1). По полученному адресу происходит выборка информации из памяти.

Рис. 3.1. Схема получения физического адреса в реальном режиме работы
ФОРМИРОВАНИЕ ФИЗИЧЕСКОГО АДРЕСА В ЗАЩИЩЕННОМ РЕЖИМЕ РАБОТЫ
Наиболее полно возможности микропроцессора по адресации памяти реализуются при работе в защищенном режиме. Объем адресуемой памяти увеличивается до 4 Гбайт, появляется возможность страничного режима адресации. Сегменты могут иметь переменную длину от 1 байта до 4 Гбайт.
Общая схема формирования физического адреса микропроцессором, работающим в защищенном режиме, представлена на рис. 3.2.
Как уже отмечалось, основой формирования физического адреса служит логический адрес. Он состоит из двух частей: селектора и смещения в сегменте.

Рис. 3.2. Формирование физического адреса при сегментно-страничной организации памяти
Селектор содержится в сегментном регистре микропроцессора и позволяет найти описание сегмента (дескриптор) в таблице дескрипторов. Дескрипторы сегментов хранятся в специальных системных объектах — глобальной (G DT) и локальных (LDT) табл ицах дескрипторов — и содержат описание различных параметров сегмента, в том числе его базовый адрес.
Смещение в сегменте кода, то есть положение выбираемой команды, определяется значением регистра — указателя команд (EIP). Для сегмента данных смещение формируется по заданному в команде режиму адресации операнда.
Сумма базового адреса сегмента и смещения дает так называемый линейный адрес. Если в микропроцессоре используется только сегментированное представление памяти, то полученный линейный адрес является физическим.
Если помимо сегментного включен также и механизм страничного преобразования, то линейный адрес представляется в виде номера виртуальной страницы и смещения в странице. С помощью специальных системных таблиц — каталога таблиц страниц и собственно таблиц страниц — по номеру виртуальной страницы формируется базовый адрес физической страницы. Положение каталога таблиц страниц в памяти определяется системным регистром CR3. Физический адрес вычисляется как сумма полученного из таблицы страниц адреса физической страницы и смещения в странице, полученного из линейного адреса.