Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Л12_13_14_15КУТО.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
29.81 Mб
Скачать

Сегментация памяти в процессоре 8086

В процессоре 8086 сегментация памяти реализована довольно простыми средствами. Под сегментом понимается блок смежных ячек памяти (в адресном пространстве 1Мбайт) с максимальным размером 64 Кбайт и начальным или базовым адресом, находя­щимся на 16-байтной границе (такая граница называется парагра­фом). Для обращения к памяти необходимо определить базу сег­мента и 16-битное расстояние от базы, называемое смещением (offset) или относительным адресом. Базовые адреса четырех одно­временно доступных программе сегментов находятся в сегментных регистрах кода CS, данных DS, стека SS и дополнительных данных ES. Каждый из них имеет длину 16 бит, но можно считать сегмент­ный регистр 20-битным при формировании физического адреса(четыре младших бита базового ад­реса содержат нули). Таким образом, две 16-битных величины (указателя), соответствующие базовому адресу сегмента (с подразу­меваемыми младшими нулями) и смещению, позволяют обращаться ко всему адресному пространству 1 Мбайт, как показано на рис. 2.1.

Рис.2.1. Сегментация памяти в процессоре 8086

Память

Отметим, что сегментные регистры содержат физические адреса памяти, т.е. значение в каждом сегментном регистре прямо указы­вает на границу параграфа в адресном пространстве 1 Мбайт. В за­щищенном режиме последующих процессоров значение в сегмент­ном регистре не имеет прямой взаимосвязи с реальным адресом памяти.

Чтобы упростить обращения к памяти, за каждой командой зак­реплен сегментный регистр по умолчанию, который привлекается без специальных указаний. Так, команды всегда выбираются из сегмента кода (указателями служит пара CS:IP), все стековые операции выполняются в сегменте стека (SS:SP), данные (переменные) находятся в сегменте данных (база находится в регис­тре DS, а смещение, называемое эффективным адресом ЕА, опре­деляется режимом адресации). Для обращения к другим сегментам перед командой помещается префикс замены сегмента. Например, команда MOV АХ,[100Н] загружает в регистр АХ слово из сегмента, базовый адрес которого находится в регистре DS, а смещение равно 100Н. Команда с префиксом замены сегмента MOV AX,ES:[100H] будет обращаться к дополнительному сегменту данных, базовый ад­рес которого находится в регистре ES.

Преобразование пары сегмент:смещение, называемой также логическим или виртуальным адресом, в физический адрес осуществ­ляется довольно просто: содержимое сегментного регистра сдвига­ется влево на четыре бита (что эквивалентно умножению на 16), а затем суммируется со смещением. Если, например, регистр DS со­держит 1234Н, а регистр SI содержит 5678Н, то физический адрес в команде MOV AX,[SI] будет равен

- (DS) * 16 + (SI) = 12340Н + 5678Н = 179В8Н

Отметим два обстоятельства, связанные с сегментацией памяти в процессоре 8086. Во-первых, преобразование логического адреса в физический всегда однозначно, т.е. каждому логическому адресу соответствует уникальный физический адрес. Однако обратное пре­образование неоднозначно: каждому физическому адресу соответ­ствуют 4К логических адресов. Поэтому во всех процессорах фирмы Intel манипуляции физическими адресами осуществляются доволь­но сложно. Во-вторых, в этом способе формирования физического адреса может возникнуть своеобразное переполнение. Пусть, на­пример, регистр DS содержит 0FFFFH. Тогда в команде MOV АХ,[3000Н] физический адрес будет равен

(DS) * 16 + 3000Н = OFFFFOH + 3000Н = 102FF0H

В такой ситуации процессор просто отбрасывает старший 21-й бит адреса и выдает на шину адрес 02FF0H. Другими словами, здесь происходит так называемое «заворачивание» или «закругление» (wrap around) адреса: от адреса 0FFFFFH происходит переход к ну­левому адресу. Заворачивание адреса приходится учитывать при ра­боте процессора i486 в R- и V-режиме.

