Лекция 3: Физическая и логическая организация адресного пространства
Логическое адресное пространство
Для адресации операндов в физическом адресном пространстве программы используют логическую адресацию. Процессор автоматически транслирует логические адреса в физические, выдаваемые затем на системную шину.
В архитектуре современных микропроцессоров ЛАП представляется в виде набора элементарных структур: байтов, сегментов и страниц. В микропроцессорах используются следующие варианты организации логического адресного пространства:
Формирование физического адреса в универсальном микропроцессоре при различных режимах работы
Микропроцессор способен работать в двух режимах: реальном и защищенном.
Этот режим обычно используется на начальном этапе загрузки компьютера для перехода в защищенный режим.
В реальном режиме сегментные регистры процессора содержат старшие 16 бит физического адреса начала сегмента. Сдвинутый на 4 разряда влево селектор дает 20-разрядный базовый адрес сегмента. Физический адрес получается путем сложения этого адреса с 16-разрядным значением смещения в сегменте, формируемого по заданному режиму адресации для операнда или извлекаемому из регистра EIP для команды (рис. 3.1). По полученному адресу происходит выборка информации из памяти.
Наиболее полно возможности микропроцессора по адресации памяти реализуются при работе в защищенном режиме. Объем адресуемой памяти увеличивается до 4 Гбайт, появляется возможность страничного режима адресации. Сегменты могут иметь переменную длину от 1 байта до 4 Гбайт.
Структура дескриптора сегмента представлена на рис. 3.3.
Мы будем рассматривать именно структуру, а не формат дескриптора, так как при переходе от микропроцессора i286 к 32-разрядному МП расположение отдельных полей дескриптора потеряло свою стройность и частично стало иметь вид «заплаток», поставленных с целью механического увеличения разрядности этих полей.
32-разрядное поле базового адреса позволяет определить начальный адрес сегмента в любой точке адресного пространства в 2 32 байт (4 Гбайт).
Поле предела (limit) указывает длину сегмента (точнее, длину сегмента минус 1: если в этом поле записан 0, то это означает, что сегмент имеет длину 1) в адресуемых единицах, то есть максимальный размер сегмента равен 2 20 элементов.
Таким образом, сегмент может иметь размер с точностью до 1 байта в диапазоне от 1 байта до 1 Мбайт (при G = 0 ). При объеме страницы в 2 12 = 4 Кбайт можно задать объем сегмента до 4 Гбайт (при G = l ):
Так как в архитектуре IA-32 сегмент может начинаться в произвольной точке адресного пространства и иметь произвольную длину, сегменты в памяти могут частично или полностью перекрываться.
Бит размерности ( Default size ) определяет длину адресов и операндов, используемых в команде по умолчанию:
Конечно, этот бит предназначен не для обычного пользователя, а для системного программиста, применяющего его, например, для отметки сегментов для сбора»мусора» или сегментов, базовые адреса которых нельзя модифицировать. Этот бит доступен только программам, работающим на высшем уровне привилегий. Микропроцессор в своей работе его не меняет и не использует.
Байт доступа определяет основные правила обращения с сегментом.
Возникает особый случай неприсутствия сегмента. При этом операционная система копирует запрошенный сегмент с диска в память (при этом, возможно, удаляя другой сегмент), загружает в дескриптор базовый адрес сегмента, устанавливает P = 1 и осуществляет рестарт той команды, которая обратилась к отсутствовавшему в ОЗУ сегменту.
Двухразрядное поле DPL ( Descriptor Privilege Level ) указывает один из четырех возможных (от 0 до 3) уровней привилегий дескриптора, определяющий возможность доступа к сегменту со стороны тех или иных программ (уровень 0 соответствует самому высокому уровню привилегий).
Пусть, например, 1 раз в секунду операционная система в дескрипторах всех сегментов сбрасывает бит А. Если по прошествии некоторого времени необходимо загрузить в оперативную память новый сегмент, места для которого недостаточно, операционная система определяет»кандидатов» на то, чтобы очистить часть оперативной памяти, среди тех сегментов, в дескрипторах которых бит А до этого момента не был установлен в»1″, то есть к которым не было обращения за последнее время.
Сумма извлеченного из дескриптора начального адреса сегмента и сформированного смещения в сегменте дает линейный адрес (ЛА).
Если в микропроцессоре используется только сегментное представление адресного пространства, то полученный линейный адрес является также и физическим.
Рассмотрим теперь все этапы преобразования логического адреса в физический более подробно.
Адресация памяти
Содержание
Методы адресации [2]
Адресное пространство
Исполнение программ
Кодирование адресов
Вычисление адресов
Способы адресации
Подразумеваемый операнд
В команде может не содержаться явных указаний об операнде; в этом случае операнд подразумевается и фактически задается кодом операции команды.
Подразумеваемый адрес
В команде может не содержаться явных указаний об адресе участвующего в операции операнда или адреса, по которому должен быть размещен результат операции, но этот адрес подразумевается.
Непосредственная адресация
В команде содержится не адрес операнда, а непосредственно сам операнд. При непосредственной адресации не требуется обращения к памяти для выборки операнда и ячейки памяти для его хранения. Это способствует уменьшению времени выполнения программы и занимаемого ею объёма памяти. Непосредственная адресация удобна для хранения различного рода констант.
Прямая адресация
Адрес указывается непосредственно в виде некоторого значения, все ячейки располагаются на одной странице. Преимущество этого способа в том, что он самый простой, а недостаток — в том, что разрядность регистров общего назначения процессора должна быть не меньше разрядности шины адреса процессора.
Относительная (базовая) адресация
При этом способе адресации исполнительный адрес определяется как сумма адресного кода команды и базового адреса, как правило хранящегося в специальном регистре — регистре базы.
Относительная адресация позволяет при меньшей длине адресного кода команды обеспечить доступ к любой ячейке памяти. Для этого число разрядов в базовом регистре выбирают таким, чтобы можно было адресовать любую ячейку оперативной памяти, а адресный код команды используют для представления лишь сравнительно короткого «смещения». Смещение определяет положение операнда относительно начала массива, задаваемого базовым адресом.
Укороченная адресация
В адресном поле командного слова содержатся только младшие разряды адресуемой ячейки. Дополнительный указательный регистр.
Регистровая адресация
Регистровая адресация является частным случаем укороченной. Применяется, когда промежуточные результаты хранятся в одном из рабочих регистров центрального процессора. Поскольку регистров значительно меньше чем ячеек памяти, то небольшого адресного поля может хватить для адресации.
Косвенная адресация
Адресный код команды в этом случае указывает адрес ячейки памяти, в которой находится адрес операнда или команды. Косвенная адресация широко используется в малых и микроЭВМ, имеющих короткое машинное слово, для преодоления ограничений короткого формата команды (совместно используются регистровая и косвенная адресация).
Адресация слов переменной длины
Эффективность вычислительных систем, предназначенных для обработки данных, повышается, если имеется возможность выполнять операции со словами переменной длины. В этом случае в машине может быть предусмотрена адресация слов переменной длины, которая обычно реализуется путем указания в команде местоположения в памяти начала слова и его длины.
Стековая адресация
Стековая память, реализующая безадресное задание операндов, особенно широко используется в микропроцессорах и Мини-ЭВМ.
Автоинкрементная и автодекрементная адресации
Поскольку регистровая косвенная адресация требует предварительной загрузки регистра косвенным адресом из оперативной памяти, что связано с потерей времени, такой тип адресации особенно эффективен при обработке массива данных, если имеется механизм автоматического приращения или уменьшения содержимого регистра при каждом обращении к нему. Такой механизм называется соответственно автоинкрементной и автодекрементной адресацией. В этом случае достаточно один раз загрузить в регистр адрес первого обрабатываемого элемента массива, а затем при каждом обращении к регистру в нём будет формироваться адрес следующего элемента массива.
При автоинкрементной адресации сначала содержимое регистра используется как адрес операнда, а затем получает приращение, равное числу байт в элементе массива. При автодекрементной адресации сначала содержимое указанного в команде регистра уменьшается на число байт в элементе массива, а затем используется как адрес операнда.
Автоинкрементная и автодекрементная адресации могут рассматриваться как упрощенный вариант индексации — весьма важного механизма преобразования адресных частей команд и организации вычислительных циклов, поэтому их часто называют автоиндексацией.
Индексация
Для реализуемых на ЭВМ методов решения математических задач и обработки данных характерна цикличность вычислительных процессов, когда одни и те же процедуры выполняются над различными операндами, упорядоченно расположенными в памяти. Поскольку операнды, обрабатываемые при повторениях цикла, имеют разные адреса, без использования индексации требовалось бы для каждого повторения составлять свою последовательность команд, отличающихся адресными частями.
Программирование циклов существенно упрощается, если после каждого выполнения цикла обеспечено автоматическое изменение в соответствующих командах их адресных частей согласно расположению в памяти обрабатываемых операндов. Такой процесс называется модификацией команд, и основан на возможности выполнения над кодами команд арифметических и логических операций.
Адресация памяти
16-разрядные процессоры могут адресовать память размером в 1 Мб. Но, поскольку сформировать 20-разрядный адрес с помощью 16-разрядных регистров напрямую нельзя, используется сегментация памяти. Вся память делится на перекрывающиеся сегменты по 64 Кб каждый. Базовый адрес каждого сегмента памяти кратен 16 байтам. Для формирования полного адреса используется адрес сегмента, хранящийся в сегментном регистре и смещение внутри сегмента.
Общая схема формирования адреса показана на рисунке ниже.
Все процессоры Intel имеют эту схему адресации к памяти. Исполнительный адрес для них задается в виде
В отличие от задания сегмента, смещение может задаваться несколькими способами, называемыми способами адресации.
Прямая адресация
Прямая адресация предполагает использование в качестве смещения непосредственно заданное значение.
Косвенная адресация
При использовании косвенной адресации, смещение получается из регистра общего назначения. Адресация может производиться только через регистры BX, BP, SI и DI.
Адресация по базе со сдвигом
При использовании адресации по базе со сдвигом, смещение вычисляется как сумма значения регистра и непосредственно заданного значения.
Адресация по базе с индексированием
При использовании адресации по базе со сдвигом, смещение вычисляется как сумма значений двух регистров и непосредственно заданного значения (если оно задано).
32-разрядная адресация
В 32-разрядных процессорах Intel добавилась новая схема адресации с использованием всех 32-разрядных регистров общего назначения. В этой схеме адресации смещение вычисляется по следующей формуле:
Полная схема 32-разрядной адресации представлена на рисунке:
Чем ограничен размер адресуемой памяти
С точки зрения программиста память состоит из отдельных ячеек размером в байт (8 бит). Точнее память состоит из битов, но программист может оперировать только отдельными байтами. Если программе нужно изменить значение только одного бита, то она все равно должна считать целый байт, содержащий этот бит.
Т.к. ячеек памяти, в отличие от процессорных регистров, огромное количество, то они не имеют названий как регистры процессора, а имеют просто уникальные числовые адреса, называемые физическими. Таким образом, память это просто огромный массив пронумерованных ячеек (нумерация начинается с нуля).
Вся память делится на оперативную (ОЗУ) (по-английски RAM (Random Access Memory) — устройство с произвольным доступом) и постоянную память (ПЗУ) (ROM (Read Only Memory) — память только для чтения). Если в ОЗУ можно как записывать, так и считывать информацию, то из ПЗУ ее можно только считывать. В ПЗУ расположена BIOS и программа начальной загрузки компьютера (POST). Постоянная и оперативная память находятся в едином пространстве адресов.
Важно помнить, что перед выполнением любая программа должна быть загружена в ОЗУ, только после этого процессор начинает последовательно считывать из нее и выполнять команды. Жесткие диски, дискеты, CD/DVD и прочие носители информации хранят файлы, которые будут выполнены только после того как будут загружены в память, причем образ на носителе информации не всегда соответствует тому образу, который будет перенесен в память. Переносом программы с носителя в память (и обратно, если необходимо) занимается операционная система.
Загруженная в память программа всегда отводит под свои нужды отдельный участок памяти, который называется стеком. Стек работает особым образом — данные в него помещаются и извлекаются по принципу LIFO (Last In First Out — «последним вошел– первым вышел»). Стек можно представить в виде стопки листов бумаги (это, кстати, одно из значений английского слова stack) — листы, которые мы положили в стопку последними, сможем забрать первыми, иначе говоря, можем класть и забирать листы только с вершины стопки. Как вы помните, существуют специальные регистры, отведенные для работы со стеком это: SS, ESP, EBP. В системе Intel дно стека всегда расположено в больших адресах памяти, т. е. стек заполняется от максимально возможного адреса к меньшим. Программа и данные заполняют память, начиная с малых адресов памяти к большим. Между стеком и программой с данными существует промежуток из неиспользуемых адресов памяти.
В реальном режиме процессор делит пространство памяти на сегменты по 64 Кбайт (сегментированная модель памяти), в защищенном режиме процессор предоставляет несколько различных моделей памяти, но чаще всего используется самая простая плоская модель памяти (память представляется одним сплошным массивом байтов). Как выглядит образ памяти программы в реальном режиме показано на рис. 3.1 и на рис. 3.2, а плоская модель памяти показана на рис. 3.3.
Рис. 3.1. Образ памяти программы типа COM.
Рис. 3.2. Образ памяти программы типа EXE.
Рис. 3.3. Плоская модель памяти.
Фирме Intel понадобилось в реальном режиме делить память на 64 Кбайт сегменты, т.к. процессоры первого поколения были 16-разрядными, а, следовательно, максимальный размер, который они могли адресовать, составлял всего 2 16 =64 Кбайт. Понятно, что это очень мало, поэтому Intel стала искать способы расширения доступного адресного пространства. Конечно, самый простой способ — это увеличить разрядность процессора (что и было сделано в последующих поколениях), но в первых поколениях процессоров это не позволяла сделать технология, ограничивающая количество элементов на чипе. Поэтому фирма Intel решила использовать специальный встроенный диспетчер памяти, для управления которым были введены известные нам уже сегментные регистры: CS указывал на область ОЗУ в котором располагался код программы, регистр DS отвечал за данные, SS определял расположение стека. А адрес ячейки внутри сегмента стал представлять собой совокупность двух слов, записываемых в программах в виде SSSSh:OOOOh, где SSSSh — адрес сегмента, а OOOOh — относительный адрес (называемый также эффективным), или смещение, который используется для доступа к ячейке внутри сегмента. Адрес, состоящий из сегмента и смещения, называют обычно логическим или виртуальным адресом.
Однако в процессорах первого поколения использовалась 20-разрядная шина адреса, по которой передать значение адреса состоящего из двух слов (32 бита) было невозможно. Поэтому для преобразования 32-х разрядного адреса в 20-разрядный адрес для передачи по шине адреса Intel ввела следующий аппаратный алгоритм: значение сегментного регистра умножается на 16 (10h) или (что то же самое) сдвигается на 4 разряда влево и складывается со значением смещения, в результате получается 20-битный адрес. Например, если 32-разрядный адрес DS:BX, где DS=1234h, BX=5678h, то значение сегментного регистра, умноженное на 16 будет равно 12340h, а физический адрес 12340h+5678h=179B8h.
Таким образом, под физическим адресом понимается адрес памяти, выдаваемый на шину адреса микропроцессора. Другие названия этого адреса — абсолютный адрес, линейный адрес (однако в защищенном режиме физический и линейный адреса — это не одно и то же). Так как физический адрес имеет размерность 20 бит, то максимальное пространство памяти, которое может использовать программа в реальном режиме равно 2 20 =1 Мбайт. Преобразование в физический адрес выполняется на аппаратном уровне, поэтому вручную программисту это делать не требуется, но знать, как в реальном режиме вычисляется физический адрес полезно.
Конечно, в наше время размер 1 Мбайт памяти, который предоставлен программе в реальном режиме, выглядит смешно. Но когда-то это казалось очень много. Ограничение памяти в 1 Мбайт в реальном режиме, также как и в режиме V86 сохранилось до сих пор — об этом следует помнить.
В последующих поколениях процессорах разрядность шины адреса увеличивалась, например в Pentium 4 она составляет 64 бита, но все равно в реальном режиме не зависимо от поколения процессора задействуются только 20 линий, а остальные линии шины адреса в этом режиме просто недоступны. Начиная с процессора 80386, в качестве смещения стало возможно использовать 32-х разрядный адрес.
Таким образом, имея 16-разрядные регистры, удалось увеличить адресное пространство до 1 Мбайт, а данную технологию назвали сегментацией памяти. Конечно, тогда это решение казалось удачным, но с появлением защищенного режима в 32-разрядных процессорах фирма Intel перешла к плоской модели памяти, а сегментную модель памяти пришлось сохранить для обеспечения совместимости с программным обеспечением, созданным под реальный режим работы процессора.
В защищенном режиме появилось еще 4 модели памяти (эти модели памяти недоступны в реальном режиме):
· сегментированная модель памяти (segmented memory model) — подобно тому, как это делается в реальном режиме, в защищенном режиме память может делиться на отдельные пространства адресов, которые называют сегментами. При этом программный код, данные и стек размещаются в отдельных сегментах памяти. Программы в 32-разрядном режиме могут использовать до 16383 сегментов разного размера, каждый из которых может иметь размер 2 32 байт (4 Гбайт). Однако в отличие от реального режима, преобразование логических адресов в физические в сегментированной модели памяти защищенного режима выполняется значительно сложнее. По-прежнему логический адрес формируется при помощи сегментных регистров и регистров, в которых хранятся смещения. Однако сегментные регистры теперь хранят не сегментный адрес, а так называемый селектор (рис. 3.4).
Рис. 3.4. Формат селектора.
Он также содержит16 бит, но теперь имеет более сложную структуру:
· Index — индекс в таблице дескрипторов(его длина13 бит, следовательно в таблице содержится не более 2 13 =8192 дескрипторов).
· TI — если бит установлен, то это селектор в LDT, сброшен в GDT.
· RPL — уровень привилегий запроса.
Индекс селектора (13 бит) указывает на дескриптор в таблице, называемой дескрипторной.
В сегментированной модели памяти защищенного режима используется две дескрипторные таблицы: глобальная (GDT) и локальная(LDT). Тип используемой таблицы определяется битом TI селектора. Таблицы— это просто массивы из дескрипторов. Адреса этих массивов хранятся в системных регистрах: GDTR и LDTR, соответственно.
Селекторы текущих сегментов кода, данных и стека хранятся в регистрах CS, DS и SS соответственно. Таким образом, логический адрес формируется из селектора сегмента и смещения внутри сегмента. Исходя из всего вышеперечисленного схема адресации сегментированной модели памяти защищенного режима будет выглядеть так как показано на рис. 3.5.
Рис. 3.5. Схема преобразования логического адреса в линейный в защищенном режиме адресации.
· страничная модель памяти (paging) — является надстройкой над сегментированной или плоской моделью памяти. В этом режиме память рассматривается как совокупность блоков фиксированного размера (страниц) размером 4 Кбайт. Начиная с 5-го поколения процессоров, появилась возможность увеличения размера страницы до 4 Мбайт. Страничная модель памяти предназначена для организации виртуальной памяти. Благодаря виртуальной памяти программы могут использовать для работы объем памяти больший, чем объем физической памяти. Суть виртуальной памяти заключается в том, что страницы могут выгружаться из физической оперативной памяти на диск (в файл обмена, файл подкачки или swap-файл) и по мере необходимости подкачиваться с него обратно. Через страничное преобразование i386 может адресовать до 4 Гбайт физической памяти и до 64 Тбайт виртуальной памяти. Виртуальная память включается в настройках операционной системы. Разбиение на страницы выполняется на аппаратном уровне и программисту знать подробностей, как правило, не требуется. На программном уровне страничный механизм включается установкой специального бита (PG) в регистре CR0 при помощи привилегированной команды.
· модель памяти в режиме V86. С точки зрения программиста эта модель памяти работает точно также как в обычном реальном режиме. Т.е. память делится на сегменты по 64 Кбайт, ячейки внутри которых адресуются с помощью двух слов, записываемых в виде СЕГМЕНТ:СМЕЩЕНИЕ, максимальная адресуемая память 1 Мбайт и пр. Однако в режиме V86 выполняются все проверки защиты защищенного режима, из-за чего в некоторых случаях не будут работать некоторые инструкции. Особенно это касается инструкций ввода-вывода IN, OUT, (REP) INS, (REP) OUTS и инструкций обработки прерываний: INT n, PUSFF, POPF, STI, CLI и IRET.
. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human.
19 апреля 2011 г.
Архитектура памяти в Windows
Адресное пространство и все, все, все.
(примечание: ну, на самом деле, есть тысяча и один способ адресовать память, но в рамках современного мира и этой статьи мы ограничимся только этим способом).
Как адресное пространство соотносится с вашим исходным кодом
Можно увидеть, как понятия языка высокого уровня («имя», «тип» и «семантика») проецируются в понятия низкого уровня («адрес», «размер» и «атрибуты доступа»).
Древний мир
Виртуальная память и виртуальное адресное пространство
(примечание: по непонятной мне причине, некоторые люди не верят в тот простой факт, что программа может спокойно выделить больше памяти, чем установлено физической памяти в системе; звучит как сюжет для разрушителей легенд (MythBusters)).
Чем чаще системе приходится копировать данные из оперативной памяти в файл подкачки и наоборот, тем больше нагрузка на жесткий диск и тем медленнее работает операционная система (при этом может получиться так, что операционная система будет тратить всё свое время на подкачку памяти, вместо выполнения программ). Поэтому, добавив компьютеру оперативной памяти, вы снизите частоту обращения к жёсткому диску и, тем самым, увеличите общую производительность системы. Кстати, во многих случаях увеличение оперативной памяти дает больший выигрыш в производительности, чем замена старого процессора на новый. А с падением цен на память уже не проблема собрать систему с 16 или 32 Гб оперативной памяти по доступной цене.
Факты о виртуальном адресном пространстве
Почему гранулярность выделения памяти равна именно 64 Кб, а не, скажем, 8 Кб? Ну, на это есть исторические причины.
Это что касается изолированности одной программы от других и от операционной системы. Внутри программы её модули (exe, DLL, bpl) друг от друга, вообще говоря, никак не изолированы. Однако на практике граница всё же появляется, но связана она с языковыми различиями и особенностью управления памятью в разных языках программирования. Но это разговор для другого раза.
Операции, производимые с виртуальной памятью
И снова: какое это имеет отношение к Delphi?
Заметьте, что операции резервирования памяти у Delphi нет, т.к. подобная операции не имеет большого смысла при «упаковке» запросов менеджером памяти. Для работы с резервированием используются функции операционной системы.
Продолжение следует.
Вот и все базовые сведения про устройство памяти в Windows, которые вам нужно знать для начала. В следующий раз мы более близко посмотрим на то, как архитектура памяти соотносится с переменными в ваших программах.


















