- •If (Interrupt Flag, бит 9) — флаг прерывания, определяющий реакцию процессора на запросы внешних прерываний по входу int (0 — прерывания запрещены, 1 — разрешены);
- •Способы адресации
- •Влияние команд на регистр флагов
- •Конвейерная обработка в процессоре Pentium
- •Развитие архитектуры Pentium
- •Расширенные регистры и типы данных процессоров x86
- •Дескрипторы
- •Порядок работы процессора в защищенном режиме
Порядок работы процессора в защищенном режиме
Глобальная (GDT) и локальная (LDT) таблицы дескрипторов
При работе в защищенном режиме все обращения к памяти происходят через глобальную таблицу дескрипторов (Global Descriptor Table, GDT) или (опционально) через локальную таблицу дескрипторов (Local Descriptor Table, LDT).
Глобальная и локальная таблицы дескрипторов содержат структуры, называемые дескрипторами сегментов. Дескриптор IA-32 имеет размер в восемь байт. Он содержит базовый (начальный) адрес сегмента, его тип, дополнительные свойства (разрядность адресов и операндов, единицу измерения величины сегмента, лимит), права доступа, информацию об использовании сегмента. Каждый дескриптор имеет связанный с ним селектор. Размер селектора — 16 бит. Он содержит индекс (номер) дескриптора в таблице, флаг, определяющий, где находится дескриптор, в локальной или глобальной таблице, а также права доступа. Линейный базовый адрес глобальной таблицы дескрипторов и ее размер содержатся в регистре глобальной таблицы дескрипторов (Global Descriptor Table Register, GDTR), локальной таблицы дескрипторов — в регистре локальной таблицы дескрипторов (Local Descriptor Table Register, LDTR). GDT может быть только одна, обычно в ней находятся описания сегментов операционной системы. LDT может быть любое количество: ни одной, одна на множество задач или по одной на каждую задачу. Они содержат описания сегментов программ, работающих под управлением операционной системы, т.е. отдельных задач. В каждый момент времени процессор может использовать только одну таблицу LDT.
Размер GDT, уменьшенный на единицу, называется пределом таблицы GDT (GDT limit). Он используется для проверки правильности задаваемых программой селекторов. Поле индекса селектора должно содержать ссылки только на существующие элементы таблицы GDT, в противном случае произойдет прерывание. Зная размер GDT, процессор блокирует использование селекторов со значениями поля индекса, выходящими за рамки разрешенных для таблицы GDT. Аналогичный механизм используется и для проверки селекторов, ссылающихся на LDT.
Системные сегменты и дескрипторы
Помимо сегментов кода, данных и стека, которые являются средой для исполнения программы или подпрограммы (процедуры), системная архитектура определяет два системных сегмента: сегмент состояния задачи (task state segment, TSS) и LDT. Каждый из этих типов сегментов имеет соответствующий тип дескриптора. GDT не рассматривается как сегмент, поскольку доступ к ней не осуществляется посредством селектора и дескриптора.
Специальные сегменты и дескрипторы
Системная архитектура определяет также множество специальных сегментов и, соответственно, дескрипторов, называемых шлюзами или вентилями (gates): шлюз вызова, шлюз прерывания, шлюз ловушки и шлюз задачи. Они предоставляют защищенные входы в системные процедуры и обработчики прерываний, которые работают на различных с прикладной программой уровнях привилегий.
Задачи и переключение между ними
TSS определяет состояние среды исполнения задачи, которое включает в себя значения:
-
регистров общего назначения;
-
сегментных регистров;
-
регистра флагов;
-
указателя команд;
-
селекторов сегментов и указателей стека для трех сегментов стека (по одному для каждого из трех уровней привилегий — 0, 1 и 2);
-
селектора сегмента LDT, связанной с задачей;
-
базовый адрес таблицы страниц.
Выполнение программы в защищенном режиме происходит в контексте задачи, называемой текущей задачей. Селектор сегмента TSS для текущей задачи размещен в регистре задач (Task Register, TR). Самый простой метод переключения между задачами — вызов или переход в задачу. Здесь селектор сегмента TSS новой задачи должен находиться в команде CALL или JMP. При переключении задач процессор выполняет следующие действия:
-
Размещает состояние текущей задачи в текущем TSS.
-
Загружает TR селектором сегмента новой задачи.
-
Обращается к новому TSS посредством дескриптора сегмента в GDT.
-
Загружает состояние новой задачи из нового TSS в регистры общего назначения, сегментные регистры, LDTR, CR3 (базовый адрес таблицы страниц), регистр флагов и указатель команд.
-
Начинает выполнение новой задачи.
Задача также может быть доступна через шлюз задач. Шлюз задач похож на шлюз вызова за исключением того, что он предоставляет доступ к TSS раньше, чем к сегменту кода.
Обработка прерываний. Таблица дескрипторов прерываний (IDT)
Внешние прерывания, программные прерывания, исключения обрабатываются с использованием таблицы дескрипторов прерываний (Interrupt Descriptor Table, IDT). Исключение — это событие, которое происходит, если команда вызывает ошибку. Например, попытка деления на ноль генерирует исключение. Однако есть исключения, например, контрольные точки, которые происходят при других условиях. IDT содержит множество дескрипторов различных шлюзов: прерываний, ловушек и задач — которые предоставляют доступ к обработчикам прерываний и исключений. Так же как и GDT, IDT не является сегментом. Линейный базовый адрес и лимит IDT содержатся в регистре таблицы дескрипторов прерываний (Interrupt Descriptor Table Register).
Для вызова обработчика процессор должен вначале получить номер прерывания от внутренней логики, внешнего контроллера прерываний или программы посредством команд INT, INTO, INT 3 или BOUND.
Номер прерывания предоставляет индекс соответствующего дескриптора в IDT. Если это дескриптор шлюза прерывания или ловушки, то вызов обработчика аналогичен вызову подпрограммы. Если это дескриптор шлюза задачи, то доступ к обработчику осуществляется через переключение задач.
Сегментная и страничная адресации
Системная архитектура поддерживает два вида адресации:
-
сегментную;
-
страничную.
В первом случае память разбивается только на сегменты, и линейный адрес рассматривается как физический адрес. Для доступа к байту внутри сегмента необходимы селектор сегмента и смещение данного байта внутри сегмента. Процессор по значению селектора определяет соответствующий дескриптор, из которого берет базу сегмента — линейный начальный адрес сегмента (адрес первого байта сегмента), прибавляет к нему смещение искомого байта и получает его линейный адрес, который в данном случае является и физическим. Этот механизм используется для доступа к любому действительному сегменту кода, данных или стека при условии, что сегмент доступен из текущего уровня привилегий (current privilege level, CPL), с которым работает процессор. CPL определяется как уровень привилегий текущего исполняемого сегмента кода.
Во втором случае сегменты разбиваются на страницы. Местоположение страниц (рамки страниц, page frames) определяется двумя типами системных структур данных: каталогом страниц (Page Directory) и таблицами страниц (Page Table), которые располагаются в физической памяти. Физический адрес каталога страниц содержит регистр CR3. Линейный адрес разбивается на части, которые представляют собой точки входа в каталог страниц, таблицу страниц, а также смещение в заданной странице, которое и дает физический адрес.
Для включения страничной адресации нужно выполнить следующие действия:
-
Подготовить каталог и таблицы страниц.
-
Поместить в регистр CR3 физический адрес начала каталога страниц.
-
Установить бит PG регистра CR0.
Каталог страниц имеет размер 4096 байт, что соответствует обычному размеру страницы (чаще всего страница имеет размер 4 Кбайта, но начиная с Pentium Pro поддерживаются 2 и 4 Мб страницы). Он содержит 1024 4-байтных указателя на таблицы страниц (рис.).