Простая сегментация памяти в процессоре 8086 обладает следу­ющими особенностями, которые в известном смысле можно считать ее недостатками, усложняющими разработки мультиза­дачных систем.

  1. Сегменты памяти, определяемые только одними сегментными регистрами, имеют всего два атрибута: начальный адрес, находя­щийся на границе параграфа, и максимальный размер 64 Кбайт. Никаких аппаратных средств контроля правильности использова­ния сегментов нет. Размещение сегментов в памяти произвольно: сегменты могут частично или полностью перекрываться или не иметь общих частей. Программа может обращаться к любому сегменту для произ­водства как считывания, так и записи данных, а также для выборки команд. В более общем плане, программа может обратиться по лю­бому физическому адресу, а для защиты определенных областей памяти от несанкционированного доступа требуются внешние схемы.

  2. Нет никаких препятствий для обращения даже к физически- несуществующей памяти. Когда программа выдает адрес несуще­ствующей памяти, результат зависит только от особенностей схем дешифрирования адреса и управления внешней шиной: процессор может получить фиктивные данные, будет сформирован сигнал прерывания или система может просто зависнуть в ожидании дан­ных, которые никогда не будут возвращены.

С учетом этих недостатков сегментация памяти сначала в про­цессоре 80286, а затем и в процессорах 80386 и далее была значительно усовершенствована. В этих процессорах имеются гиб­кие средства организации сегментов с большим числом атрибутов и эффективные механизмы контроля и защиты доступа к сегментам. Кроме того, «ниже» сегментации действует внутренний механизм страничной организации памяти, который позволяет еще более гибко управлять ресурсами памяти компьютера.

2.1.2. Определение сегментов в процессоре с i486

В той модели сегментации памяти, которая применяется в процессоре i486, невозможно представить всю определяющую сегмент информацию в одном 16-битном сегментном регистре. Реализация в нем нескольких уровней привилегий и механизмов защиты задач требует больше информации о каждом сегменте. Основное отличие модели сегментации памяти в процессоре i486 от процессора 8086 заключается в том, что теперь пользовательская программа не может свободно обращаться по любому адресу в пространстве памяти. Каждая программа, независимо от ее уровня привилегий, не может обращаться к сегменту до тех пор, пока он не «описан» для программы. Программе не разрешается обращаться по любому адресу, который она может сформировать.

Вместо простого определения сегмента путем загрузки его базового адреса в сегментный регистр системный программист определяет довольно много информации о каждом сегменте, в частности его базовый адрес, длину или размер, целевое использование (для хранения кода, стека или данных) и другие атрибуты. В задании атрибутов сегментов предоставляется довольно большая свобода. Например, базовый адрес может быть любым (не требуется его выравнивание на границу параграфа), а размер сегмента варьируется от одного байта до всего адресного пространства в 4 Гбайт. Последний размер показывает, что с помощью 32-битного индекса можно «пройти» все адресное пространство, не модифицируя содержимого сегментного регистра. Такая свобода определения сегментов предоставляет программисту полное управление использованием памяти и позволяет удовлетворить практически любые запросы памяти.

ДЕСКРИПТОР СЕГМЕНТА. Каждый сегмент в работающей системе характеризуется специальной 8-байтной структурой данных, называемой дескриптором сегмента (segment descriptor). В описание сегмента включается базовый адрес сегмента, размер сегмента, тип (определяющий целевое использование сегмента), уровень привилегий и дополнительная информация о состоянии, т.е. все то, что необходимо знать о сегменте. При создании дескриптора область адресного пространства определяется как используемая с учетом ограничений, содержащихся в дескрипторе. Число дескрипторов сегментов в системе практически не ограничивается. Если не описать область адресного пространства памяти дескриптором, соответствующий диапазон адресов оказывается недоступным и процессор отказывается обращаться к нему. Когда программа ошибочно или намеренно формирует такой недействительный адрес, процессор «перехватывает» виноватую команду до попытки считывания/записи по неопределенному адресу.

Формат дескриптора сегмента, приведенный на рис. 2.2, на первый взгляд кажется довольно запутанным. В частности, удивляет тот факт, что поля базового адреса и предела разбросаны по нескольким подполям. Объясняется такая «хаотичность» тем, что аналогичный дескриптор в процессоре 80286 содержит 0 в старшем слове (биты 63 — 48), а его поля базового адреса и предела составляют всего 24 и 16 бит, соответственно. Расширение размеров этих полей до 32 и 20 бит заставило в целях совместимости разместить их дополнительные биты в старшем слове дескриптора. Конечно, внутри процессора эти подполя объединяются. Рассмотрим назначение отдельных полей дескриптора сегмента.

