В мир информатики # 99 (1 – 15 декабря).
Эксперименты
Как процессор обменивается данными с памятью
Е.А. Еремин,
г. Пермь
Окончание. Начало см. “В
мир информатики” № 96–98 / “Информатика” №
20–22/2007
4. Несколько слов о сегмнтной
адресации и ее роли
В компьютерах типа IBM PC существует
историческая особенность адресации к данным в
16-разрядном режиме. При создании самых первых,
тогда еще 16-разрядных, моделей конструкторы
отчетливо понимали необходимость расширения
адресного пространства. Дело в том, что с помощью
двухбайтового регистра можно непосредственно
адресовать только 216/210 = 26 = 64 Кб
памяти; именно такой объем в основном и
использовался в микрокомпьютерах до появления IBM
PC. Для преодоления этого ограничения инженеры
применили весьма специфическое решение —
формировать 20-разрядный адрес путем сложения
с дополнительным сегментным регистром, причем
значение последнего перед сложением сдвигалось
влево на 4 разряда (младшие четыре при этом всегда
заполнялись нулями, так что получаемое
сегментное значение по-прежнему содержало
только 16 “значащих” бит). В результате
разрядность итогового адреса стала 16 + 4 = 20 бит.
Величина сдвига была выбрана во многом
произвольно, видимо, так, чтобы получить
возможность установить оперативную память
объемом 640 Кб, т.е. увеличив его на порядок.
Говорят, что в это время Билл Гейтс сделал
неосторожное заявление о том, что такого объема
хватит на долгие времена…
Особенность предложенного метода
адресации состоит в том, что если зафиксировать
значение сегментной добавки, то адресовать можно
по-прежнему только некоторый сегмент памяти
размером во все те же 64 Кб. Тем не менее таких
сегментов в оперативной памяти можно
сформировать много. Кроме того, программист в
состоянии менять значения сегментных регистров
с помощью весьма разнообразных инструкций
процессора, тем самым элементарно переходя от
одного сегмента памяти к другому.
В одной из своих книг [1] Питер Нортон
метко назвал сегментный способ словом “клудж”
(по-английски kludge — приспособление для
временного устранения проблемы). С появлением
32-разрядных процессоров (начиная с Intel 80386)
20-разрядная хитрость с сегментами стала
абсолютно ненужной, но из-за проводимой фирмой
Intel политики полной обратной совместимости этот
ненужный “рудимент” жив до сих пор.
Именно по причине постепенного
отмирания данного метода адресации, а также
потому, что, кроме компьютеров типа IBM PC, он нигде
больше не применялся, мы не будем его изучать.
Отметим только одну особенность, которая
объяснит, почему многие числа в приводимых в
наших статьях протоколах выделены наклонным
шрифтом (напомним, что так помечен текст
протокола, который при проведении экспериментов
на вашем компьютере скорее всего будет другим).
В процессорах Intel имеется несколько
сегментных регистров: CS — для определения
кодового (программного) сегмента, DS — для
сегмента данных программы, SS — для стека;
дополнительные сегментные регистры ES, FS и GS
предназначены для создания структур данных,
причем из них только ES используется в конкретных
командах и отображается в Debug (см. любой протокол).
Обычно прикладные программы, особенно несложные,
не меняют значения сегментных регистров и даже
не задают их начальные значения, а получают их
“готовыми” от операционной системы. В этом есть
глубокий смысл: операционная система, занося в
сегментные регистры некоторые значения, тем
самым выделяет программе некоторый сегмент
памяти, за который без необходимости выходить не
стоит. Нетрудно видеть, что для простоты все
сегментные регистры устанавливаются на одно и то
же значение (во всех моих протоколах стоит число
1423), что совмещает все сегменты в единый сегмент
памяти. Для начинающих программистов это весьма
удобное решение.
Наконец, поясним еще одну особенность
записи адресов в Debug. При сегментном методе
каждый адрес представляется в виде двух чисел,
разделенных двоеточием, например, полный адрес
экспериментального массива в моем протоколе
выглядит как 1423:0200 (у вас первое число,
конечно, свое). Число перед двоеточием и есть
соответствующее значение сегментного регистра,
установленное операционной системой. Поскольку
ни в одном из наших экспериментов сегмент не
изменялся, в процессе обсуждения на него можно
просто не обращать внимания (это тем более
удобно, поскольку значения сегментных регистров
у нас могут быть разными).
5. Как получается физический адрес
памяти
После проведения наших экспериментов
мы получили некоторое представление о том, что
каждая задача в отведенной ей области памяти
может использовать весьма гибкий набор методов
адресации. В частности, в наиболее сложных
случаях адрес данных получается как сумма трех
компонент: базового и индексного регистров с
некоторым смещением. Полученное число, которое
позволяет нашей программе найти в своем
собственном адресном пространстве любые данные,
принято называть эффективным адресом. Но
действительно ли мы обращаемся к тем адресам
памяти, которые получаются после суммирования?
Конечно, нет, и тому существует серьезная
причина, именуемая многозадачностью.
Современная операционная система создает каждой
запускаемой программе такие условия, как будто
она одна находится в памяти, поэтому просто
нельзя допустить, чтобы каждая из задач имела
возможность напрямую обращаться к реальным
физическим адресам. Если такой запрет кажется
вам несущественным, попробуйте представить себе,
что может произойти, если три разные программы
начнут одновременно использовать для хранения
своих данных одну и ту же ячейку памяти!
Из предыдущего раздела мы знаем, что в
процессорах с системой команд Intel к полученному
“внутреннему” адресу данных еще добавляется
определенным образом содержимое сегментного
регистра. Полученный в результате адрес называют
линейным адресом. У самой первой модели
процессора (с номером 8086) 20-разрядный линейный
адрес был окончательным результатом и
непосредственно использовался для выборки
данных из физической памяти. Но компьютеры на
базе такого процессора были способны обеспечить
лишь около 1 Мб памяти и функционирование однозадачной
операционной системы, какой являлась MS-DOS.
Чтобы создать техническую базу для
многозадачных систем, описанного механизма
адресации явно недостаточно. Поэтому в
последующих моделях, начиная с 80286 (и особенно с
выходом 32-разрядной 80386), появился новый режим
работы — защищенный (protected mode);
первоначальный однозадачный режим стал
называться реальным (real mode). В защищенном
режиме адресация усложнилась, зато ее
возможности существенно возросли. Для того чтобы
получить некоторое представление о новом режиме,
обратимся к рис. 3.