Рис. Формирование физического адреса в защищенном режиме при включенной страничной адресации в процессорах IA-32
Каждая таблица страниц тоже имеет размер 4096 байт и содержит указатели до 1024 4-килобайтных страниц. Если страница имеет размер 4 Кбайта, то полностью заполненная таблица страниц описывает 4 Мбайта, а полный каталог полностью заполненных таблиц — 4 Гбайта, т. е. все 32-битное адресное пространство процессоров IA-32.
При обращении процессора к памяти при включенной страничной адресации линейный адрес рассматривается как структура следующего формата:
-
биты 31–22 — номер таблицы страниц в каталоге (точка входа в каталог страниц);
-
биты 21–12 — номер страницы в выбранной таблице страниц (точка входа в таблицу страниц);
-
биты 11–0 — смещение от физического адреса начала страницы в памяти.
Этот процесс требует множества циклов обращения к памяти и занимает много времени, поэтому в процессоре имеется специальный кэш страниц — TLB (Translation Lookaside Buffer, буфер трансляции адресов), и если к странице было обращение недавно, то процессор определит ее физический адрес сразу.
Элементы каталога страниц и таблиц страниц имеют одинаковый формат:
-
биты 31–12: биты 31–12 физического адреса начала таблицы страниц или самой страницы;
-
биты 11–9 могут быть использованы операционной системой;
-
бит 8: G — "глобальная страница" — страница не удаляется из буфера TLB при переключении задач или перезагрузке регистра CR3 (только на Pentium Pro, если установлен бит PGE регистра CR4);
-
бит 7: PS — размер страницы: 1 — для страницы размером 2 или 4 мегабайта, иначе — 0;
-
бит 6: D — "грязная страница" — устанавливается в 1 при записи в страницу, всегда равен нулю для элементов каталога страниц;
-
бит 5: А — бит доступа, устанавливается в 1 при любом обращении к таблице страниц или отдельной странице;
-
бит 4: PCD — бит запрещения кэширования;
-
бит 3: PWT — бит разрешения сквозной записи;
-
бит 2: U — страница/таблица доступна для программ с CPL = 3;
-
бит 1: W — страница/таблица доступна для записи;
-
бит 0: Р — 1 — страница/таблица присутствует; 0 — отсутствует, при этом остальные биты элемента система может использовать по своему усмотрению, например, чтобы хранить информацию о том, где физически находится отсутствующая страница.
В процессорах Intel64 страничная адресация имеет более сложную структуру (рис.)