Рис. 2.2. Формат дескриптора сегмента

Базовый адрес. 32-битное поле базового адреса занимает байты 2, 3, 4 и 7 дескриптора. Оно определяет любой начальный адрес сегмента в линейном адресном пространстве 4 Гбайт. Именно этот адрес сформирует процессор при задании нулевого смещения.

Предел. 20-битное поле предела (limit), которое называется еще границей сегмента, занимает байты 0 и 1, а также младшие четыре бита байта 6 дескриптора. Предел равен размеру сегмента в байтах минус 1 (но см. далее о гранулярности); можно также считать, что предел задает максимальное смещение в конкретном сегменте или последнюю адресуемую единицу в сегменте.

Казалось бы, что 20-битное поле предела позволяет определить сегмент, размер которого не превышает 1 Мбайт. На самом деле это не так. Сегмент действительно ограничен 1М элементов, но размер элементов задает специальный бит гранулярности G (Granularity) или дробности (это бит 55 в байте 6 дескриптора сегмента) — элементами сегмента могут быть байты или страницы из 4 Кбайт. Таким образом, сегмент с байтной гранулярностью (G = 0) измеряется в байтах и имеет максимальный размер 1 Мбайт, когда поле предела содержит 0FFFFFH. Сегмент со страничной гранулярностью (G = 1) измеряется в страницах и имеет максимальный размер 1М страниц, когда поле предела содержит 0FFFFFH; это соответствует 1М * 4К = 4 Гбайтам, т.е. всему линейному адресному пространству памяти процессора. В этом смысле термин «гранулярность» эквивалентен понятию разрешающей способности цифрового представления изображений. Отметим, что в процессоре 80286 все сегменты имеют байтную гранулярность, так как бит G всегда находится в состоянии 0. Когда сегмент имеет страничную гранулярность, для получения его предела в байтах необходимо к содержимому его поля предела «приписать» справа 12 единиц (или FFFH).

Предположим, например, что регистр DS адресует (косвенно, через дескрипторную таблицу) сегмент с байтной гранулярностью, имеющий предел 0001FH. Размер сегмента составляет 20Н (32 байта) и последний адресуемый байт имеет смещение 0001FH. Приведем простые примеры допустимых и недопустимых команд с обращением к этому сегменту.

Допустимые команды:

mov eax,[G000h]

mov eax,[001ch]

mov al,[001fh]

raov [001eh],ax

Недопустимые команды:

mov eax,[1234h]

mov eax,[001dh]

mov al,[0020h]

mov [001fh],ax

;Последний считываемый байт по ЗН

;Последний считываемый байт по 1FH

;Последний считываемый байт по 1FH

;Последний записываемый байт по 1FH

;Адрес памяти вне предела ;Размер элемента вне предела ;Адрес памяти вне предела ;Размер элемента вне предела

Теперь представим себе сегмент со страничной гранулярностью, имеющий предел 00000Н. Размер сегмента равен одной странице и последней адресуемой страницей является страница 0, а последним адресуемым байтом будет байт со смещением 00FFFH.

Допустимые команды:

Mov eax,[0000h]

Mov eax,[Offch]

mov al,[0fffh]

mov [0ffeh],ax

Недопустимые команды:

mov eax,[1234h]

mov eax,[Offdh]

mov al,[1020h]

mov [Offfh],ax

;Последний считываемый байт по ЗН

;Последний считываемый байт по OFFFH

;Последний считываемый байт по OFFFH

;Последний записываемый байт по OFFFH

;Адрес памяти вне предела ;Размер элемента вне предела ;Ддрес памяти вне предела ;Размер элемента вне предела

Байт 5 дескриптора сегмента содержит так называемые права доступа (Access Rights) и часто называется байтом AR. Рассмотрим назначение полей байта прав доступа.

Бит присутствия Р (Present) установлен в состояние 1, когда описываемый дескриптором сегмент находится (присутствует) в физической памяти. В системе виртуальной памяти операционная система может передавать содержимое некоторых сегментов на диск, когда физическая память заполнена. При этом она отмечает дескриптор передаваемого на диск сегмента как временно неприсутствующий, сбрасывая бит Р в 0. Когда программа загружает в сегментный регистр селектор и селектор выбирает дескриптор с Р = 0, возникает особый случай неприсутствия сегмента. Операционная система должна отыскать свободную область физической памяти (при этом, возможно, ей придется отправить на диск какой-то другой сегмент), скопировать содержимое запрошенного сегмента с диска в память, загрузить в дескриптор новый базовый адрес сегмента, установить бит Р в состояние 1 и осуществить рестарт (restart), т.е. повторное выполнение «виноватой» команды. Описанный процесс обращения к неприсутствующему сегменту с последующими передачами сегментов между основной памятью и диском обычно называется свопингом (swapping) или «подкачкой».