Рис. 3. Механизмы адресации
процессоров Intel в различных режимах
В левом верхнем углу рисунка
символически изображены механизмы логической
адресации, обсуждавшиеся ранее по таблице
приложения 1 в первой части статьи. Эффективный
адрес, получающийся в результате, в реальном
режиме складывается с содержимым сдвинутого
влево сегментного регистра2 (соответствующая
пунктирная линия на рис. 3 подписана как RM).
В защищенном режиме значение из
сегментного регистра используется не как
составляющая адреса, а в качестве индекса
специальных так называемых таблиц дескрипторов3
(см. на рис. 3 ломаную, образованную точками и
помеченную как PM). Каждый дескриптор содержит
информацию о базовом адресе сегмента памяти и
его границе (т.е. фактически о размере), а также
атрибуты для данной области памяти, такие, как
уровень защиты доступа, способ задания размера
сегмента, и некоторые другие технические
особенности выделенного участка памяти. Нас
сейчас больше всего интересует первый из
названных параметров, который, суммируясь (уже
без всяких сдвигов!) с эффективным адресом,
формирует линейный адрес защищенного режима.
Заметим, что при этом аппаратным образом всегда
производится проверка допустимости полученного
адреса, иначе говоря, осуществляется защита
памяти от некорректного доступа.
Рассмотренный сегментный механизм
преобразования адресов в защищенном режиме
является только первым шагом. Полученный в
результате линейный адрес может быть подвергнут страничному
преобразованию (данный этап не является
обязательным: страничный механизм способен
отключаться). Важной чертой страничного
преобразования является разделение линейного
адреса на две части: младшие 12 бит фиксированны и
фактически служат адресом данных внутри
страницы. Зато остальные (старшие) биты при
помощи специальных таблиц преобразуются, и в
результате из линейного адреса наконец
получается действительный физический адрес
памяти (механизм также предусматривает
аппаратную защиту при доступе к данным). Именно
благодаря страничному механизму в современных
компьютерах реализуется виртуальная память,
объединяющая оперативную память и специальный
файл ее расширения на диске.
Как и сегментный механизм, страничный
позволяет пересчитать одинаковые логические
(эффективные) адреса, принадлежащие разным
задачам, в абсолютно независимые области памяти.
В страничном механизме для этой цели
предусмотрен контрольный регистр процессора CR3,
значение которого обязательно перезагружается
при переключении задач; тем самым, каждая задача
всегда имеет собственные страничные таблицы для
преобразования адресов.
Кратко описанный выше процесс
преобразования логических адресов конкретной
задачи в физические адреса ячеек компьютерной
памяти для наиболее полного случая защищенного
режима обобщен на рис. 4 (все значения адресов
на нем выбраны произвольно).