Рис. Формирование физического адреса в защищенном режиме при включенной страничной адресации в процессорах Intel64
Страничная адресация используется операционными системами, поскольку позволяет реализовать виртуальную память — использовать часть диска как дополнение к основной оперативной памяти компьютера. При этом только недавно используемые страницы могут находиться в физической оперативной памяти, а давно неиспользуемые выгружаются на диск.
Повышение надежности функционирования системы в защищенном режиме
Функционирование системы в защищенном режиме значительно повышает ее надежность.
Во-первых, повышение надежности обусловлено возможностью задания необходимого размера сегмента и контролем адресации памяти вне пределов сегментов.
Во-вторых, байт доступа дескриптора сегмента кода содержит бит разрешения чтения сегмента (бит 1). Если этот бит установлен в 1, программа может считывать содержимое сегмента кода. В противном случае процессор может только выполнять этот код, т. е. программа не может модифицировать сегмент кода. Это означает невозможность создания самомодифицирующихся программ для защищенного режима. Впрочем, возможность модификации кода остается. Для сегмента кода можно создать еще один, алиасный дескриптор, в котором этот сегмент отмечен как сегмент данных. Для него можно разрешить запись, установив тот же самый бит 1, и модифицировать код программы во время ее выполнения.
Процессор при обращении к памяти в защищенном режиме проверяет соблюдение всех необходимых условий: возможность доступа к сегменту по уровню привилегий, не превысил ли адрес предел сегмента, можно ли вообще обращаться к данному сегменту в данной ситуации. И если процессор обнаруживает нарушение какого-либо условия, то генерирует исключение и тем самым обеспечивает защиту (режим называется защищенным) и, следовательно, повышение надежности.