Двухбитное поле уровня привилегий дескриптора DPL (Descriptor Privilege Level) определяет уровень привилегий, ассоциируемый с той областью памяти, которую описывает дескриптор, и правильнее было бы назвать это поле уровнем привилегий сегмента. Уровень привилегий имеет значения от 0 (наибольшие привилегии) до 3 (наименьшие привилегии). Привилегии входят составной частью в механизм защиты процессора IA32.

Бит системный S (System) или сегмента (Segment) в дескрипторах сегментов памяти всегда установлен в состояние 1, а конкретное назначение сегмента описывается полем типа. Если бит S = 0, дескриптор описывает системный объект, как являющийся, так и не являющийся сегментом памяти (такие дескрипторы рассматриваются далее).

Трехбитное поле типа TYPE определяет целевое использование сегмента, задавая допустимые в сегменте операции. Имеются следующие типы сегментов:

-000В - сегмент данных, разрешено только считывание;

-001В - сегмент данных, разрешены считывание и запись;

- 010В - сегмент стека, разрешено только считывание (на практике такие сегменты не применяются);

- 011В - сегмент стека, разрешены считывание и запись;

-100В - сегмент кода, разрешено только выполнение;

- 101В - сегмент кода, разрешены выполнение и считывание;

-110В - подчиненный сегмент кода, разрешено только выполнение;

111В - подчиненный сегмент кода, разрешено выполнение и считывание.

Поле типа определяет правила доступа к сегментам. Например, в регистр CS нельзя загружать селекторы сегментов с типами 0 — 3 (это сегменты данных). Никакая программа не может модифицировать сегмент, для которого разрешено только считывание. Сегменты кода, которые разрешено только выполнять, невозможно считать (это предотвращает несанкционированное копирование программ), указывая префикс CS: замены сегмента. Попытка нарушить любое из этих правил вызывает особый случай защиты.

Бит доступа или обращения A {Accessed). Этот бит процессор автоматически устанавливает в состояние 1, когда осуществляется обращение к тому сегменту памяти, который определяется данным дескриптором. Обычно операционная система привлекает бит А для того, чтобы выбрать нечасто используемые сегменты, которые при необходимости можно передать на диск в процессе свопинга.

Четыре дополнительных поля дескриптора сегмента находятся в старшей тетраде байта 6.

Бит гранулярности G, определяющий размер элементов сегмента, был рассмотрен выше.

Бит размера по умолчанию D (Default Size) обеспечивает совместимость с процессором 80286. Когда бит D содержит 0, находящиеся в сегменте операнды считаются имеющими размер 16 бит. Если же бит D установлен в состояние 1, операнды в сегменте имеют размер 32 бита.

Процессор интерпретирует содержимое сегмента кода, дескриптор которого имеет D = 0, как 16-битный код процессора 80286. Сегмент кода, дескриптор которого имеет D = 1, считается содержащим 32-битный код процессора i486. Следовательно, благодаря биту D процессор i486 без специальных дополнительных мер может переключаться с выполнения 16-битного кода на 32-битный и наоборот.

Для сегментов данных и стека справедлива аналогичная интерпретация. Когда бит D = 0, стековые операции производятся с 16-битными элементами и в качестве указателя стека привлекается регистр SP. Кроме того, максимальный размер стека ограничен 64 Кбайтами, а не 4 Гбайтами.

Бит 53 зарезервирован фирмой Intel для будущих процессоров и программисты не должны использовать этот бит. Он должен содержать 0.

Бит пользователя U (User) предназначен для использования системными программистами по их усмотрению, а процессор игнорирует этот бит. Такие «свободные» биты в зарубежной литературе обычно отмечаются как AVL (AVaiLable — доступный, свободный/ Возможные применения бита U включают в себя отметку сегментов, предназначенных для «сбора мусора», или сегментов, базовые адреса которых нельзя модифицировать.