Рис. 4. Преобразование адресов
отдельной задачи
в физические адреса памяти
Из рис. 4 можно сделать следующие
выводы.
1. Размер и начальные адреса сегментов
произвольны, для страниц они, напротив,
фиксированны.
2. Логическая адресация внутри
отдельных задач произвольна и независима.
3. В линейном пространстве каждая
задача получает собственный участок (если
потребуется, то несколько участков) памяти.
4. При страничной переадресации задаче
независимо от количества фактически требуемых
байт выделяются только фиксированные объемы
памяти (кратные длине страниц); страницы одной
задачи не обязаны находиться в смежных областях
памяти.
Примечание. Фрагментация
страниц памяти, принадлежащих к одной задаче,
имеет такую же природу, как и фрагментация файлов
на интенсивно используемом диске, который разбит
на отдельные кластеры.
Помимо рассмотренных выше реального и
защищенного режимов, в процессорах Intel
существует еще один “промежуточный” режим
работы — режим виртуального процессора 8086 (virtual
8086 mode). Он во многом похож на реальный режим, но
в отличие от последнего допускает
функционирование параллельно выполнению других
задач. Строго говоря, в этом режиме (его
сокращенное обозначение — V86) выполняется
стандартная защищенная задача — имитатор среды
8086, под управлением которой и запускается та или
иная прикладная программа. На языке
пользователей Windows режим V86 принято называть виртуальной
DOS-машиной, а выполняемое под ее управлением
приложение — сеансом MS-DOS. Нетрудно
сообразить, что Debug работает именно в таком
режиме.
Примечание. Возможности
режима V86 шире, чем реального; примером этого, в
частности, служит допустимость в нем 32-разрядной
адресации, которой мы воспользовались в ходе
нашего эксперимента (см. протокол 3).
Особенностью описываемого режима
является отсутствие механизма сегментации
адресов с помощью таблиц дескрипторов. Как видно
из рис. 3, сегментный регистр в V86 используется
точно так же, как и в реальном режиме, а
полученный в результате сложения со сдвигом
адрес сразу передается на страничную
переадресацию (см. сплошные стрелки на рисунке,
помеченные текстом V86M). Благодаря механизму
страничной переадресации процессор способен
создать несколько виртуальных машин, которые к
тому же могут работать параллельно с другими
защищенными приложениями.
Особенности формирования адресов в
различных режимах процессоров семейства Intel
обобщены в следующей таблице, которая в основном
базируется на данных, представленных в [2].
Особенности формирования
адресов
в различных режимах процессоров семейства Intel

Примечание. SMM — System Management
Mode, режим системного управления
(используется при переходе системы в режим
пониженного энергопотребления).
В качестве важного вывода отметим, что
прикладному программисту доступны только методы
формирования логического адреса; обслуживанием
механизмов сегментации и страничной
переадресации занимается операционная система.
Последняя из соображений безопасности стремится
ограничить влияние программ на любые не
относящиеся к ним области памяти,
“монополизируя” для этой цели все механизмы
распределения физической памяти и не допуская к
ним прикладные программы. Именно по этой причине,
пользуясь отладчиком Debug в среде Windows, не удастся
провести какой-либо эксперимент с сегментацией
или страничной переадресацией.
Литература
1. Нортон П., Соухэ Д. Язык
ассемблера для IBM PC. М.: Изд-во “Компьютер”;
“Финансы и статистика”, 1992.
2. Ершова Н.Ю., Соловьев А.В.
Организация вычислительных систем. http://www.intuit.ru/department/hardware/csorg/4/csorg_4.html.
Окончание в следующем номере
2 Полный сегментный регистр состоит из 64
разрядов, но прикладному программисту доступны
только старшие 16 (они выделены сплошной линией).
3 Слово descriptor согласно англо-русскому
компьютерному словарю означает описатель (описание),
паспорт. |