Глава 3. Адресация памяти в защищённом режиме.
Первое, с чем сталкивается программа при переходе в защищённый режим - это совершенно другая система адресации памяти. Для начала, давайте вспомним, как это происходит в режиме реальных адресов - для обращения к памяти используется пара 16-разрядных регистров - сегментный регистр и смещение.
В сегментном регистре находится адрес сегмента. Сегмент - это область памяти размером в 64 Кб, которая должна начинаться на границе параграфа или, другими словами, на 16-байтной границе, то есть сегмент может начинаться только по адресу 0, 16, 32, 48 и т.д. Адресное пространство процессора 8086 равно одному мегабайту - это адреса в диапазоне от 00000h до FFFFFh. Т.к. сегмент начинается по адресу, кратному 16 (10h), то возможные адреса начала сегмента будут 00000h, 00010h, 00020h, ... , FFFF0h. Как видите, информация содержится в старших четырёх шестнадцатеричных разрядах - их и хранят в сегментном регистре. Другими словами, можно взять значение из сегментного регистра, умножить его на 16 (т.е. на 10h) и вы получите адрес начала сегмента.
Для указания конкретного адреса внутри сегмента используется второй 16-разрядный регистр, так называемое смещение. Использование пары регистров сегмент:смещение обеспечивает доступ ко всему мегабайту адресного пространства.
Каждый раз, перед тем как процессор обратится к памяти по адресу, указанному в паре регистров сегмент:смещение, он вычисляет адрес памяти по следующей схеме:
Осталось заметить, что, вообще говоря, в режиме реальных адресов адресное пространство немного больше одного мегабайта, а именно:
При этом адрес будет равен:
Теперь давайте рассмотрим схему образования адреса в защищённом режиме, как это происходит в процессоре i386 (80386 - это базовая модель для любого Pentium-а).
Адрес памяти в 32-разрядном процессоре является также 32-разрядным. Это значит, что адресное пространство для такого процессора равно 4 Гб (2 32 байт).
Адресация памяти также производится через сегмент и смещение в сегменте, для чего используется пара регистров, но для описания сегмента используется больше информации, а именно:
Как видите, информации об одном сегменте достаточно много. Для того, чтобы её хранить, используется не регистр, а специальная область памяти. Сегмент по-прежнему указывается в сегментном регистре, но теперь в нём хранится номер сегмента из списка определённых сегментов. Этот номер называется селектор.
В качестве смещения используется 16- или 32-разрядный регистр.
При обращении к памяти, процессор проверяет возможность доступа к сегменту по уровню привилегий, проверяет, не превысил ли адрес предел сегмента и можно ли обращаться к этому сегменту в данном случае (например, запрещена передача управления в сегмент, описывающий данные или стек). Если в результате проверки будет обнаружено нарушение какого-либо условия, то процессор сгенерирует исключение и тем самым обеспечит защиту.
Предел сегмента - это максимально допустимое смещение внутри него, таким образом, предел сегмента определяет его размер: размер_сегмента = предел_сегмента + 1
Обратите внимание, что значение предела - 20-разрядная величина, это значит, что максимальное значение предела равно 2 20 - 1.
Процессор измеряет размер сегмента двумя типами величин: либо байтами, либо страницами. Страница - это блок памяти размером в 4Кб.
В описании сегмента можно указать, в каких единицах измеряется сегмент и тогда можно получить два типа сегментов с максимальными размерами:
Эта способность измерять сегмент либо байтами, либо страницами, называется гранулярность.
Значение предела сегмента может быть любым, от 0 до 2 20 - 1, гранулярность устанавливается по усмотрению программиста и может быть либо байтная, либо страничная. Всё это позволяет определять сегменты любого размера - от 0 байт до 4Гб.
Следующая глава | Оглавление | Вопросы? Замечания? Пишите: sasm@narod.ru |
Copyright © Александр Семенко. |