13) Эффективный адрес и преобразование адресов.
Три адресных пространства: логическое, линейное и физическое. По сочетанию сегментации и страничной трансляции различают две модели памяти: 1.В сегментной модели памяти приложение использует несколько сегментов памяти (для кода, данных, стека). В этой модели приложение оперирует логическими адресами. 2. В плоской модели памяти приложению для всех целей выделяется единственный сегмент. В этой модели приложение оперирует линейными адресами.
Логический адрес состоит из селектора сегмента Seg и эффективного адреса, называемого также смещением (offset). Логический адрес обозначается в форме Seg:Offset. Селектор сегмента хранится в старших 14 битах сегментного регистра (CS, DS, ES, SS, FS или GS), участвующего в адресации конкретного элемента памяти.Преобразование логического адреса в физический для 32-битных процессоров.
Физический адрес памяти образуется после преобразования линейного адреса блоком страничной трансляции адресов.
Блок страничной трансляции адресов позволяет использовать разрядность физического адреса, отличную от разрядности линейного адреса. В процессорах различных моделей соотношения разрядностей менялись: 1. В 386SX при 32-битном линейном адресе физический был 24-битным (до 16 Мбайт физически адресуемой памяти). 2. В большинстве 32-битных процессоров до 6-го поколения использовался 32-битный физический адрес (до 4 Гбайт физически адресуемой памяти). Формирование адреса памяти процессоров с 64-битным расширением рисунок.
14) Страничная трансляция адресов и виртуальная память
СТА.Механизм сегментации обеспечивает превосходную защиту, но он не очень удобен для реализации виртуальной памяти (подкачки). В дескрипторе сегмента есть бит присутствия, по нему процессор определяет, находится ли данный сегмент в физической памяти или он находится на внешнем запоминающем устройстве (на винчестере). В последнем случае генерируется исключение #11, обработчик которого может подгрузить сегмент в память. Неудобство заключается в том, что различные сегменты могут иметь различную длину. Этого можно избежать, если механизм подкачки реализовывать на основе страничного преобразования. Особенностью этого преобразования является то, что процессор в этом случае оперирует с блоками физической памяти равной длины (4Кбайт) — страницами. Страницы не имеют непосредственного отношения к логической структуре программы.Страничное преобразование действует только в защищенном режиме и включается установкой в 1 бита PG в регистре CR0.
Под виртуализацией памяти понимается метод автоматического управления иерархической памятью. По своей сути виртуализация памяти представляет способ аппаратной и программной реализации концепции иерархической памяти. В рамках идеи виртуализации памяти ОП рассматривается как линейное пространство N адресов, называемое физическим пространством (ФП) памяти. Для задач, где требуется более чем N ячеек, предоставляется значительно большее пространство адресов (обычно равное общей емкости всех видов памяти), называемое виртуальным пространством (ВП).
Страничная организация виртуальной памяти
Страничная организация памяти служит целям преобразования виртуальных адресов в физические. Программа разбивается на части равной величины, называемые страницами. Размер страницы обычно выбирают в пределах 4 – 8 Кбайт (должен быть кратен емкости одного сектора магнитного диска). Виртуальное и физическое адресные пространства разбиваются на блоки размером в страницу. Блок ОП, соответствующий странице, часто называют страничным кадром или фреймом (page frame). Страницам виртуальной и физической памяти присваивают номера.
Команда LEA
Команда LEA в Ассемблере вычисляет эффективный адрес ИСТОЧНИКА и помещает его в ПРИЁМНИК. Синтаксис:
LEA ПРИЁМНИК, ИСТОЧНИК
После выполнения этой команды флаги не изменяются.
Обратите внимание, что ИСТОЧНИКОМ может быть только переменная (ячейка памяти), а ПРИЁМНИКОМ — только регистр (но не сегментный).
Что такое эффективный адрес
Прежде чем продолжить рассказ об инструкции LEA, напомню, что такое эффективный адрес.
Не люблю я иностранные слова — они только путаницу вносят. Но так уж повелось на Руси — если иностранные словечки не употребляешь, значит — лох. В итоге часто люди сами не понимают, что говорят, а исконно русские и понятные слова уже давно забыты и найти подходящую замену иностранному слову бывает непросто (даже мне при всём желании))).
Так вот, слово “эффективный” можно перевести на русский как “действенный”, “действующий”, “настоящий”. Что касается программистской терминологии, то в некоторых источниках вместо “эффективный адрес” встречается словосочетание “текущий адрес” или даже “виртуальный адрес”.
Слишком глубоко в адресацию погружаться не будем. Если вы совершенно далеки от этого, то можете изучить мою контрольную работу по этой теме университетских времён (эх, давно это было…)
Ну а если кратко, то эффективный (текущий) адрес — это
БАЗА + СМЕЩЕНИЕ + ИНДЕКС
где БАЗА — это базовый адрес, находящийся в регистре (при 16-разрядной адресации могут использоваться только регистры BX или BP); СМЕЩЕНИЕ (или ОТКЛОНЕНИЕ — displacement) — это константа (число со знаком), заданная в команде; ИНДЕКС — значение индексного регистра (при 16-разрядной адресации могут использоваться только регистры SI или DI).
Любая из частей эффективного адреса может отсутствовать (например, необязательно указывать СМЕЩЕНИЕ или ИНДЕКС), но обязательно должна присутствовать хотя бы одна часть (например, только БАЗА).
Вычисление эффективного адреса
Ну а теперь чуть подробнее о самой команде LEA. Как уже было сказано, она выполняет вычисление адреса в Ассемблере. В итоге в ПРИЁМНИК записывается адрес памяти (точнее, только смещение).
С помощью команды LEA можно вычислить адрес переменной, которая описана сложным способом адресации (например, по базе с индексированием, что часто используется при работе с массивами и строками).
Если адрес 32-разрядный, а ПРИЁМНИК — 16-разрядный, то старшая половина вычисленного адреса теряется. Если наоборот, ПРИЁМНИК — 32-разрядный, а адрес 16-разрядный, то вычисленное смещение дополняется нулями.
Команда LEA позволяет определить текущее смещение косвенного операнда любого типа. Так как при косвенной адресации может использоваться один или два регистра общего назначения, то приходится каким-то образом вычислять текущее смещение операнда во время выполнения программы.
Команду LEA также удобно применять для определения адреса параметра, находящегося в стеке. Например, если в процедуре определяется локальный массив, то для работы с ним часто необходимо загрузить его смещение в индексный регистр (что как раз таки можно сделать командой LEA).
Оператор OFFSET позволяет определить смещение только при компиляции, и в отличие от него команда LEA может сделать это во время выполнения программы. Хотя в остальных случаях обычно вместо LEA используют MOV и OFFSET, то есть
LEA ПРИЁМНИК, ИСТОЧНИК
это то же самое, что и
MOV ПРИЁМНИК, offset ИСТОЧНИК
При этом следует помнить об указанных выше ограничениях применения оператора OFFSET.
Ещё один пример:
После выполнения этой программы в AX будет записано значение 0104h. Команда LEA занимает 3 байта, команда RET занимает 1 байт. Мы начинаем с адреса 100h, поэтому адрес переменной Х — это 104h (100h + 3 + 1 = 104h). Команда LEA вычислила этот адрес и записала его в указанный регистр (в нашем случае в АХ).
Команда LEA в арифметических операциях
Инструкция LEA часто используется для арифметических операций, таких как умножение и сложение. Преимущество такого способа в том, что команда LEA занимает меньше места, чем команды арифметических операций. Кроме того, в отличие от последних, она не изменяет флаги. Примеры:
Обратите внимание на то, что адресацию со смещением, где используется знак умножения (*), не поддерживает эмулятор emu8086 (возможно, некоторые другие эмуляторы тоже). Поэтому в данном эмуляторе первый пример не будет работать правильно. Второй же пример (сложение), будет работать.
Напоследок, как всегда, о происхождении аббревиатуры LEA.
LEA — Load Effective Address (загрузить эффективный адрес).
Разница между режимами прямой и косвенной адресации
Режимы прямой и косвенной адресации — это разные типы режимов адресации, которые определяют способ доступа к данным из памяти при выполнении инструкций. Основное различие между режимами прямой и косвенной адресации состоит в том, что в прямом режиме адресное поле ссылается непосредственно на ячейку памяти, в которой хранятся данные. В отличие от этого, в косвенном режиме поле адреса сначала ссылается на регистр, который затем направляется в ячейку памяти.
Что такое режим адресации?
Это метод определения операнда инструкции. Основная функция микропроцессора — выполнение группы инструкций, хранящихся в памяти, для выполнения определенной задачи.
Что требуется для операции?
Для операции требуются две вещи — код операции и операнд. Например, если мы хотим вычесть два числа x и y, тогда эти два числа будут операндами, а минус (-) или знак вычитания — оператором.
Сравнительная таблица
Основа для сравнения | Прямая адресация | Косвенная адресация |
---|---|---|
Базовый | Содержит фактический операнд в адресном поле кода инструкции. | Поле адреса инструкции содержит адрес операнда. |
Количество необходимых ссылок на память | Два | Три |
Количество адресного пространства | Маленький | Большой |
Дополнительный расчет | Не требуется | Это единственный способ выполнить операцию. |
Скорость | Больше | Меньше |
Определение прямой адресации
Название Прямая адресация сам по себе дает понять, что он не задействует какой-либо носитель для доступа к данным из памяти. Это наиболее простой метод адресации, при котором поле адреса содержит действующий операнд адреса.
EA = A
Здесь фактический (эффективный адрес) обозначается «EA», который является местоположением, содержащим упомянутый операнд, а «A» обозначает содержимое поля адреса, принадлежащего команде.
Что такое эффективный адрес?
В эффективный адрес — 32-битный адрес, вычисляемый процессором во время выполнения инструкции перехода, доступа к памяти или при получении следующей последовательной инструкции. Для вычисления эффективных адресов, касающихся поиска данных и инструкций, используется 32-битная двоичная арифметика без знака.
Однако в настоящее время прямой метод обычно не используется, поскольку это традиционный метод. Это просто, требуется всего одна ссылка на память и никаких дополнительных вычислений.
пример
Рассмотрим пример инструкции, в которой данные перемещаются из одного места в другое. Таким образом, инструкция MOV A, R1 в микропроцессоре передает содержимое регистра 1 в аккумулятор.
Определение косвенной адресации
В режиме прямой адресации адресное поле требует меньше места для слов, что ограничивает диапазон адресов. Итак, один из способов — иметь адресное поле, ссылающееся на адрес слова в памяти, чтобы хранить полный адрес операнда. Это известно как косвенная адресация. Проще говоря, этот режим адресации использует регистр для хранения фактического адреса, где хранятся данные.
EA = (A)
Здесь «A» в круглых скобках обозначает «содержимое A», а EA — действующий адрес.
Основное достоинство этого подхода заключается в том, что он обеспечивает адресное пространство размером 2 N для длины слова N. Длина слова это количество бит в слове. Хотя в этом методе адресное пространство было увеличено, но для извлечения определенного операнда требуется две ссылки на память. Одна ссылка используется для его адреса, а другая — для получения его значения.
пример
Например, у нас есть регистры R0 и R1 как восьмибитный индекс и DPTR (указатель данных) как 16-битный индекс. Для косвенной адресации используется символ «@» (знак at). Как показано на схеме, инструкция MOV A, @ R0 передает содержимое ячейки памяти, адрес которой хранится в R0, в аккумулятор. В примере значение аккумулятора 07H.
Используя смещение, этот режим адресации также может быть расширен для доступа к структуре данных в памяти пространства данных.Однако расширенная версия косвенной адресации известна как регистр косвенный со смещением.
Вывод
Основное различие между режимом прямой и косвенной адресации заключается в том, что в прямом режиме расположение памяти указывается напрямую. Напротив, в режиме косвенной адресации указывается адрес области основной памяти.
Адреса памяти: физические, виртуальные, логические, линейные, эффективные, гостевые
Мне периодически приходится объяснять разным людям некоторые аспекты архитектуры 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-преобразования. Алгоритм последнего схож с ранее описанным страничным преобразованием: набор связанных таблиц с общим корнем, последний уровень которых определяет, существует ли физическая страница для указанной гостевой физической.
Полная картина
Я попытался собрать все преобразования адреса в одну иллюстрацию. В ней преобразования обозначены стрелками, типы адресов обведены в рамки.
Как уже было сказано выше, каждое из преобразований может вернуть ошибку для адресов, не имеющих представления в следующем по цепочке виде. Устранение подобных проблем — это задача операционных систем и мониторов виртуальных машин, реализующих абстракцию виртуальной памяти.