Права доступа сегмента
Рассмотрим несколько подробнее поля байта прав доступа AR и их применение. Прежде всего отметим, что в процессоре i486 разрешены не все 256 комбинаций в этом байте. Например, комбинации 00Н и 80Н считаются, недействительными. Дескрипторы сегментов с неверными или неопределенными значениями в байте AR сами по себе не считаются ошибкой, но при попытке использовать такой дескриптор процессор фиксирует особый случай.
1. Бит присутствия Р, по существу, служит флажком, показывающим возможность доступа к сегменту. Если при создании дескриптора задать Р = 0, процессор отвергает все последующие попытки использовать дескриптор в командах и определяемое дескриптором адресное пространство как бы «пропадает». Отметим также, что при обнаружении Р = 0 процессор игнорирует остальные поля дескриптора за исключением байта AR, который всегда должен быть действительным. В этой ситуации программист может распоряжаться остальными семью байтами дескриптора по своему усмотрению (см. рис. 2.3).
Рис. 2.3. Дескриптор неприсутствующего сегмента
2. Поле типа, определяющее назначение и использование сегмента, играет очень важную роль в определении сегментов памяти. В общем, каждый бит этого поля несет свою смысловую нагрузку, что показано на рис. 2.4.
Рис. 2.4. Формат байта прав доступа
Бит 3 различает сегменты кода (1) и данных (0). Для сегментов кода бит 2 называется битом подчинения С (Conforming) или согласования (см. гл. 3), а бит 1 называется битом считывания R (Read) и показывает возможность считывания кода как данных с помощью префикса замены сегмента.
Для сегментов данных бит 2 называется битом расширения вниз ED (Expand Down); он различает сегменты стека (ED = 1) и сегменты собственно данных (ED = 0) и управляет интерпретацией поля предела. Наконец, бит 1 записи W (Write) показывает возможность модификации содержимого сегмента посредством записи в него(W=l).
Тип сегмента 0 соответствует сегменту данных, для которого разрешено считывание, но запрещена запись. Другими словами, этот тип определяет виртуальное постоянное запоминающее устройство ПЗУ. Будет ли фактически приходиться на этом сегмент ПЗУ, не играет роли: процессор i486 не разрешает запись в адресное пространство сегмента. Очевидно, тип 0 следует назначать сегментам, содержимое которых нельзя изменять. Такие сегменты могут содержать таблицы констант, общесистемные справочные данные, информацию о состоянии и т.п.
Тип сегмента 1 задает традиционный сегмент данных, для которого разрешены операции считывания и записи. Сегменты типов 0 и 1 применяются только для хранения данных и в них нельзя хранить код, так как для них не существует разрешение на выполнение и это ограничение является очень жестким. Командами FAR CALL или FAR JMP невозможно заставить процессор i486 «выполнять данные как код» (в процессоре 8086 это вполне допустимо, хотя и бессмысленно). Такое ограничение способствует разработке надежных и живучих операционных систем.
Типы сегментов 2 и 3 определяют сегменты стека, которые по существу являются разновидностью сегментов данных. Сегменты стека отличаются от сегментов собственно данных с разрешенными операциями записи и считывания только интерпретацией поля предела, которое определяет размер стека с учетом бита гранулярности G.
В сегментах данных адресуемый диапазон простирается от базового адреса до базового адреса плюс предел, т.е. смещения варьируются от 0 до предела. Смещения, которые больше предела, вызывают особый случай зашиты. В сегментах стека с ED = 1 ситуация оказывается противоположной в том смысле, что поле предела определяет неадресуемую область сегмента. Здесь все смещения должны быть строго больше предела, а если смещение меньше или равно пределу, фиксируется особый случай нарушения стека. Отметим, что термин «расширение вниз», т.е. к меньшим адресам, относится к такой графической иллюстрации адресного пространства, в которой адрес 0 находится внизу, а максимальный адрес вверху.
Рис. 2.5. Интерпретация поля предела для сегментов данных и стека
На рис.2.5 показаны сегмент стека и сегмент данных, которые оба имеют предел 1FFFH (G = 0). Для сегмента данных допустимыми будут все смещения, меньшие или равные 1FFFH. Первый адресуемый байт находится по смещению 0, а последний по смещению 1FFFH; размер сегмента составляет 2000Н или 8 Кбайт. Для сегмента стека допустимы все смещения, которые больше предела; первый адресуемый байт находится по смещению 2000Н, а последний по смещению 0FFFFH. Размер стека составляет 0E00H или 56 Кбайт.
В сегменте данных минимальный адрес задается полем базового адреса дескриптора, а максимальный полем предела. Для сегментов стека минимальный адрес определяется полем предела, а чему же равен максимальный адрес? Здесь имеется два выбора. Если бит D = 0, то максимальный адрес равен базовому адресу плюс константа OFFFFH (64K— 1). Когда же бит D = 1, максимальный адрес равен базовому адресу плюс 0FFFFFFFFH (4Г — 1). Так как все смещения должны быть больше предела, максимальный размер стека получается, когда предел равен 0. Сегмент стека имеет минимальный размер, когда предел равен либо OFFFFH (D = 0), либо OFFFFFFFFH (D = 1), что соответствует пустому сегменту с нулевым размером.
содержимое указателя стека уменьшается, при нехватке стекового пространства возникают Напомним, что, если в дескрипторе сегмента стека бит D = 1, то во всех стековых операциях участвует 32-битный указатель стека ESP и все включения и извлечения оперируют 32-битными двойными словами. Если же бит D = 0, то для стековых операций привлекается указатель стека SP и в них участвуют 16-битные слова. Следовательно, для использования 32-битного стека, что рекомендуется при разработке новых прикладных программ, необходимо задать в дескрипторе сегмента стека D = 1, а это приводит к максимальному адресу стека 4Г — 1. Более того, процессор i486 требует, чтобы при D = 1 бит гранулярности G также находился в состоянии 1. Если же D = 0, то и бит G должен находиться в состоянии 0. Следовательно, необходимо не только определить 32-битный сегмент стека с максимальным адресом 4Г — 1, но и установить предел в единицах 4 Кбайт.
В общем случае для использования стека необязательно определять сегмент стека. Вполне допустимо заставить указатель стека ESP адресовать середину обычного сегмента данных (разумеется, с разрешенной операцией записи). Но так как указатель стека обычно инициализируется на наибольший адрес в сегменте, а затем по мере включений в стек трудности с увеличением размера стека. Для расширения обычного сегмента данных достаточно увеличить значение в поле предела дескриптора и пользоваться большими адресами. Однако стек «растет» в направлении уменьшения адресов, поэтому при расширении сегмента данных придется сдвигать в область больших адресов весь стековый кадр. Такие операции оказываются очень неудобными и трудоемкими. Если же с самого начала определить сегмент как стек, то для его расширения достаточно уменьшить значение предела.
Типы сегментов 4—7 определяют исполняемые сегменты, т.е. сегменты, в которых находится код (машинные команды). Для таких сегментов можно разрешить/запретить считывание. Если считывание запрещено (тип 4), сегмент должен содержать «чистый» код; в нем не должны находиться даже константы, так как их невозможно считать. Отметим, что запись в сегмент кода никогда не разрешается, поэтому реализовать в процессоре i486 хитроумные трюки с самомодифицирующимися программами невозможно.
Бит подчинения С, установленный в состояние 1, позволяет намеренно лишить соответствующий сегмент кода защиты по уровням привилегий. Такое средство удобно для организации в системе библиотек, программы которых должны быть доступными всем выполняющимся в системе задачам. Библиотечные программы оформляются как подчиненные сегменты кода и они могут быть вызваны (CALL) любой текущей задачей.
Дата добавления: 2015-06-05; просмотров: 1960;