Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

Процессор i486(TM)

                                                                                              
 
 Процессор i486 обеспечивает наивысшую скорость выполнения
 прикладных программ для DOS, OS/2, Windows и UNIX System V/386.
 Он на 100% программно совместим с микропроцессорами 386(ТМ) DX &
 SX. Один миллион транзисторов объединенной кэш-памяти
 (сверхбыстрой оперативной памати), вместе с аппаратурой для
 выполнения операций с плавающей запятой и управлением памяти на
 одной микросхеме, тем не менее поддерживают программную
 совместимость с предыдущими членами семейства процессоров
 архитектуры 86. Часто используемые операции выполняются за один
 цикл, что сравнимо со скоростью выполнения RISC-команд.
 Восьмикилобайтный унифицированный кэш для кода и данных,
 соединенный с шиной пакетного обмена данными со скоростью 80/106
 Мбайт/сек при частоте 25/33 Мгерц гарантируют высокую
 производительность системы даже с недорогими дисками (DRAM).
 
 Новые возможности расширяют многозадачность систем. Новые
 операции увеличивают скорость работы с семафорами в памяти.
 Оборудование на микросхеме гарантирует непротиворечивость
 кеш-памяти и поддерживает средства для реализации
 многоуровневого кэширования.
 
 Встроенная система тестирования проверяет микросхемную логику,
 кэш-память и микросхемное постраничное преобразование адресов
 памяти. Возможности отладки включают в себя установку ловушек
 контрольных точек в выполненяемом коде и при доступе к данным.
 
 Возможности процессора i486 включают в себя:
 
 - Полная программная совместимость с ЦПУ 386 DX, 386 SX,
   встроенным 376(TM) процессором, процессорами 80286, 8086 и
   8088;
 
 - Модуль выполнения команд разработан так, чтобы выполнять часто
   встречающиеся операции за один цикл;
 
 - 32-разрядный процессор для выполнения арифметических и
   логических операций;
 
 - Встроенный модуль обработки арифметических операций с
   плавающей точкой для поддержки 32, 64, и 80-разрядных
   форматов, заданных в соответствие со стандартом IEEE 754
   (объектно совместимом с 387 (TM) DX и 387 SX арифметическими
   сопроцессорами);
 
 - Внутренняя 8 Кбайтовая кэш-память, которая обеспечивает
   быстрый доступ к часто используемым данным и операциям;
 
 - Сигналы управления шиной для поддержки непротиворечивости кэша
   в многозадачных системах;
 
 - Сегментация, одна из форм управления памятью для создания
   независимых, защищенных адресных пространств;
 
 - Постраничное разбиение, одна из форм управления памятью,
   которая обеспечивает доступ к структурам данных, большим, чем
   доступное пространство памяти, путем хранения данных частично
   в памяти, частично на диске;
 
 - Перезапускаемые операторы, которые позволяют перезапуск
   программы после исключения (необходимы для поддержки
   постраничного доступа к виртуальной памяти);
 
 - Конвеерное выполнение команд, перекрывающееся по времени с
   интерпретацией других команд;
 
 - Регистры отладки для аппаратной поддержки контрорльных точек
   в командах и данных;
 
 Процессор i486 совместим на уровне объектных кодов с тремя
 другими процессорами семейства 386:
 
 - Процессор 386 DX (32-разрядная шина данных) - эффективная
   относительно своей стоимости форма для персональных
   компьютеров высокого класса и рыночих станций среднего уровня;
 
 - Процессор 386 SX (16-разрядная шина данных) - 386-ой процессор,
   адаптированный для персональных компьютеров среднего класса, для
   которых существенна высокая цена системы с 32-разрядной шиной.
 
 - 376 встроенный процессор (16-разрядная шина данных) -
   упрощенная форма 386 процессора, оптимизированная для
   применения в качестве встроенного в систему процессора, такую
   как контроллеры процессов. Процессору 386 не хватает
   постраничной организации памяти и совместимости с процессором
   8086, обеспечиваемых процессором i486. Процессор 376
   значительно дешевле и меньше любого варианта исполнения
   процессора 386.
 
 Режим работы процессора i486 определяет, какие команды и какие
 архитектурные возможности доступны. Процессор i486
 предусматривает три режима выполнения программ:
 
 - Защищенный режим использует естественное множество
   32-разрядных команд процессора. В данном режиме доступны все
   команды и все архитектурные возможности.
 
 - Режим реальной (прямой) адресации (называемый также "реальным
   режимом") эмулирует программную среду процессора 8086, с
   некоторыми дополнительными возможностями (такими, как
   возможность прервать данный режим). При перезагрузке процессор
   устанавливается именно в этот режим.
 
 - Виртуальный режим 86 (называемый также "режим V86") является
   другой формой эмуляции режима 8086. В отличие от режима прямой
   адресации, виртуальный режим 86 совместим с защитой и
   управлением памятью. Процессор может установить виртуальный
   режим 86 из защищеного режима, чтобы выполнить программу,
   написанную для процессора 8086, а затем выйдя из виртуального
   режима 86 и перейдя в защищенный режим продолжить выполнение
   программы, которая использует множество 32-разрядных команд.
 
 1.1 Структура данного руководства
 ----------------------------------------------------------------
 
 Эта книга описывает архитектуру процессора i486 в пяти частях:
 
 - Часть   I - Прикладное программирование.
 - Часть  II - Системное программирование.
 - Часть III - Численная обработка.
 - Часть  IV - Совместимость.
 - Часть   V - Набор команд.
 - Приложения.
 
 Это деление определяется архитектурой процессора и теми
 способами, которыми программисты используют данную книгу. Первые
 три части содержат информацию о назначении различных
 архитектурных возможностей, развитии терминологии и концепций;
 описание команд с точки зрения их соотношений со специфифескими
 задачами и специфическими архитектурными возможностями.
 Остальные части содержат справочные материалы для программистов,
 создающих прикладное программное обеспечение для процессора
 i486.
 
 Первые четыре части охватывают режимы работы и механизм защиты
 процессора i486. Различие между прикладным программированием и
 системным программированием относится к механизму защиты
 процессора i486. Одним из назначений механизма защиты является
 предупреждение столкновений между прикладными программами и
 операционной системой. По этой причине некоторые регистры и
 команды недоступны для прикладных программ. Возможности,
 обсуждаемые в Частях I  и III, доступны для прикладных программ;
 возможности, описанные в Части II, доступны только для программ,
 выполняемых со специальными привилегиями, или для программ,
 выполняемых в режимах, где механизм защиты не используется.
 
 Возможности, доступные для прикладных программ в защищенном
 режиме, и для всех программ в виртуальном режиме 8086,
 одинаковы. Эти возможности описаны в Частях I  и  III данной
 книги. Дополнительные возможности, доступные для системных
 программ в защищенном режиме, описаны в Части II. Часть IV
 описывает режим прямой адресации и виртуальный режим 86, а также,
 как выполнять смесь 16-разрядных и 32-разрядных программ.
 
 1.1.1 ЧАСТЬ I - Прикладное программирование.
 ----------------------------------------------------------------
 
 Эта часть описывает возможности, используемые большинством
 прикладных программ. В нее не включены описания возможностей,
 используемых в численных приложениях, которые обсуждаются в
 Части III.
 
 Глава 2 - Основная модель программирования: Дает введение в
 модели организации памяти. Определяет типы данных. Описывает
 множество регистров, используемых прикладными программами.
 Вводит понятие стека. Объясняет операции над строками. Определяет
 поля команд. Объясняет принципы вычисления адресов. Дает введение в
 прерывания и исключения с точки зрения того, как они применяются
 в прикладных программах.
 
 Глава 3 - Множество команд для прикладных программ :
 Рассматриваются команды, обычно используемые в прикладном
 программировании. Рассматривыемые команды объединены в
 функционально связанные группы: например, операции над строками
 объединены в один раздел, в то время как управляющие команды
 объединены в другом разделе. Основные понятия вводятся до
 рассмотрения команд. Подробности конкретных команд
 рассматриваются в Части IV, которая является справочником по
 всем коммандам процессора.
 
 1.1.2 Часть II - Системное программирование.
 ----------------------------------------------------------------
 
 В данной части описаны возможности, используемые операционной
 системой, драйверами устройств, отладчиками и другим
 программным обеспечением, которое поддерживает работу прикладных
 программ. Некоторая дополнительная информация, относящаяся к
 системному программированию, представлена в Части III.
 
 Глава 4 - Архитектура системы : Описывает возможности процессора
 i486, используемые системными программистами. Вводит понятия
 регистров и структур данных процессора i486, которые не описаны
 в Частях I и III. Описывает системно-ориентированные команды в
 контексте регистров и структур данных, которые они поддерживают.
 Ссылается на главы, в которых каждый регистр, структура данных и
 команда описывается более подробно.
 
 Глава 5 - Управление памятью : Описывает возможности структур
 данных, регистров и команд, которые поддерживают сегментацию.
 Объясяется, как разработчики систем могут выбирать между
 несегментированной ("плоской") моделью организации памяти и
 моделью с сегментацией.
 
 Глава 6 - Защита : Обсуждается применение защиты сегментов.
 Рассматриваются применение правил привилегированности, стековое
 переключение, оценка достоверности указателя, пользовательский и
 супервизорский режимы. Обсуждение аспектов защиты при
 многозадачности отложено до следующей главы.
 
 Глава 7 - Многозадачность : Объясняется, как аппаратное
 обеспечение процессора i486 поддерживает многозадачность с
 контекстно-зависимым переключением операций и защиту задач от
 взаимного влияния.
 
 Глава 8 - Ввод/Вывод : Описывает возможности ввода/вывода
 процессора i486, включая команды ввода/вывода; защиту, с точки
 зрения к ввода/вывода, и битовый массив разрешения ввода/вывода.
 
 Глава 9 - Исключения и прерывания : Объясняет основной механизм
 прерываний процессора i486. Показывает, как прерывания и
 исключения относятся к защите. Приводится список всех исключений
 с указанием вызывающих их причин и дополнительной информации,
 необходимой для обработки и восстановления из каждого
 исключения.
 
 Глава 10 - Инициализация : Определяет состояние процессора после
 перезагрузки. Объясняет, как задать значения регистров, флагов о
 структур данных. Показывает, как тестировать память на
 микросхеме и ассоциативного буфера трансляции. Содержит пример
 программы инициализации.
 
 Глава 11 - Отладка : Описывает, как использовать регистры
 отладки процессора i486.
 
 Глава 12 - Кэширование : Вводит понятие кэширования и описывает
 специальный механизм, используемый внутренней кэш-памятью
 процессора i486.
 
 Глава 13 - Многозадачность : Объясняет команды и флаги, которые
 поддерживают множество процессов с разделением памяти.
 
 1.1.3 ЧАСТЬ III - Численная обработка.
 ----------------------------------------------------------------
 
 Эта часть объясняет возможности арифметики с плавающей точкой
 для процессора i486. Эти возможности совместимы на уровне
 объектных кодов с реализацией возможностей, предлагаемых
 математическими сопроцессорами 387 DX & SX, используемыми вместе
 с процессорами 386 DX & SX.
 
 Глава 14 - Введение в численные приложения : Предлагается обзор
 модуля чисел с плавающей запятой и пересматриваются понятия
 численных вычислений.
 
 Глава 15 - Архитектура числового блока : Описываются регистры
 для чисел с плавающей запятой и типы данных, доступные как для
 прикладных, так и для системных программистов.
 
 Глава 16 - Особые ситуации при вычислениях : Обсуждаются
 специальные значения, которые могут быть представленны в
 вещественных форматах процессора i486 - ненормализованные числа,
 нули, бесконечности, NaNs (нечисленные выражения) - так же, как
 и численные выражения. Эта глава в обязательном порядке должна
 быть прочитана системными программистами, но может быть
 пропущена программистами прикладными. Многие из описанных
 специальных ситуаций могут никогда не возникнуть в прикладных
 программах.
 
 Глава 17 - Команды работы с числами с плавающей запятой :
 Делается обзор команд, обычно используемых для численной
 обработки. Подробности конкретных команд отложены до Части V -
 справочника команд.
 
 Глава 18 - Численные приложения : Описывает арифметические
 возможности процессора i486 в вычислениях с плавающей запятой.
 Предлагает короткие примеры программ на ассемблере и языках
 высокого уровня.
 
 Глава 19 - Соображения системного уровня : Предлагается
 информация, интересная для разработчиков системного
 программного беспечения.
 
 Глава 20 - Примеры численного программирования : Предлагаются
 подробные примеры численного программирования на языке
 ассемблера процессора i486, включая условное ветвление,
 преобразование значений с плавающей запятой в их представления
 в формате ASCII и обратно, использование тригонометрических
 функций.
 
 1.1.4 ЧАСТЬ IV - Совместимость.
 ----------------------------------------------------------------
 
 Эта часть объясняет возможности архитектуры, которые
 поддерживают работу программ, написанных для более ранних версий
 процессоров семейства Intel. Естественный режим выполнения
 является обобщением среды процессоров 80286 и 386 DX. Все три
 режима выполнения поддерживают 16-разрядное программирование: 16
 -разрядные команды могут быть выполнены в защищенном режиме,
 используя префикс размерности операнда, программы, написанные
 для процессора 8086 или в режиме прямой адресации процессора
 80286 могут бять выполнены в режиме прямой адресации процессора
 386 DX, и монитор виртуальной машины может быть использован для
 эмуляции режима прямой адресации с использованием виртуального
 режима 8086, даже в случае многозадачности с 32-разрядными
 программами.
 
 Глава 21 - Выполнение программ для процессоров 80286 и 386 DX :
 Объясняются различия в программировании для процессоров 80286 и
 i486, и между процессорами 386 DX и i486.
 
 Глава 22 - Режим прямой адресации : Объясняет режим прямой
 адресации процессора i486. В этом режиме процессор i486 работает
 как самые быстрые процессоры прямой адресации 80286 и 386 DX или
 как самый быстрый процессор 8086, усовершенствованный при помощи
 дополнительных команд.
 
 Глава 23 - Виртуальный режим 8086 : Описывает, как процессор
 i486 поддерживает выполнение одной или более программ для 8086,
 8088, 80186 или 80188 в среде защищенного режима процессора i486.
 
 Глава 24 - Смешанный 16-разрядный и 32-разрядный код :
 Объясняет, как процессор i486 может смешивать 16-разрядные и
 32-разрядные модули в одной программе или задаче. Каждый
 отделъный модуль может использовать одновременно 16-разрядные и
 32-разрядные операнды и адреса.
 
 Глава 25 - Совместимость с арифметическими сопроцессорами 8087,
 80287 и 387 DX : Сравнивает арифметику с плавающей запятой для
 процессора i486 с арифметикой арифметических сопроцессоров,
 используемых с ранними версиями процессоров семейства Intel.
 
 1.1.5 ЧАСТЬ V - Набор команд.
 ----------------------------------------------------------------
 
 Части I, II и III представляют читателю общие возможности
 множества команд с точки зрания того, как они соотносятся со
 специфическими особенностями архитектуры. Часть V описывает
 команды в алфавитном порядке, с теми подробностями, которые
 необходимы программистам, использующим язык ассемблера, и
 разработчикам отладчиков, компиляторов, операционных систем и
 т.д. Описание команды включает алгоритмическое описание операций,
 результаты установки флагов, эффекты аттрибутов размерности
 адресов и операндов и исключения, которые могут появиться в
 ходе выполнения команды.
 
 1.1.6 Приложения.
 ----------------------------------------------------------------
 
 Приложения содержат таблицы кодирования команд и другие
 подробности в формате, разработанном для их быстрого поиска.
 
 1.2 Дополнительная литература.
 ---------------------------------------------------------------
 
 Следующие книги содержат дополнительные материалы, связанные с
 процессорами семейства Intel :
 
 Introduction to the 80386, Order Number 231252.
 80386 Processor Hardware Reference Manual, Order Number 231732.
 80386 Processor System Software Writer's Guide, Order Number 231499.
 80386 High-Performance 32-Bit CHMOS Microprocessor with
 Integrated Memory Management, Order Number 231630.
 376(TM) Embedded Processor Programmer's Reference Manual, Order
 Number 240314.
 386(TM) DX Processor Programmer's Reference Manual, Order Number
 230985.
 386(TM) SX Processor Programmer's Reference Manual, Order Number
 240331.
 80387 Programmer's Reference Manual, Order Number 231917.
 376(TM) High-Performance 32-Bit Embedded Processor, Order Number
 240182.
 386(TM) SX Microprocessor, Order Number 240187
 Microprocessor and Peripherial Handbook (vol.1), Order Number
 230843.
 
 The i486(TM) Microprocessor Hardware Reference Manual аналогична
 данной книге и рекомендуется для использования разработчиками
 аппаратуры. Она содержит информацию, которая может быть полезной
 для программистов, особенно для системных программистов. Order
 Number 240552.
 
 The i486(TM) Microprocessor Data Sheet содержит самую свежую
 информацию, касающуюся параметров устройств (уровни напряжения,
 время выполнения циклов шины, приоритеты одновременных
 исключений и прерываний и т.д.). Order Number 240440.
 
 The i486(TM) Microprocessor Product Brief Book описывает
 множество различных продуктов, обычно используемых с ЦПУ i486.
 Order Number 240459.
 
 1.3 Соглашения об использыемых обозначениях
 ----------------------------------------------------------------
 
 Данное руководство использует специальные обозначения для
 форматов структур данных, мнемонического представления команд и
 шестнадцатиричных чисел. Обзор используемых обозначений
 упростит чтение данного руководства.
 
 1.3.1 Порядок битов и байтов.
 ----------------------------------------------------------------
 
 В иллюстрациях размещения структур данных в памяти младший
 адрес располагается в нижней части рисунка; адреса возрастают
 по направлению к верхней части. Нумерация битов производится
 справа налево. Числовое значение бита равняется двойке в степени
 положения бита. Для процессора i486 нумерация байт в слове
 начинается с наименьшего значащего байта. Рисунок 1-1
 иллюстрирует данное соглашение.
 
 Числа обычно представляются в десятичном виде (по основанию 10).
 Когда используется шестнадцатиричное число (по основанию 16),
 оно обозначается суффиксом 'H'.
 
 ???????????????????????????????????????????????????????????????
 ?                                                             ?
 ?                      СТРУКТУРА ДАННЫХ                       ?
 ?                                                             ?
 ?     СТАРШИЙ                                       БИТОВОЕ   ?
 ?     АДРЕС   31        23      15       7      0  СМЕЩЕНИЕ  ?
 ?             ???????????????????????????????????             ?
 ?             ??????????????????????????????????? 28          ?
 ?             ??????????????????????????????????? 24          ?
 ?             ??????????????????????????????????? 20          ?
 ?             ??????????????????????????????????? 16          ?
 ?             ??????????????????????????????????? 12          ?
 ?             ??????????????????????????????????? 8           ?
 ?             ?           НЕОПРЕДЕЛЕНО          ? 4           ?
 ?             ???????????????????????????????????             ?
 ?             ?  БАЙТ 3  БАЙТ 2  БАЙТ 1  БАЙТ 0 ? 0   МЛАДШИЙ ?
 ?             ???????????????????????????????????     АДРЕС   ?
 ?                                                            ?
 ?                                              БАЙТОВОЕ       ?
 ?                                              СМЕЩЕНИЕ       ?
 ???????????????????????????????????????????????????????????????
 
               Рисунок 1-1. Порядок Битов и Байтов.
 
 1.3.2 Неопределенные биты и совместимость программного
       обеспечения.
 ----------------------------------------------------------------
 
 Во многих регистрах и дескрипторах некоторые биты помечаются как
 зарезервированные. Когда биты помечены как неопределенные или
 зарезервированные, важным для совместимости с последующими
 поколениями процессоров является то, чтобы программное
 обеспечение интерпретировало данные биты как имеющие в будующем
 свое значение, в данный момент неизвестное. Программное
 обеспечение должно руководствоваться следующими правилами, когда
 дело касается зарезервированных битов :
 
 - Независимость от состояния любого из зарезервированных битов
   при тестировании значений регистров, содержащих такие биты.
   Следует маскировать такие биты, прежде чем проводить
   тестирование.
 
 - Независимость от состояния любого из зарезервированых битов
   при записи в память или в регистр.
 
 - Независимость от возможности сохранить информацию, записанную
   в любом из зарезервированных битов.
 
 - При загрузке регистра, всегда необходимо загружать
   зарезервированные биты значениями, указанными в документации,
   если таковые имеются, или загружать их значениями, которые
   прежде хранились в том же регистре.
 
                            ПРИМЕЧАНИЕ
 
 Зависимость от значений зарезервированных битов регистров делает
 программное обеспечение зависимым от неуказанного способа, при
 помощи которого процессор i486 управляет этими битами.
 Зависимость от зарезервированных значений приводит к риску
 несовместимости с будующими поколениями процессоров. ИЗБЕГАЙТЕ
 ЗАВИСИМОСТИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ОТ СОСТОЯНИЯ ЛЮБЫХ
 ЗАРЕЗЕРВИРОВАННЫХ БИТОВ РЕГИСТРОВ ПРОЦЕССОРА i486.
 
 1.3.3 Операнды команд.
 ----------------------------------------------------------------
 
 Когда команды описываются символически, используется
 подмножество языка ассемблера процессора i486. В этом
 подмножестве команда имеет следующий формат :
 
 метка: мнемоническое обозначение аргумент1, аргумент2, аргумент3
 
 где :
 
 - метка - это идентификатор, за которым следует двоеточие.
 
 - мнемоническое обозначение - зарезервированное название
   кода операции для класса команд, имеющих одинаковые функции.
 
 - операнды аргумент1, аргумент2, аргумент3 являются
   необязательными. В зависимости от кода операции может быть от
   нуля до трех операндов. Когда операнды есть, они имеют форму
   литералов или идентификаторов для обозначения данных.
   Идентификаторы операндов являются либо зарезервированными
   названиями регистров, либо предполагается, что они присвоены
   элементам данных, объявленных в другой части программы
   (которая может не быть приведена в примере).
 
 Когда в логической или арифметической операции указано два
 операнда, правый операнд является источником информации (операнд
 -источник), а левый операнд является местом сохранения
 результата (операнд-приемник). Некоторые ассемблерные языки
 расставляют источник и место хранения в обратном порядке.
 
 Например :
 
 LOADREG: MOV EAX, SUBTOTAL
 
 В этом примере LOADREG является меткой, MOV - это мнемоническое
 обозначение кода операции, EAX - место сохранения результата
 операции (приемник) и SUBTOTAL - исходный операнд (источник).
 
 1.3.4 Шестнадцатиричные числа.
 ----------------------------------------------------------------
 
 Числа по основанию 16 представляются в виде строки
 шестнадцатиричных цифр, за которыми следует символ Н.
 Шестнадцатиричной цифрой является символ из множества
 (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F). Если число начинается с одной
 из цифр A-F, перед ним ставится нуль. Например, 0FH равняется
 десятичному числу 15.
 
 1.3.5 Сегментная адресация.
 ----------------------------------------------------------------
 
 Процессор i486 использует побайтную адресацию. Это означает, что
 память организована в виде последовательности байтов и доступ к
 ней осушествляется как к последовательности байтов. Для доступа
 к одному или нескольким байтам, для адресации памяти
 используется его номер. Память, адресация которой может быть
 осуществлена таким способом, называется адресным пространством.
 
 Процессор i486 также поддерживает сегментную адресацию. Эта
 такая форма адресации, при которой программа может иметь много
 поименованных адресных пространств, называемых сегментами.
 Например, программа может хранить свой код (команды) и стек в
 разных сегментах. Адресация кодов всегда будет ссылаться на
 кодовое пространство, и адресация стека всегда будет ссылаться
 на стековое пространство. Ниже приведен пример обозначений,
 описываящий способ сегментной адресации:
 
 CS:EIP.
 
 Этот пример ссылается на байт внутри кодового сегмента. Номер
 байта хранится в регистре EIP.
 
 1.3.6 Исключения (особые ситуации).
 ----------------------------------------------------------------
 
 Исключением называется событие, которое возникает, когда команда
 порождает ошибку. Например, попытка деления на ноль порождает
 исключение. Имеется несколько различных типов исключений, и
 некоторые из этих типов могут порождать коды ошибок. Код ошибки
 содержит дополнительную информацию об ошибке. Коды ошибок
 генерируются только для некоторых исключений. Пример
 обозначения, используемого для лдя иллюстрации исключения и кода
 ошибки, приведен ниже.
 
 #PF(код ошибки).
 
 Этот  пример ссылается на исключение сбоя страницы при
 условии, что код ошибки указывает конкретный тип сбоя страницы.
 При некоторых условиях исключения, которые генерируют код
 ошибки, могут не иметь возможности породить верный код. В этом
 случае код ошибки равен нулю, как показано ниже :
 
 Часть II  Системное программирование
 -----------------------------------------------------------------
 
 Глава 4   Архитектура системы
 -----------------------------------------------------------------
 
 Многие свойства архитектуры процессора i486 используются только
 системными программистами. В данной главе содержится обзор этих
 свойств. Прикладным программистам также может понадобиться
 прочесть эту и последующие главы, описывающие свойства
 архитектуры процессора, для понимания того, какие аппаратные
 средства используются системными программистами для создания
 надежной и защищенной среды разработки прикладных программ.
 Архитектура системного уровня также поддерживает мощные
 отладочные средства, доступные прикладным программистам при
 разработке программ.
 
 Свойства системного уровня архитектуры процессора включают в
 себя:
 
      Организация памяти
      Защита
      Многозадачность
      Ввод/вывод
      Особые ситуации и прерывания
      Инициализация
      Сопроцессорная и многопроцессорная обработка
      Отладка
      Организация кеширования памяти
 
 Эти свойства поддерживаются регистрами и командами процессора,
 рассматриваемыми в следующих разделах. Назначение данной главы
 состоит не в том, чтобы подробно объяснять каждое из этих
 свойств, а в том, чтобы дать общую перспективу размещения
 посвященных им материалов в главах части II. При упоминании тех
 или иных регистров и команд сразу же дается пояснение или ссылка
 на их описание в одной из последующих глав.
 
 4.1  Системные регистры
 -----------------------------------------------------------------
 
 Регистры, предназначенные для использования системными
 программистами, делятся на следующие категории:
 
      Регистр флагов EFLAGS
      Регистры организации памяти
      Управляющие регистры
      Отладочные регистры
      Тестовые регистры
 
 Системные регистры управляют средой, в которой происходит
 выполнение прикладных программ. В большинстве систем доступ к
 этим регистрам из прикладных программ запрещен (хотя возможно
 построение и таких систем, в которых все программы работают на
 наиболее привилегированном уровне, что означает возможность
 доступа к системным регистрам и их модификацию из прикладных
 программ).
 
 4.1.1  Системные флаги
 -----------------------------------------------------------------
 
 Системные флаги в регистре EFLAGS управляют вводом/выводом,
 маскируемыми прерываниями, отладкой, переключением между
 задачами, а также виртуальным режимом 8086. Прикладными
 программами эти флаги должны игнорироваться, а попытки
 модификации их состояния из прикладных программ недопустимы. В
 большинстве систем попытка изменения системного флага из
 прикладной программы приводит к возникновению исключения (особой
 ситуации). Флаги показаны на Рисунок 4.1.
 
 AC (Режим контроля выравнивания в памяти, бит 18)
 
 Установка флага AC и бита AM в регистре CR0 разрешает контроль
 выравнивания при обращениях к памяти. В случае обращения к
 невыравненному операнду в памяти, например к операнду размером в
 слово по нечетному адресу памяти или к операнду размером в
 двойное слово по адресу памяти, не кратному четырем,
 генерируется исключение контроля выравнивания. Исключения
 контроля выравнивания генерируются только в режиме пользователя
 (уровень привилегированности 3). Ссылки к памяти, по умолчанию
 имеющие уровень привилегированности 0, такие как загрузка
 дескриптора сегмента, не генерируют данного исключения даже в
 тех случаях, когда они былм выполнены в режиме пользователя.
 
 Прерывание контроля выравнивания может быть использовано для
 контроля выравнивания данных в памяти. Это средство может быть
 полезным при обмене данными с другими процессорами, например, 64
 -разрядным микропроцессором i860, который требует выравнивание
 всех обрабатываемых им данных. Прерывание контроля выравнивания
 может также использоваться интерпретаторами для того, чтобы
 отметить некоторый указатель как специальный, намеренно нарушив
 для этого выравнивание данного указателя. Тем самым отпадает
 необходимость проверять все указатели в поисках искомого и
 обрабатывать только специальный указатель, если он был таким
 способом обозначен.
 ???????????????????????????????????????????????????????????????????
 ?                                                                 ?
 ?                           1 1 1 1 1 1 1 1 1                     ?
 ? 31                        8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ?
 ???????????????????????????????????????????????????????????????????
 ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?   ? ? ? ? ? ? ? ? ? ? ? ? ??
 ??0?0?0?0?0?0?0?0?0?0?0?0?0?A?V?R?0?N?I O?O?D?I?T?S?Z?0?A?0?P?1?C??
 ?? ? ? ? ? ? ? ? ? ? ? ? ? ?C?M?F? ?T?P L?F?F?F?F?F?F? ?F? ?F? ?F??
 ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?   ? ? ? ? ? ? ? ? ? ? ? ? ??
 ???????????????????????????????????????????????????????????????????
 ?                           ? ? ?   ?  ?      ? ?                 ?
 ?   Проверка выравнивания ??? ? ?   ?  ?      ? ?                 ?
 ?   Флаг режима виртуального ?? ?   ?  ?      ? ?                 ?
 ?   процессора 8086             ?   ?  ?      ? ?                 ?
 ?   Флаг возобновления ??????????   ?  ?      ? ?                 ?
 ?   Флаг вложенности задачи ?????????  ?      ? ?                 ?
 ?   Уровень привилегий ввода-вывода ????      ? ?                 ?
 ?   Разрешение прерываний ????????????????????? ?                 ?
 ?   Флаг ловушки ????????????????????????????????                 ?
 ?                                                                 ?
 ?                                                                 ?
 ? 1 или 0 обозначают биты, зарезервированные фирмой Intel         ?
 ? Данные регистры не используются, а их значения всегда постоянны ?
 ?                                                                 ?
 ???????????????????????????????????????????????????????????????????
 
                   Рисунок 4-1. Системные флаги
 
 VM (Виртуальный режим 8086, бит 17)
 
 Установка флага VM переводит процессор в виртуальный режим 8086,
 в котором эмулируется среда программирования для процессора
 8086. Более подробная информация приводится в Главе 23.
 
 RF (Флаг возобновления, бит 16)
 
 Флаг RF временно отменяет действие отладочных исключений,
 поэтому после такого исключения может быть выполнена другая
 команда и это не приведет к немедленному генерированию другого
 отладочного исключения. При входе в отладчик этот флаг
 обеспечивает его нормальное функционирование; в противном случае
 отладчик выполнял бы рекурсивные вызовы самого себя до тех пор,
 пока не произошло бы переполнение стека. Команда POPF на флаг RF
 воздействия не оказывает, но команды POPFD и IRET влияют на
 состояние этого флага. Более подробная информация приводится в
 Главах 7 и 11.
 
 NT (Флаг вложенности задачи, бит 14)
 
 Процессор использует флаг вложенности задачи для управления
 последовательностью выполнения прерванных и вызванных задач.
 Флаг NT оказывает влияние на работу команды IRET. Команды POPF,
 POPFD и IRET воздействуют на состояние флага NT. Неверные
 изменения состояния данного флага могут привести к генерации
 неожиданных исключений в прикладных программах. Более подробную
 информацию о вложенных задачах см. в Главах 7 и 9.
 
 IOPL (Уровень привилегий ввода/вывода, биты 12 и 13)
 
 Уровень привилегированности ввода/вывода используется механизмом
 защиты для управления доступом к адресному пространству
 ввода/вывода. Уровень привилегированности выполняемого в текущий
 момент кодового сегмента (CPL) и IOPL определяют, может ли
 данное поле быть модифицировано командами POPF, POPFD и IRET.
 Более подробную информацию см. в Главе 8.
 
 IF (Флаг разрешения прерываний, бит 9)
 
 Установка флага IF переводит процессор в режим, в котором он
 отвечает на запросы маскируемых прерываний (прерывания INTR).
 Очистка флага IF отменяет эти прерывания. Флаг IF не оказывает
 воздействия на особые ситуации или немаскируемые (NMI)
 прерывания. CPL и IOPL опеределяют, может ли это поле быть
 модифицировано командами CLI, STI, POPF, POPFD и IRET. Более
 подробную информацию о прерываниях см. в Главе 9.
 
 TF (Флаг ловушки, бит 8)
 
 Установка флага TF переводит процессор в режим пошаговой работы
 для отладки программ. В этом режиме процессор после выполнения
 каждой команды генерирует отладочное исключение, что позволяет
 наблюдать за тем, как выполненяется каждая команда программы.
 Пошаговое выполнение представляет собой одно из отладочных
 средств процессора i486. Если прикладная программа устанавливает
 при помощи команд POPF, POPFD или IRET флаг TF, то генерируется
 отладочное исключение. Более подробную информацию см. в Главах 9
 и 11.
 
 4.1.2  Регистры управления памятью
 -----------------------------------------------------------------
 
 Как показано на Рисунок 4-2, четыре регистра процессора i486
 задают расположение структур данных, которые управляют
 организацией сегментированной памяти. Для загрузки и сохранения
 этих регистров имеются специальные команды. Регистры GDTR и IDTR
 могут быть загружены при помощи команд, извлекающих из памяти
 шести-байтовые блоки. Регистры LDTR и TR могут быть загружены
 при помощи команд, принимающих в качестве операнда 16-битовый
 селектор сегмента. Затем остальные байты этих регистров
 загружаются процессором автоматически из дескриптора, на который
 ссылается переданный операнд.
 
 Большинство систем защищает команды, загружающие регистры
 организации памяти от использования в прикладных программах
 (хотя возможна и система, не имеющая такого рода защиты).
 
 Регистр таблицы глобальных дескрипторов GDTR
 
 Этот регистр содержит 32-битовый базовый адрес и 16-битовую
 границу сегмента для таблицы глобальных дескрипторов (GDT). При
 ссылке на данные в памяти для того, чтобы найти дескриптор
 сегмента в GDT или LDT используется селектор сегмента.
 Дескриптор сегмента содержит базовый адрес сегмента.
 Сегментирование рассматривается в Главе 5.
 
 Регистр таблицы локальных дескрипторов LDTR
 
 Этот регистр содержит 32-битовый базовый адрес, 16-битовую
 границу сегмента и 16-битовый селектор сегмента для таблицы
 локальных дескрипторов (LDT). Сегмент, который содержит LDT,
 имеет соответствующий дескриптор сегмента в GDT. Дескриптора
 сегмента для GDT не существует. При ссылке на данные в памяти
 для того, чтобы найти дескриптор сегмента в GDT или LDT
 используется селектор сегмента. Дескриптор сегмента содержит
 базовый адрес сегмента. Сегментирование рассматривается в Главе
 5.
 
 
       Регистры системных адресов
 
          32-битовый линейный
             базовый адрес           Граница
       47                      16 15          0
       -----------------------------------------
   GDTR |                         |             |
       -----------------------------------------
   LDTR |                         |             |
       -----------------------------------------
 
      Системные   Регистры дескрипторов (автоматически загружаемые)
      сегментные
      регистры
       ___^__      _______________________^_______________________
      /      \    /                                               \
                  32-битовый линейный 32-битовая граница  Аттрибуты
      15       0  базовый адрес       сегмента
      ----------  -------------------------------------------------
   TR  |селектор|  |                  |                  |  |   |  |
      ----------  -------------------------------------------------
   IDTR|селектор|  |                  |                  |  |   |  |
      ----------  -------------------------------------------------
 
             Рисунок 4-2. Регистры управления памятью
 
 Регистр таблицы дескриптора прерываний IDTR
 
 Этот регистр содержит 32-разрядный базовый адрес и 16-разрядную
 границу сегмента для таблицы дескрипторов прерываний. Когда
 происходит прерывание, вектор прерывания используется в качестве
 индекса для получения из данной таблицы дескриптора шлюза.
 Последний сдержит указатель, используемый для запуска
 обработчика прерываний. Более подробную информацию о механизме
 прерываний см. в Главе 9.
 
 Регистр задачи TR
 
 Этот регистр содержит 32-разрядный базовый адрес, 16-разрядную
 границу сегмента, аттрибуты дескриптора и 16-разрядный селектор
 сегмента для текущей выполняемой задачи. Он содержит ссылку на
 дескриптор сегмента состояния задачи (TSS), находящийся в
 таблице глобального дескриптора. Более подробную информацию о
 средствах мультизадачности процессора i486 см. в Главе 7.
 
 4.1.3  Регистры управления
 -----------------------------------------------------------------
 
 На Рисунке 4-3 показан формат управляющих регистров CR0, CR1,
 CR2 и CR3. В большинстве систем загрузка управляющих регистров
 из прикладных программ невозможна (хотя в незащищенных системах
 такая загрузка разрешается). Прикладные программы имеют
 возможность считывать эти регистры для определения наличия
 математического сопроцессора. Некоторые разновидности команды
 MOV позволяют загружать управляющие регистры из регистров общего
 назначения, и наоборот. Например,
 
      MOV  EAX,  CR0
      MOV  CR3,  EBX
 
 Регистр CR0 содержит системные управляющие флаги, которые
 управляют режимами или указывают на состояние процессора в
 целом, а не относительно выполнения конкретных задач. Программа
 не должна пытаться изменить состояние каких-либо битов в
 зарезервированных позициях. Эти зарезервированные биты всегда
 должны устанавливаться в то состояние, которое они имели ранее
 при считывании.
 
 
 31          23            15             7       3       0
 -----------------------------------------------------------
 |   Базовый регистр страничного   |           |P|P|       |
 |       каталога (PBDR)           |           |C|W|       | CR3
 |                                 |           |D|T|       |
 -----------------------------------------------------------
 |            Линейный адрес сбоя страницы                 | CR2
 -----------------------------------------------------------
 |                     Зарезервировано                     | CR1
 -----------------------------------------------------------
 |P|C|N|         |A| |W|   Зарезервировано     |N|E|T|E|M|P| CR0
 |G|D|W|         |M| |P|                       |E|T|S|M|P|E|
 -----------------------------------------------------------
      29         18  16
 
                Рисунок 4-3.  Управляющие регистры
 
 Команда LMSW может модифицировать только младшие 16 битов
 регистра CR0.
 
 PG (Подкачка страниц, бит 31)
 
 Данный бит разрешает подкачку страниц, если он установлен, и
 запрещает ее, если он очищен. Более подробная информация о
 подкачке страниц находится в Главе 5. В Главе 10 описано, как
 разрешить подкачку страниц.
 
 Когда при подкачке страниц возникает исключение, в регистр CR2
 помещается 32-разрядный линейный адрес, вызвавший это
 исключение. Информация об обработке исключений, генерируемых при
 подкачке страниц (отсутствие нужной страницы) находится в Главе
 9.
 
 При использовании подкачки страниц регистр CR3 содержит 20
 наиболее значащих битов адреса страничного каталога (таблицы
 страниц первого уровня). Регистр CR3 также называется базовым
 регистром страничного каталога (PDBR). Отметим, что страничный
 каталог должен быть выравнен по границе страницы, поэтому 12
 младших битов регистра игнорируются. В отличие от процессора 386
 DX, процессор i486 назначает функции двум из этих битов. Это:
 
 PCD (Запрещение  кеширования  на  уровне страниц,  бит 4 регистра
 CR3)
 
 Состояние этого бита устанавливается в зависимости от состояния
 штырька PCD во время циклов шины, не работающих со страницами
 (например, циклов квитирования прерывания), когда подкачка
 страниц разрешена. Если подкачка страниц запрещена, то состояние
 этого бита устанавливается в любых циклах шины. Штырек PCD
 используется для управления работой внешнего кеша по циклам.
 
 PWT (Прозрачность записи на уровне страниц, бит 3 регистра CR3)
 
 Состояние этого бита устанавливается в зависимости от состояния
 штырька PWT во время циклов шины, не работающих со страницами
 (например, циклов квитирования прерывания), когда подкачка
 страниц разрешена. Если подкачка страниц запрещена, то состояние
 этого бита устанавливается в любых циклах шины. Штырек PWT
 используется для управления сквозной записью во внешний кеш по
 циклам.
 
 CD (Запрещение кеширования, бит 30)
 
 Данный бит разрешает внутреннее кеширование, если он очищен, и
 запрещает, если он установлен. Когда данный бит установлен,
 несовпадения кеша не вызывают заполнения строки кеша. Отметим,
 что совпадения кеша при этом не отменяются; для полного
 запрещения кеша он должен быть очищен.
 
 NW (Сквозная запись не происходит, бит 29)
 
 Данный бит разрешает сквозную запись и циклы аннулирования кеша,
 если он очищен, и запрещает циклы аннулирования и сквозную
 запись, ищущую совпадения кеша, если он установлен. Информация о
 кешировании находится в Главе 12. Отмена сквозной записи
 позволяет хранить в кеше данные о состоянии.
 
 AM (Маска выравнивания, бит 18)
 
 Этот бит позволяет выполнять контроль выравнивания, если он
 установлен, и запрещает этот контроль, если он очищен. Контроль
 выравнивания выполняется только когда бит AM установлен, флаг AC
 установлен, а CLP имеет значение 3 (режим пользователя).
 
 WP (Защита записи, бит 16)
 
 Если этот бит установлен, то он защищает от записи страницы
 уровня пользователя при доступе в режиме супервизора. Если этот
 бит очищен, то страницы уровня пользователя, предназначенные
 только для чтения, могут быть затерты записью процессом
 супервизора. Это свойство может быть полезным для реализации
 метода "записи в копию" создания нового процесса (ветвления
 параллельных процессов), используемого некоторыми операционными
 системами (например, UNIX).
 
 NE (Числовая ошибка, бит 5)
 
 Этот бит разрешает стандартный механизм сообщений об ошибках при
 числовых операциях с плавающей точкой, если он установлен. Когда
 NE очищен, а вход IGNNE# активен, числовые ошибки игнорируются.
 Когда бит NE очищен, а вход IGNNE# не активен, числовая ошибка
 ведет к останову процессора и ожиданию прерывания. Прерывание
 генерируется при помощи штырька FERR#, формирующего ввод в
 контроллер прерываний (штырек FERR# эмулирует штырек ERROR#
 сопроцессоров 80287 и 387 DX). Бит NE, штырек IGNNE # и штырек
 FERR# используются внешними логическими схемами для реализации
 сообщений об ошибках в стиле PC.
 
 ET (Тип расширения, бит 4)
 
 Этот бит служит для того, чтобы указывать на поддержку команд
 математического сопроцессора 387 DX (Intel резервируется).
 
 TS (Переключение задачи, бит 3)
 
 Процессор устанавливает бит TS при каждом переключении задачи и
 проверяет его при интерпретации арифметических команд с
 плавающей точкой. Данный бит позволяет откладывать
 сохранение/восстановление числовых данных до их фактического
 использования. Команда CLTS очищает этот бит.
 
 EM (Эмуляция, бит 2)
 
 Если установлен один из битов, EM или TS, то выполнение команды
 WAIT или числовой команды генерирует исключение "сопроцессор
 недоступен". EM может быть установлен для получения исключения 7
 для каждой команды WAIT или числовой команды.
 
 MP (Математический сопроцессор присутствует, бит 1)
 
 В случае процессоров 80286 и 386 DX бит MP управляет работой
 команды WAIT, используемой для синхронизации с сопроцессором.
 При выполнении программ на процессоре i486 данный бит должен
 быть установлен.
 
 PE (Разрешение защиты, бит 0)
 
 Установка бита PE разрешает защиту на уровне сегмента. Более
 подробную информацию о защите см. в Главе 6. Информацию о
 разрешении и запрещении подкачки страниц см. в Главах 10 и 22.
 
 4.1.4  Отладочные регистры
 -----------------------------------------------------------------
 
 Отладочные регистры дают процессору i486 расширенные возможности
 отладки, включая контрольные точки данных и средство
 устанавливать контрольные точки команд без модификации кодовых
 сегментов (что может быть полезным при отладке ПЗУ-резидентного
 программного обеспечения). Доступ к этим регистрам имеют только
 программы с наивысшим уровнем привилегированности. В Главе 11
 находится полное описание их форматов и способа использования.
 Отладочные регистры показаны на Рисунке 4-4.
 
 4.1.5  Тестовые регистры
 ----------------------------------------------------------------
 
 Тестовые регистры не являются формальной частью архитектуры
 процессора. Они представляют собой зависящее от конкретной
 реализации средство, предназначенное для тестирования
 ассоциативного буфера трансляции (TLB) и кеша. Полное описание
 их формата и использования см. в Главе 10. Тестовые регистры
 показаны на Рисунок 4-5.
 
 31               23              15              7             0
 -----------------------------------------------------------------
 |LEN|R/W|LEN|R/W|LEN|R/W|LEN|R/W|0 0|0|0 0 0|G|L|G|L|G|L|G|L|G|L|DR7
 | 3 | 3 | 2 | 2 | 1 | 1 | 0 | 0 |   | |     |E|E|3|3|2|2|1|1|0|0|
 -----------------------------------------------------------------
 |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|S|S|S|0 0 0 0 0 0 0 0 0|S|S|S|S|DR6
 |                               |T|S|D|                 |3|2|1|0|
 ----------------|---------------|---------------|----------------
 |                        Зарезервировано                        |DR5
 ----------------|---------------|---------------|----------------
 |                        Зарезервировано                        |DR4
 ----------------|---------------|---------------|----------------
 |                Линейный адрес контрольн.точки 3               |DR3
 ----------------|---------------|---------------|----------------
 |                Линейный адрес контрольн.точки 2               |DR2
 ----------------|---------------|---------------|----------------
 |                Линейный адрес контрольн.точки 1               |DR1
 ----------------|---------------|---------------|----------------
 |                Линейный адрес контрольн.точки 0               |DR0
 ----------------|---------------|---------------|----------------
 
      Рисунок 4-4.  Отладочные регистры
 
                                        1 1 1
 31                                     2 1 0 9 8 7 6 5 4 3 2 1 0
 -----------------------------------------------------------------
 |                                       |P|P| LRU |0 0|P| R |0 0|
 | Физический адрес                      |C|W|     |   |L| E |   |TR7
 |                                       |D|T|     |   | | P |   |
 -----------------------------------------------------------------
 |                                       | | |D| |U| |W|       | |
 | Линейный адрес                        |V|D|#|U|#|W|#|0 0 0 0|C|TR6
 |                                       | | | | | | | |       | |
 -----------------------------------------------------------------
 |                                         |             | E | C |
 | Не используется                         |   Выбор     | N | T |TR5
 |                                         | набора      | T | L |
 -----------------------------------------------------------------
 |                                         | |     |       |     |
 | Линейный адрес                          |V| LRU | VALID |0 0 0|TR4
 |                                         | |     |       |     |
 -----------------------------------------------------------------
 |                      Данные                                   |TR3
 -----------------------------------------------------------------
 
 
 LRU - признак наиболее давнего использования для метода "удаления
       стариков"
 V     VALID    (Допустимо)
 CTL   CONTROL  (Управление)
 ENT   ENTRY    (Вход)
 
                 Рисунок 4-5.  Тестовые регистры
 
 4.2  Системные команды
 -----------------------------------------------------------------
 
 Системные команды выполняют следующие функции:
 
 1. Верификация параметров указателей (см. Главу 6):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | ARPL    | Настройка RPL               |   Нет     |   Нет     |
 | LAR     | Загрузка прав доступа       |   Да      |   Нет     |
 | LSL     | Загрузка границы сегмента   |   Да      |   Нет     |
 | VERR    | Верификация для чтения      |   Да      |   Нет     |
 | VERW    | Верификация для записи      |   Да      |   Нет     |
 -----------------------------------------------------------------
 
 2. Адресация таблиц дескриптора (см. Главу 5):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | LLDT    | Загрузка регистра LDT       |   Да      |   Нет     |
 | SLDT    | Сохранение регистра LDT     |   Да      |   Нет     |
 | LGDT    | Загрузка регистра GDT       |   Нет     |   Да      |
 | SGDT    | Сохранение регистра GDT     |   Нет     |   Нет     |
 -----------------------------------------------------------------
 
 3. Мультизадачность (см. Главу 7):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | LTR     | Загрузка регистра задачи    |   Нет     |   Да      |
 | STR     | Сохранение регистр задачи   |   Да      |   Нет     |
 -----------------------------------------------------------------
 
 4. Числовые операции с плавающей точкой (см. Часть III):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | CLTS    | Очистка бита TS в CR0       |   Нет     |   Да      |
 | ESC     | Управляющие команды         |   Да      |   Нет     |
 | WAIT    | Ждать освобождения          |   Да      |   Нет     |
 |         | сопроцессора (Not Busy)     |           |           |
 -----------------------------------------------------------------
 
 5.  Ввод и вывод (см. Главу 8):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | IN      | Ввод                        |   Да      | Может быть|
 | OUT     | Вывод                       |   Да      | Может быть|
 | INS     | Ввод строки                 |   Да      | Может быть|
 | OUTS    | Вывод строки                |   Да      | Может быть|
 -----------------------------------------------------------------
 
 6.  Управление прерываниями (см. Главу 9):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | CLI     | Очистить флаг IF            | Может быть| Может быть|
 | STI     | Сохранить флаг IF           | Может быть| Может быть|
 | LIDT    | Загрузить регистр IDT       |   Нет     |   Да      |
 | SIDT    | Сохранить регистр IDT       |   Нет     |   Нет     |
 -----------------------------------------------------------------
 
 7.  Отладка (см. Главу 11):
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | MOV     | Загрузка и сохранение       |   Нет     |   Да      |
 |         | отладочных регистров        |           |           |
 -----------------------------------------------------------------
 
 8.  Организация кеша:
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | INVD    | Аннулирование кеша          |   Нет     |   Да      |
 |         | с обратной записью          |           |           |
 | WBINVD  | Аннулирование кеша          |   Нет     |   Да      |
 |         | без обратной записи         |           |           |
 | INVLPG  | Аннулирование ввода TLB     |   Нет     |   Да      |
 -----------------------------------------------------------------
 
 9.  Управление системой:
 
 -----------------------------------------------------------------
 | Команда |          Описание           |Полезна в  |Защищена от|
 |         |                             |прикладных |прикладных |
 |         |                             |программах?|программ?  |
 -----------------------------------------------------------------
 | SMSW    | Сохранение MSW              |   Нет     |   Нет     |
 | LMSW    | Загрузка MSW                |   Нет     |   Да      |
 | MOV     | Загрузка и сохранение       |   Нет     |   Да      |
 |         | управляющего регистра       |           |           |
 | HLT     | Останов процессора          |   Нет     |   Да      |
 | LOCK    | Захват шины                 |   Нет     | Может быть|
 -----------------------------------------------------------------
 
 Команды SMSW и LMSW обеспечивают совместимость с процессором
 80286. Программа для процессора i486 не должна использовать эти
 команды. Доступ к управляющим регистрам выполняется при помощи
 разновидностей команды MOV. Команда LMSW не влияет на биты PG,
 CD, NW, AM, WP, NE или ET и не может быть использована для
 очистки бита PE.
 
 Команда HLT останавливает процессор до приема разрешенного
 прерывания или сигнала RESET. (Отметим, что немаскируемые
 прерывания разрешены всегда). Процессор генерирует специальный
 цикл шины, которым обозначает вход в режим останова. Аппаратное
 обеспечение может отреагировать на этот сигнал несколькими
 способами. Может включиться светодиод индикатора на передней
 панели. Может быть генерировано немаскируемое прерывание для
 записи диагностической информации. Может произойти активизация
 инициализатора сброса системы. Разработчики программного
 обеспечения должны знать аппаратную реакцию на режим останова
 процессора.
 
 Командный префикс LOCK используется для запуска монопольной
 (элементарной) операции чтения-модификации-записи при
 модификации операнда памяти. Выдается сигнал LOCK#, и процессор
 не реагирует на запросы на управление шиной до окончания
 монопольной операции. Этот механизм служит для обеспечения
 надежной связи между процессорами в многопроцессорных системах.
 
      Помимо упомянутых  выше  глав,  подробная  информация о каждой из
 этих команд приводится в справочнике по командам  процессора,  который
 находится в Главе 26.
 
 
 Глава 5   Организация памяти
 -----------------------------------------------------------------
 
 Организация памяти представляет собой аппаратный механизм,
 позволяющий операционной системе создавать для выполняющихся
 программ упрощенную среду. Например, при одновременном
 выполнении нескольких программ каждой из них должно быть дано
 независимое адресное пространство. При разделении всеми этими
 программами одного и того же адресного пространства каждая из
 них должна была бы выполнять сложные и занимающие много
 процессорного времени проверки, чтобы избежать влияния на другие
 программы.
 
 Организация памяти состоит из сегментации и подкачки страниц.
 Сегментация служит для того, чтобы дать каждой программе
 несколько независимых, защищенных адресных пространств. Подкачка
 страниц используется для поддержки среды, в которой большие
 адресные пространства моделируются на базе небольшой области
 оперативной памяти и некоторой дисковой памяти. Разработчики
 систем могут использовать как оба этих механизма, так и любой из
 них. При одновременном выполнении нескольких программ для защиты
 программ от влияния на них других программ можно использовать
 любой механизм.
 
 Сегментация позволяет иметь полностью неструктурированную и
 простую память, подобную модели памяти 8-битового процессора,
 либо высоко структурированную память, с использованием
 трансляции адресов и защиты. Средства организации памяти
 работают с единицами, которые называются сегментами. Каждый
 сегмент представляет собой независимое, защищенное адресное
 пространство. Доступ к сегментам управляется данными, в которых
 описаны их размер, уровень привилегированности, который нужен
 для доступа к ним, типы ссылок к памяти, применимые к этому
 сегменту (выборка команды, помещение или извлечение из стека,
 операция чтения, операция записи и т.д.), а также его
 присутствие в памяти.
 
 Сегментация служит для управления доступом к памяти, что полезно
 для нахождения ошибок при разработке программы и для повышения
 надежности конечного продукта. Она также используется для
 упрощения компоновки объектных модулей кода. Механизм
 сегментации делает ненужным создание кодов, независимых от
 позиции в памяти, поскольку все ссылки к памяти могут
 выполняться относительно базового адреса кодового сегмента и
 сегмента данных модуля. Сегментация может быть использована для
 создания ПЗУ-резидентных программных модулей, в которых
 фиксированные адреса (фиксированные в том смысле, что они не
 могут быть изменены) представляют собой смещения относительно
 базового адреса сегмента. Различные программные системы могут
 иметь модули ПЗУ в различных физических адресах, поскольку
 механизм сегментации в любом случае позволяет правильно
 направить все ссылки к памяти.
 
 В случае простой архитектуры памяти все адреса относятся к
 одному и тому же адресному пространству. Это модель памяти,
 используемая 8-битовыми микропроцессорами, такими как 8080, где
 логический и физический адреса совпадают. Процессор i486 может
 быть использован подобным же образом посредством отображения
 всех сегментов в одном и том же адресном пространстве и
 запрещения подкачки страниц памяти. Такая модель может
 понадобиться при адаптации старых разработок для 32-разрядной
 машины без учета новых архитектурных средств этой машины.
 
 Прикладная программа также частично может использовать механизм
 сегментации. Частая причина отказа программного обеспечения
 состоит в том, что стек растет и "вклинивается" в область
 командных кодов или данных программы. Для того, чтобы
 предотвратить такого рода ошибку, можно воспользоваться
 мехнизмом сегментации. Стек можно поместить в другое адресное
 пространство, нежели то, где находятся кодовый сегмент и сегмент
 данных. Адреса стека всегда будут относиться к памяти стекового
 сегмента, тогда как адреса данных всегда будут относиться к
 памяти, распределенной сегменту данных. Стековый сегмент будет
 иметь максимальный размер, принудительно установленный
 аппаратным обеспечением. Любая попытка увеличить размер стека за
 установленное значение приведет к возникновению исключения.
 
 Сложная программная система может использовать все средства,
 предоставляемые сегментацией. Например, система, в которой
 программы разделяют данные в режиме реального времени, может
 иметь возможность очень точно управлять доступом к этим данным.
 Когда программа делает попытку неверного доступа к данным, такая
 ошибка приводит к генерированию исключения. Это может служить
 как вспомогательное отладочное средство при разработке
 программы, а также может использоваться для запуска
 восстановительных процедур при ошибке в системах,
 предназначенных для конечного пользователя.
 
 Аппаратное обеспечение сегментации транслирует сегментированный
 (логический) адрес в адрес непрерывного, несегментированного
 адресного пространства, который называется линейным адресом.
 Если разрешена подкачка страниц, то аппаратное обеспечение
 подкачки транслирует линейный адрес в физический адрес. Если
 подкачка страниц не разрешена, то в качестве физического адреса
 используется сразу линейный адрес. Физический адрес подается на
 выходящую из процессора адресную шину.
 
 Подкачка страниц представляет собой механизм, который служит для
 моделирования большого несегментированного адресного
 пространства при помощи малого фрагментированного адресного
 пространства и некоторого объема дисковой памяти. Подкачка
 страниц обеспечивает доступ к структурам данных, превышающим по
 размеру доступное пространство оперативной памяти, благодаря
 тому, что часть таких структур держится в оперативной памяти, а
 часть - на диске.
 
 Подкачка выполняется по блокам размером в 4К, которые и
 называются страницами. Когда программа пытается обратиться к
 странице, которая в этот момент находится на диске, в программе
 происходит специальное прерывание. В отличие от прочих
 исключений и прерываний, исключение, генерируемое при
 транслировании адреса, восстанавливает содержимое регистров
 процессора в значения, позволяющие повторить выполнение команды,
 вызвавшей данное исключение. Такие специальные действия носят
 названия перезапуска команды. Это позволяет операционной системе
 прочесть страницу с диска, обновить отображение линейных адресов
 в физические адреса для данной страницы и перезапустить
 программу. Такой процесс прозрачен для программы.
 
 Если операционная система никогда не устанавливает бит 31
 регистра CR0 (бит PG), механизм подкачки страниц никогда не
 будет разрешен. Тогда линейные адреса будут одновременно
 являться и физическими адресами. Это может быть в тех случаях,
 когда разработка, которая была сделана для 16-разрядного
 процессора, адаптируется для использования 32-разрядного
 процессора. Операционная система, написанная для 16-разрядного
 процессора, не использует механизма подкачки страниц, поскольку
 размер ее адресного пространства настолько мал (64Кбайт), что
 гораздо более эффективным является механизм свопинга между
 оперативной памятью и диском целых сегментов, нежели отдельных
 страниц памяти.
 
 Подкачка страниц должна быть разрешена для операционных систем,
 которые могут поддерживать виртуальную память с подкачкой
 страниц по требованию, например UNIX. Подкачка страниц прозрачна
 для прикладного программного обеспечения, поэтому операционная
 система, которая должна поддерживать прикладные программы,
 написанные для 16-битовых процессоров, может выполнять эти
 программы с разрешенной подкачкой страниц. В отличие от
 подкачки, сегментация не прозрачна для прикладных программ.
 Программы, использующие сегментацию, должны выполняться с теми
 сегментами, которые были назначены для использования при
 разработке этих программ.
 
 5.1  Выбор модели сегментации
 -----------------------------------------------------------------
 
 Выбор модели сегментации памяти выполняется на основе требований
 надежности и быстродействия. Например, система, состоящая из
 нескольких программ, разделяющих данные в режиме реального
 времени, будет иметь наилучшие характеристики быстродействия при
 выборе модели, которая аппаратно контролирует ссылки к памяти.
 Это многосегментная модель памяти.
 
 В качестве другой крайности, рассмотрим систему, состоящую всего
 из одной выполняемой программы - такая система позволяет
 получить максимальный выигрыш в случае несегментированной
 "плоской" модели памяти. Отсутствие в программе "дальних"
 указателей и префиксов переопределения сегмента уменьшает размер
 кода и увеличивает его быстродействие. Также быстрее выполняются
 контекстные перключения, поскольку нет необходимости сохранять и
 восстанавливать содержимое сегментных регистров.
 
 Некоторые преимущества от использования сегментации также
 обеспечиваются за счет подкачки страниц. Например, разделение
 данных может выполняться за счет отображения одних и тех же
 страниц памяти в адресное пространство каждой программы.
 
 5.1.1  Плоская модель
 -----------------------------------------------------------------
 
 Самой простой моделью является плоская модель. В этом случае все
 сегменты отображаются в единое физическое адресное пространство.
 Смещение сегмента может относиться либо к области кода, либо к
 области данных. Данная модель в наивысшей степени исключает
 механизм сегментации из архитектуры, видимой как разработчику
 системы, так и прикладному программисту. Такая модель выбирается
 для программной среды типа UNIX, которая поддерживает подкачку
 страниц, но не поддерживает сегментацию.
 
 Сегмент определяется дескриптором сегмента. Для плоской модели
 должно создаваться минимум два дескриптора, один для ссылок к
 коду, а другой для ссылок к данным. Оба дескриптора имеют
 одинаковое значение базового адреса. Всякий раз при доступе к
 памяти содержимое одного из сегментных регистров используется
 для выбора дескриптора сегмента. Дескриптор сегмента содержит
 базовый адрес сегмента и его границу, а также информацию,
 управляющую доступом (см. Рисунок 5-1).
 
 Сегментные            Дескрипторы         Физическая
 регистры              сегментов           память
 
 -----------                               --------------------4Гб
 |   CS    |----                           | ППЗУ (EPROM)     |
 -----------    |                          |------------------|
 -----------    |                          |                  |
 |   SS    |--  |      ----------------    |                  |
 -----------  |  -->   |Доступ|Граница|    |                  |
 -----------   ---->   ----------------    |                  |
 |   DS    |------->   |Базовый адрес |    |                  |
 -----------     -->   ----------------    |                  |
 -----------    |                     |    |------------------|
 |   ES    |----                      |    |Опер.память(DRAM) |
 -----------                           --> -------------------- 0
 
                   Рисунок 5-1  Плоская модель
 
 
 В вершине физического адресного пространства обычно помещается
 ПЗУ, посколько процессор начинает выполнение с адреса
 0FFFFFFF0H. Оперативная память находится в нижней части
 адресного пространства, поскольку начальный базовый адрес
 сегмента данных DS после инициализации сброса системы
 устанавливается в 0.
 
 Для плоской модели каждый дескриптор имеет базовый адрес, равный
 0, и границу сегмента 4 гигабайта. Установкой границы сегмента в
 значение 4 гигабайта механизм сегментации предотвращает
 генерацию исключений для ссылок к памяти, выходящих за границу
 сегмента. Исключения могут тем не менее генерироваться
 механизмами подкачки страниц или защиты сегментации, но и они
 могут быть исключены из модели памяти.
 
 5.1.2  Защищенная плоская модель
 -----------------------------------------------------------------
 
 Защищенная плоская модель аналогична плоской модели, за
 исключением того, что границы сегментов устанавливаются равными
 таким диапазонам адресов, которым соответствует фактически
 существующая оперативная память. Общее исключение защиты
 генерируется при любой попытке доступа к несуществующей памяти.
 Эта модель может использоваться в системах, где запрещен
 механизм подкачки страниц, поскольку она обеспечивает
 минимальный уровень аппаратной защиты от некоторых типов
 программных ошибок.
 
 В этой модели аппаратное обеспечение сегментации предотвращает
 обращение программ к несуществующим адресам памяти. Последствия
 в случае разрешенного доступа к таким адресам памяти зависят от
 аппаратного обеспечения. Например, если процессор не получил
 сигнала READY# (сигнала квитирования и завершения цикла шины),
 то цикл шины не получит завершения, и произойдет остановка
 выполнения программы.
 
 Хотя никакие программы не должны делать попытки доступа к таким
 адресам памяти, такие попытки все же могут иметь место
 вследствие программных ошибок. Без аппаратного контроля адресов
 такие ошибки могут иметь следствием внезапную остановку работы
 программы. В случае же аппаратного контроля программный сбой
 такого рода обрабатывается установленным образом. Может быть
 выдано диагностическое сообщение и сделана попытка запустить
 восстановительную процедуру.
 
 Пример защищенной плоской модели показан на Рисунке 5-2. Здесь
 дескрипторы сегментов устанавливаются таким образом, чтобы
 отражать только физически существующие диапазоны памяти. Сегмент
 кода и сегмент данных размещаются в физической памяти типа EPROM
 (ППЗУ) и DRAM (оперативная память). Граница кодового сегмента
 может быть опционально установлена таким образом, чтобы был
 разрешен доступ к области DRAM. Граница сегмента данных должна
 быть установлена равной сумме размеров EPROM и DRAM. При
 использовании ввода/вывода, управляемого памятью, допустима
 адресация сегмента данных за концом области оперативной памяти.
 
 
 Сегментные     Дескрипторы        Физическая    Логические
 регистры       сегментов          память        смещения
 
 ------        ----------------    -------- 4Гб  --------
 | CS |------> |Доступ|Граница|    |EPROM |      |      |
 ------        ------------------->|------|      |------|
 ------        |Базовый адрес |  / |      |      |Память|
 | ES |----    ---------------- |  |------|      | I/O  |
 ------    |                    |  |Память|      |------|
 ------    |                    |  | I/O  |      |      |
 | SS |--  |   ----------------/   |------|      | DRAM |
 ------  |  -> |Доступ|Граница|    |      |      |      |
 ------   ---> ----------------    |      |      |------|
 | DS |------> |Базовый адрес |    |DRAM  |      |EPROM |
 ------        ----------------    --------  0   --------
 
              Рисунок 5-2. Защищенная плоская модель
 
 
 5.1.3  Многосегментная модель
 -----------------------------------------------------------------
 
 Наиболее сложной является многосегментная модель. В данном
 случае используются все средства, предоставляемые механизмом
 сегментации. Каждой программе дается собственная таблица
 дескрипторов сегментов и свои собственные сегменты. Эти сегменты
 могут либо поступать в исключительное распоряжение программы.
 либо могут разделяться другими конкретными программами. Доступ
 между программами и конкретными сегментами может управляться
 индивидуально.
 
 Для немедленного использования могут быть готовы до шести
 сегментов. Существуют сегменты, для которых селекторы сегмента
 загружены в сегментные регистры. Доступ к остальным сегментам
 выполняется при помощи загрузки соответствующих селекторов
 сегмента в сегментные регистры (см. Рисунок 5-3).
 
 Каждый сегмент представляет собой отдельное адресное
 пространство. Хотя они и могут располагаться в смежных блоках
 физической памяти, механизм сегментации предотвращает доступ к
 содержимому одного сегментом посредством выхода за границу
 другого сегмента при чтении. Попытка адресации памяти за концом
 сегмента ведет к генерации исключения общей защиты.
 
 Механизм сегментации принудительно устанавливает адресный
 диапазон, заданный в дескрипторе сегмента. Ответственность за
 распределение каждому сегменту отдельного адресного диапазона
 лежит на операционной системе. Могут существовать ситуации,
 когда желательно иметь сегменты, разделяющие один и тот же
 адресный диапазон. Например, система может иметь и код, и
 данные, хранимые в ПЗУ. При доступе в ПЗУ для выборки команд
 должен быть использован дескриптор кодового сегмента. При
 доступе в ПЗУ для выборки оттуда данных должен быть использован
 дескриптор сегмента данных.
 
 Сегментные        Дескрипторы                       Физическая
 регистры          сегментов                         память
 
 ----------        ----------------                  -------------
 |   CS   |------> |Доступ|Граница|                  |           |
 ----------        ------------------------          |           |
                   |Базовый адрес |        |         |           |
                   ----------------        |         |           |
                                           |         |           |
 ----------        ----------------        |         |           |
 |   SS   |------> |Доступ|Граница|        |         |           |
 ----------        --------------------------------- |           |
                   |Базовый адрес |        |        \|           |
                   ----------------        |         |-----------|
                                           |         |           |
 ----------        ----------------        |         |           |
 |   DS   |------> |Доступ|Граница|         \        |           |
 ----------        -----------------------   \       |           |
                   |Базовый адрес |        \  \      |           |
                   ----------------         \  \     |           |
                                             \  \    |           |
 ----------        ----------------           \  \   |           |
 |   ES   |------> |Доступ|Граница|            \  \  |           |
 ----------        --------------------------   \  \ |           |
                   |Базовый адрес |          |   \  \|           |
                   ----------------          |    \  |-----------|
                                             |     \ |           |
 ----------        ----------------          |      \|           |
 |   FS   |------> |Доступ|Граница|          |       |-----------|
 ----------        ------------------------------    |           |
                   |Базовый адрес |          |   \   |           |
                   ----------------          |    \  |           |
                                             |     \ |           |
 ----------        ----------------          |      \|           |
 |   GS   |------> |Доступ|Граница|          |       |-----------|
 ----------        ---------------------     |       |           |
                   |Базовый адрес |     \     \      |           |
                   ----------------      \     \     |           |
                                          \     \    |           |
                   ----------------        \     \   |           |
                   |Доступ|Граница|         \     \  |           |
                   --------------------      \     \ |           |
                   |Базовый адрес |   |       \     \|           |
                   ----------------   |        \     |-----------|
                                      |         \    |           |
                   ----------------   |    ------\---|-----------|
                   |Доступ|Граница|   |   |       \  |           |
                   ------------------------        \ |           |
                   |Базовый адрес |   |             \|           |
                   ----------------   --------       |-----------|
                                              \      |           |
                   ----------------        ----------|-----------|
                   |Доступ|Граница|       |     \    |           |
                   ------------------------      \   |           |
                   |Базовый адрес |               \  |           |
                   ----------------                \ |           |
                                                    \|           |
                   ----------------                  |-----------|
                   |Доступ|Граница|                  |           |
                   --------------------------------  |           |
                   |Базовый адрес |                 \|           |
                   ----------------                  -------------
 
               Рисунок 5-3.  Многосегментная модель
 
 
 5.2  Преобразование сегмента
 -----------------------------------------------------------------
 
 Логический адрес состоит из 16-битового селектора сегмента и 32-
 битового смещения в этом сегменте. Логический адрес
 транслируется в линейный адрес сложением смещения и базового
 адреса сегмента. Базовый адрес берется из дескриптора сегмента -
 структуры данных в памяти, которая содержит информацию о размере
 и расположении данного сегмента в памяти, а также информацию для
 управления доступа. Дескриптор сегмента берется в одной из двух
 таблиц, таблицы глобальных дескрипторов (GDT) или таблицы
 локальных дескрипторов (LDT). Для всех программ в системе
 существует единая таблица GDT, а также по одной таблице LDT для
 каждой отдельной выполняемой в текущий момент программы. Если
 позволяет операционная система, то разные программы могут
 разделять одну и ту же LDT. Система может быть организована
 вообще без таблиц LDT; в этом случае все программы будут
 использовать GDT.
 
 Каждый логический адрес связан со своим сегментом (даже если
 система отображает все сегменты в одно и том же линейное
 адресное пространство). Хотя программа может иметь тысячи
 сегментов, для немедленного использования доступны только шесть
 из них. Имеется шесть сегментов, селекторы которых загружены в
 процессор. Селектор сегмента содержит информацию, используемую
 для транслирования логического адреса в соответствующий линейный
 адрес.
 
 Для каждого вида ссылки к памяти (пространству кода,
 пространству стека и пространствам данных) в процессоре
 существуют отдельные сегментные регистры. Они содержат селекторы
 текущих используемых сементов. Доступ к другим сегментам требует
 загрузки сегментного регистра с помощью разновидности команды
 MOV. Одновременно может быть доступно до четырех сегментов
 данных, что в сумме с остальными составляет шесть сегментных
 регистров.
 
 При загрузке селектора сегмента также происходит загрузка в
 сегментный регистр базового адреса, границы сегмента и
 информации, управляющей доступом. После этого процессор уже не
 обращается к таблицам дескрипторов до тех пор, пока не
 произойдет загрузка другого селектора сегмента. Информация,
 хранимая процессором, позволяет ему выполнять адресные
 транслирования, не тратя на это лишних циклов шины. В системах,
 где несколько процессоров имеют доступ к одним и тем же таблицам
 дескрипторов, ответственность за перезагрузку сегментных
 регистров при модификации таблиц дескрипторов лежит на
 программном обеспечении системы. Если этого не сделать, то может
 произойти использование старого дескриптора сегмента,
 кешированного в сегментный регистр, уже после модификации его
 резидентной в памяти версии.
 
 Селектор сегмента содержит 13-разрядный индекс для одной из
 дескрипторных таблиц. Индекс умножается на восемь (число байтов
 в дескрипторе сегмента) и складывается с 32-битовым базовым
 адресом дескрипторной таблицы. Базовый адрес берется из регистра
 таблицы глобальных дескрипторов (GDTR), либо из регистра таблицы
 локальных дескрипторов (LDTR). Эти регистры содержат линейный
 адрес начала дескрипторных таблиц. Бит в селекторе сегмента
 определяет, какая таблица должна быть использована, как показано
 на Рисунке 5-4.
 
 
  Селектор сегмента          Таблица                Таблица
                           глобальных              локальных
 --------------------     дескрипторов            дескрипторов
 |          |T|     |
 |          |I|     |
 --------------------
             |                  TI=0                   TI=1
              -------------------------------------------
                                  |                      |
                                 \/                     \/
                          -----------------      -----------------
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                          |---------------|      |---------------|
                          |       |       |      |       |       |
                          |---------------|      |---------------|
                          |               |      |               |
                 -------> -----------------  --> -----------------
                |                            |
                |                            |
                |                            |
                |  -------------             |    -------------
                |  | Селектор  |             |    | Селектор  |
                |  -------------             |    -------------
                |  | Граница   |             |    |  Граница  |
            --------------------         ----------------------
            |  Базовый  адрес  | GDTR    |  Базовый  адрес    | LDTR
            --------------------         ----------------------
 
      Рисунок 5-4. Бит TI выбирает таблицу дескрипторов
 
 
 Преобразованный адрес представляет собой линейный адрес, как
 показано на Рисунке 5-5. Если подкачка страниц не используется,
 то он одновременно является и физическим адресом. Если подкачка
 используется, то физический адрес получается на втором уровне
 преобразования адреса. Трансляция адресов описана в разделе 5.3.
 
 
             15                0    31                           0
 Логический  --------------------   ------------------------------
 адрес       |    Селектор      |   |        Смещение            |
             --------------------   ------------------------------
                  |         |                     |
           -------          \/                    |
           |       Таблица                        |
           |    дескрипторов                      |
           |   --------------                     |
           |   |            |                     |
           |   |            |                     |
           |   |------------|                     |
           |   | Дескриптор | Базовый   -----     |
            -->|  сегмента  |---------->| + |<----
               |------------| адрес     -----
               |            |             |
               --------------             |
                             31           \/          0
                            ---------------------------
                  Линейный  |Каталог|Страница|Смещение|
                  адрес     ---------------------------
 
             Рисунок 5-5. Трансляция адреса сегмента
 
 
 5.2.1  Сегментные регистры
 -----------------------------------------------------------------
 
 Каждый вид ссылок к памяти связан с соответствующим сегментным
 регистром. Ссылки к коду, данным и стеку выполняются посредством
 доступа к содержимому соответствующих сегментных регистров. Во
 время выполнения программы возможен доступ и к другим сегментам,
 для чего требуется загрузить селекторы нужных сегментов в
 сегментные регистры.
 
 Каждый сегментный регистр имеет "видимую" и "невидимую" часть,
 как показано на Рисупке 5-6. Для загрузки видимой части
 сегментных регистров используются разновидности команды MOV,
 невидимая часть загружается самим процессором.
 
 
      Видимая часть         Невидимая часть
      ------------------------------------------------
      |  Селектор   |  Базовый адрес, граница и т.д. | CS
      |----------------------------------------------|
      |                                              | SS
      |----------------------------------------------|
      |                                              | DS
      |----------------------------------------------|
      |                                              | ES
      |----------------------------------------------|
      |                                              | FS
      |----------------------------------------------|
      |                                              | GS
      ------------------------------------------------
 
      Рисунок 5-6. Сегментные регистры
 
 
 
 Для загрузки этих регистров используются команды прикладных
 программ, описанные в Главе 3. Имеется два типа таких команд:
 
 1. Команды прямой загрузки, такие как MOV, POP, LDS, LSS, LSG и
    LFS. Эти команды обращаются к сегментным регистрам явно.
 
 2. Неявные команды загрузки, такие как версии команд CALL и JMP
    для дальних указателей. Эти команды изменяют содержимое
    регистра CS в процессе их выполнения.
 
 При использовании этих команд, в видимую часть сегментного
 регистра загружаются селектор сегмента. Базовый адрес, границу,
 тип и прочую информацию процессор извлекает из дескрипторной
 таблицы автоматически и помещает их в невидимую часть
 сегментного регистра.
 
 Поскольку большинство команд ссылается на сегменты, селекторы
 которых уже загружены в сегментные регистры, процессор может
 прибавлять смещения логического адреса к базовому адресу
 сегмента без потерь быстродействия.
 
 
 5.2.2  Селекторы сегмента
 -----------------------------------------------------------------
 
 Селектор сегмента указывает на информацию, определяющую сегмент,
 которая называется дескриптором сегмента. В программе может
 использоваться больше шести сегментов, селекторы которых
 занимают сегментные регистры. В таком случае программа
 использует разновидности команды MOV для изменения содержимого
 этих регистров всякий раз, когда ей требуется доступ к новому
 сегменту.
 
 Селектор сегмента идентифицирует дескриптор сегмента, задавая
 таблицу дескрипторов и позицию нужного дескриптора в этой
 таблице. Селекторы сегмента видны прикладной программе в
 качестве части переменной типа указателя, однако обычно значения
 селекторов назначаются или модифицируются редакторами связей или
 компонующими загрузчиками, но не прикладными программами. Формат
 селектора сегмента показан на Рисунке 5-7.
 
 Индекс: выбирает один из 8192 дескрипторов в таблице
 дескрипторов. Процессор умножает значение индекса на 8 (число
 байтов в дескрипторе сегмента) и складывает результат с базовым
 адресом таблицы дескрипторов (берется из регистра GDTR или
 LDTR).
 
 Бит-индикатор таблицы (TI): задает используемую таблицу
 дескрипторов. Если этот бит очищен, то выбирается таблица GDT;
 если же он установлен, то выбирается текущая таблица LDT.
 
 Запрошенный уровень привилегированности (RPL):если это поле
 содержит уровень привилегированности с большим значением, чем
 программа (т.е. привилегированность меньше), то оно
 переопределяет уровень привилегированности программы. Если
 программа использует менее привилегированный селектор сегмента,
 доступ к памяти происходит с меньшим уровнем
 привилегированности. Это свойство используется для защиты от
 нарушения безопасности данных, если менее привилегированная
 программа пытается использовать более привилегированную
 программу для доступа к защищенным данным.
 
 
      15                         3  2  1 0
      -------------------------------------
      |                            |T|    |
      |       Индекс               |I|RPL |
      |                            | |    |
      -------------------------------------
 
      Индикатор таблицы (TI) (0=GDT, 1=LDT)
      Запрошенный уровень привилегированности (RPL)
      (00=наибольшая привилегированность, 11=наименьшая)
 
                  Рисунок 5-7. Селектор сегмента
 
 Например, системные утилиты или драйверы устройств должны
 выполняться с самым высоким уровнем привилегированности с тем,
 чтобы иметь возможность доступа к защищенным системным
 средствам, таким как управляющие регистры или интерфейс с
 периферийными устройствами. Однако, они не должны
 взаимодействовать с другими защищенными средствами, даже при
 получении такого запроса от менее привилегированных программ.
 Если программа запросила прочесть с диска сектор в область
 память, занятый более привилегированной программой, например
 операционной системой, то RPL может быть использован для
 генерации исключения общей защиты, если использованный селектор
 сегмента имеет более низкий уровень привилегированности. Данное
 исключение возникает даже тогда, когда программа, использующая
 данный селектор сегмента, имеет достаточно выский уровень
 привилегированности для выполнения такой операции.
 
 Поскольку первый элемент таблицы GDT процессором не
 используется, селектор, содержащий индекс со значением 0 и
 индикатор таблицы 0 (т.е. селектор, указывающий на первый
 элемент GDT), используется в качестве "пустого селектора".
 Процессор не генерирует исключения, когда сегментный регистр (не
 являющийся регистром CS или SS) загружается пустым селектором.
 Однако, исключение генерируется, если сегментный регистр,
 содержащий пустой селектор, используется для доступа к памяти.
 Это средство может быть использовано для инициализации
 неиспользуемых сегментных регистров.
 
 5.2.3  Дескрипторы сегментов
 -----------------------------------------------------------------
 
 Дескриптор сегмента представляет собой структуру данных в
 памяти, которая сообщает процессору размер и расположение в
 памяти сегмента, а также управляющую информацию и информацию о
 состоянии сегмента. Дескрипторы обычно создаются компиляторами,
 компоновщиками, загрузчиками или операционной системой, но не
 прикладными программами. На Рисунке 5-8 показаны два общих
 формата дескриптора. Дескриптор системного сегмента более
 подробно рассматривается в Главе 6. Все типы дескрипторов
 системы имеют один из этих форматов.
 
 База: Определяет расположение сегмента в пределах 4 гигабайтного
 физического адресного пространства. Процессор располагает вместе
 три поля базового адреса, которые образуют одно 32-битовое
 значение. Значения базы сегмента должны быть выравнены по
 кратным 16 байтам адресам памяти, что позволяет программам
 максимизировать их быстродействие, выравнивая в свою очередь по
 кратным 16 байтам адресам памяти код/данные.
 
 Бит грануляции: Включает масштабирование поля Границы масштабным
 коэффициентом 4096(2**12). Если этот бит очищен, то граница
 сегмента интерпретируется в блоках по 4Кб (т.е. в страницах).
 Отметим, что двенадцать наименее значащих битов адреса в случае,
 если используется масштабирование, не тестируются. Например,
 граница 0 при установленном бите грануляции дает допустимые
 смещения от 0 до 4095. Отметим также, что этот коэффициент
 действует только на значение поля Границы. Базовый адрес
 остается гранулированным по байтам.
 
 Дескрипторы, используемые для сегментов кода и данных
 прикладных программ:
 
                2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 31             4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ---------------------------------------------------------------
 |               | | | |A|      | | D | |      |               |
 | BASE  31:24   |G|D|0|V|      |P| P |S| TYPE |   BASE 23:16  |
 |               | | | |L|      | | L | |      |               |
 |-------------------------------------------------------------|
 |      Базовый адрес 15:00     |    Граница сегмента 15:00    |
 ---------------------------------------------------------------
 
 Дескрипторы, используемые для специальных системных сегментов:
 
                2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 31             4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ---------------------------------------------------------------
 |               | | | |A|      | | D | |      |               |
 | BASE  31:24   |G|D|0|V|      |P| P |S| TYPE |   BASE 23:16  |
 |               | | | |L|      | | L | |      |               |
 |-------------------------------------------------------------|
 |      Базовый адрес 15:00     |    Граница сегмента 15:00    |
 ---------------------------------------------------------------
 
 AVL       Доступно для использования системным программным
           обеспечением
 BASE      Базовый адрес сегмента
 DPL       Уровень привилегированности дескриптора
 S         Тип дескриптора
           (0=системный; 1=прикладной)
 G         Грануляция
 Граница   Граница сегмента
 P         Присутствие сегмента
 TYPE      Тип сегмента
 D         Размер операции по умолчанию
           (Распознается только в дескрипторах кодового сегмента:
            0=16-битовый размер; 1=32-битовый размер)
 
                Рисунок 5-8  Дескрипторы сегмента
 
 Граница: Определяет размер сегмента. Процессор помещает рядом
 два поля границы сегмента, в совокупности образующих одно
 20-разрядное значение. Процессор интерпретирует границу одним из
 двух слудующих способов, в зависимости от установки бита
 грануляции:
 
 1. Если бит грануляции очищен, то граница может принимать
    значения от 1 байта до 1 мегабайта, с приращениями в один
    байт.
 
 2. Если бит грануляции установлен, то граница может принимать
    значения от 4 Килобайт до 4 Гигабайт, с приращениями в 4 Кб.
 
 Для большинства сегментов логический адрес может иметь значение
 смещения в диапазоне от 0 до значения границы. Прочие значения
 ведут к генерации исключений. Сегменты с расширением вниз
 изменяют смысл поля граница на противоположный: они позволяют
 адресацию любыми значениями смещения, кроме значений от 0 до
 значения границы (см. описание поля Типа, приводимое ниже). Это
 позволяет создавать сегменты, для которых увеличение значения
 поля Границы приводит к распределению новой памяти в нижней
 части адресного пространства, вместо верхней. Сегменты с
 расширением вниз предназначены для хранения стеков, но
 использовать их не обязательно. Если стек должен быть помещен в
 сегмент, который не будет изменять свой размер, то таким
 сегментом может быть обычный сегмент данных.
 
 Бит S: Определяет, является ли этот сегмент системным сегментом,
 или же сегментом кода или данных. Если бит S установлен, то
 сегмент является либо кодовым сегментом, либо сегментом данных.
 Если этот бит очищен, то сегмент является системным сегментом.
 
      Бит D:  Указывает длину операндов и  исполнительных  адресов
 сегмента по умолчанию.  Если бит D установлен,  то предполагается
 режим 32-разрядных операндов и 32-разрядных исполнительных  адресов.
 Если этот бит очищен то предполагается использование 16-разрядных
 операндов и адресов.
 
 Тип: Интерпретация этого поля зависит от того, относится ли
 данный дескриптор к прикладному, или же к системному сегменту.
 Системные сегменты имеют несколько иной формат дескриптора,
 рассматриваемый в Главе 6. Поле Типа дескриптора памяти задает
 тип доступа, разрешенного к данному сегменту, а также
 направление, в котором этот сегмент растет (см. Таблицу 5-1).
 
             Таблица 5-1. Типы прикладных сегментов
 
 -----------------------------------------------------------------
 Число | E | W | A |    Тип    |             Описание
       |   |   |   |дескриптора|
 -----------------------------------------------------------------
    0    0   0   0    Данные    Только чтение
    1    0   0   1    Данные    Только чтение, выполнен доступ
    2    0   1   0    Данные    Чтение/запись
    3    0   1   1    Данные    Чтение/запись, выполнен доступ
    4    1   0   0    Данные    Только чтение, расширение вниз
    5    1   0   1    Данные    Только чтение, расширение вниз,
                                выполнен доступ
    6    1   1   0    Данные    Чтение/запись, расширение вниз
    7    1   1   1    Данные    Чтение/запись, расширение вниз,
                                выполнен доступ
 -----------------------------------------------------------------
 Число | C | R | A |    Тип    |             Описание
       |   |   |   |дескриптора|
 -----------------------------------------------------------------
    8    0   0   0    Код       Только выполнение
    9    0   0   1    Код       Только выполнение, выполнен доступ
   10    0   1   0    Код       Выполнение/чтение
   11    0   1   1    Код       Ваполнение/чтение, выполнен доступ
   12    1   0   0    Код       Только выполнение, конформный
   13    1   0   1    Код       Только выполнение, конформный,
                                выполнен доступ
   14    1   1   0    Код       Выполнение/только чтение, конформный
   15    1   1   1    Код       Выполнение/только чтение, конформный,
                                выполнен доступ
 -----------------------------------------------------------------
 
 Для сегментов данных три младших бита поля типа можно
 интерпретировать как признаки расширения вниз (E), разрешения
 записи (W) и того, что к сегменту был выполнен доступ (A). Для
 кодовых сегментов три младших бита поля типа можно
 интерпретировать как признак конформности (C), разрешения чтения
 (R) и выполненного доступа (A).
 
 Сегменты данных могут быть предназначены только для чтения или
 для чтения/записи. Загрузка регистра SS селектором сегмента для
 любого другого типа сегмента генерирует исключение общей защиты.
 Если стековому сегменту требуется иметь возможность изменять
 размер, то ему может быть назначен сегмент данных с типом
 расширения вниз. Для сегмента с расширением вниз смысл поля
 Границы меняется на противоположный. Если для других типов
 сегмента допустимыми являются значения смещения в диапазоне от 0
 до значения границы (вне этого диапазона генерируется исключение
 общей защиты), то для сегмента с расширением вниз значения в
 этом диапазоне, напротив, ведут к генерации исключения.
 Допустимыми смещениями для сегментов с расширением вниз являются
 те, что для сегментов других типов вызывают особую ситуацию.
 Сегменты с расширением вверх должны адресоваться смещениями,
 меньшими или равными границе сегмента. Смещения же в сегменты с
 расширением вниз всегда должны превышать значение границы
 сегмента. Такая интерпретация границы сегмента вызывает
 распределение области памяти в нижней части сегмента, когда
 граница сегмента увеличивается, что является правильным для
 стековых сегментов, поскольку они растут в направлении младшего
 адреса. Если стек помещается в сегменте, который не меняет
 своего размера, то этот сегмент не обязан быть сегментом с
 расширением вниз.
 
 Кодовые сегменты могут быть предназначены только для выполнения,
 либо для выполнения/чтения. Сегмент с типом "выполнение/чтение"
 может быть использован, например, когда в команды кода в ПЗУ
 помещены константы. В данном случае константы могут быть
 прочитаны либо при помощи команды, имеющей префикс
 переопределения сегмента CS, либо при помощи помещения селектора
 данного кодового сегмента в сегментный регистр для сегмента
 данных.
 
 Кодовые сегменты могут быть либо конформными, либо
 не-конформными. Переход выполнения в более привилегированный
 конформный сегмент сохранит текущий уровень привилегированности.
 Переход выполнения в не-конформный сегмент с другим уровнем
 привилегированности приведет к генерации исключения общей
 защиты, если не использован шлюз задачи (обсуждение средств
 мультизадачности см. в Главе 6). Системные утилиты, не
 обращающиеся к средствам защиты, такие как функции
 транслирования данных (например, перекодировка EBCDIC/ASCII,
 кодирование / декодирование по методу Хафмана, библиотека
 математических функций), а также некоторые типы исключений
 (например, ошибка деления на ноль, переполнение, обнаруженное
 при помощи INTO или превышение диапазона BOUND) могут быть
 загружены в конформные кодовые сегменты.
 
 Поле Типа также сообщает о том, был ли к данному сегменту
 выполнен доступ. В исходном состоянии дескрипторы сегментов
 сообщают о том, что доступ к сегменту был. Если поле Типа затем
 установить в значение, означающее, что доступ к сегменту не был
 выполнен, процессор восстановит значение, если доступ к сегменту
 произошел. Очистив и проверив младший бит поля Типа, программное
 обеспечение может контролировать использование сегмента (младший
 бит поля Типа также называется битом Доступа).
 
 Например, система разработки программ может очистить все биты
 Доступа для сегментов прикладной программы. При сбое в
 прикладной программе состояния этих битов могут быть
 использованы для генерации карты всех сегментов, к которым
 выполнила доступ данная прикладная программа. В отличие от
 контрольных точек, которые обеспечиваются механизмом отладки
 (см. Главу 11), информация, предоставляемая этим полем,
 относится не к физическим адресам, а к сегментам.
 
 Процессор может обновлять поле Типа при доступе к сегменту, даже
 если доступ этот произошел в цикле чтения. Если таблицы
 дескрипторов были помещены в ПЗУ, аппаратному обеспечению может
 потребоваться запретить связь ПЗУ с шиной данных во время цикла
 записи. Также может потребоваться возвратить сигнал READY#
 процессору в цикле записи в ПЗУ; в противном случае не
 произойдет завершение этого цикла. Эти средства аппаратной
 конструкции необходимы для использования ПЗУ-резидентных таблиц
 дескрипторов с процессором 386 DX, который всегда устанавливает
 бит Доступа при загрузке дескриптора сегмента. Однако, процессор
 i486 только в том случае, если он еще не установлен. Избежать
 попытки записи в таблицы дескрипторов в ПЗУ можно, установив
 биты Доступа в каждом дескрипторе.
 
 DPL (Уровень привилегированности дескриптора): Определяет
 уровень привилегированности сегмента. Используется для
 управления доступом к сегменту при помощи механизма защиты,
 описанного в Главе 6.
 
 Бит присутствия сегмента: Если этот бит очищен, то процессор при
 загрузке в сегментный регистр селектора данного дескриптора
 генерирует исключение "сегмент не присутствует". Это свойство
 используется для обнаружения попыток доступа к сегментам,
 которые стали недоступными. Сегмент может стать недоступным,
 когда системе понадобилось создать свободную память. Для
 элементов памяти, таких как символьные шрифты или драйверы
 устройств, в тех случаях, когда они в текущий момент не
 используются, выполняется отмена распределения памяти. Отмена
 распределения памяти такому элементу выполняется маркировкой
 такого сегмента как "не присутствующего" (это выполняется при
 помощи очистки бита присутствия сегмента). После этого память,
 занимаемая данным сегментом, может быть распределена для другого
 использования. Когда элемент, для которого было отменено
 распределение памяти, понадобится в следующий раз, исключение
 "сегмент не присутствует" укажет на то, что необходимо снова
 загрузить этот сегмент в память. Если такого рода организация
 памяти выполняется способом, не видимым для прикладных программ,
 то она называется "виртуальной памятью". Система может работать
 с общим размером виртуальной памяти, значительно превышающим
 физическую память, благодаря тому, что одновременно в физической
 памяти присутствует только несколько сегментов.
 
 На Рисунке 5-9 показан формат дескриптора, когда бит присутствия
 сегмента очищен. В этом случае операционная система имеет право
 использовать адреса памяти, отмеченные как Доступная, для
 хранения там своих собственных данных, например, информации об
 отсутствующих сегментах.
 
 
                           1 1 1 1 1 1 1
      31                   6 5 4 3 2 1 0 9 8 7          0
      ---------------------------------------------------
      |                     | | D |D|       |           |
      |   Доступная         |0| P |T|  Тип  | Доступная | +4
      |                     | | L | |       |           |
      ---------------------------------------------------
      |                    Доступная                    | +0
      ---------------------------------------------------
 
    Рисунок 5-9. Дескриптор сегмента (Сегмент не присутствует)
 
 5.2.4  Таблицы дескрипторов сегментов
 -----------------------------------------------------------------
 
 Таблица дескрипторов сегментов представляет собой массив
 дескрипторов сегментов. Существуют два типа таблиц дескрипторов:
 
      - Таблица глобальных дескрипторов (GDT)
      - Таблицы локальных дескрипторов (LDT)
 
 Существует единственная для всех задач таблица GDT, а для каждой
 выполняемой задачи, кроме того, существует по одной таблице LDT.
 Таблица дескрипторов представляет собой массив сегментных
 дескрипторов, показанный на Рисунке 5-10. Таблица дескрипторов
 имеет переменную длину и может содержать до 8192 (2**13)
 дескрипторов. Первый дескриптор в таблице GDT процессором не
 используется. Селектор сегмента для данного "пустого
 дескриптора" при загрузке его в сегментный регистр не генерирует
 есключения, однако исключение генерируется всякий раз при
 попытке доступа к памяти с использованием такого дескриптора.
 Инициализация сегментных регистров таким селектором сегмента
 гарантирует генерацию исключения при ошибочных ссылках на
 неиспользуемые сегментные регистры.
 
 
               Таблица                Таблица
             глобальных              локальных
            дескрипторов            дескрипторов
 
            -----------------      -----------------
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+38   |               |+38
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+30   |               |+30
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+28   |               |+28
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+20   |               |+20
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+18   |               |+18
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+10   |               |+10
            |---------------|      |---------------|
            |       |       |      |       |       |
            |---------------|      |---------------|
            |               |+8    |               |+8
            |---------------|      |---------------|
            |Первый         |      |       |       |
            |дескриптор в   |      |---------------|
            |GDT            |      |               |
            |не используется|+0    |               |+0
            -----------------<---  -----------------<--------
                                |                           |
            Регистр             |  Регистр  -------------   |
            GDTR                |  LDTR     | Селектор  |   |
                -------------   |           -------------   |
                | Граница   |   |           |  Граница  |   |
         --------------------   |  ----------------------   |
         |  Базовый  адрес  |----  |  Базовый  адрес    |---
         --------------------      ----------------------
 
      Примечание:  Адреса даны в шестнадцатиричном формате.
 
                Рисунок 5-10. Таблицы дескрипторов
 
 
 5.2.5  Базовые регистры таблиц дескрипторов
 -----------------------------------------------------------------
 
 Процессор выполняет поиск таблицы глобальных дескрипторов (GDT)
 и таблицы дескрипторов прерываний (IDT) через регистры GDTR и
 IDTR, соответственно. Эти регистры содержат 32-битовые базовые
 адреса таблиц в линейном адресном пространстве. Они также
 содержат 16-битовые значения граничного размера этих таблиц. При
 загрузке или сохранении этих регистровв памяти происходит доступ
 к 48-битовому "псевдо-дескриптору", как показано на Рисунке
 5-11. Для максимизации быстродействия за счет заполнения строки
 кеша GDT и IDT должны быть выравнены по границе адреса, кратного
 16 байтам.
 
 Граничное значение выражается в байтах. Как и для сегментов, оно
 складывается с базовым адресом для получения адреса последнего
 допустимого байта. В случае значения границы 0 имеется всего
 один допустимый байт. Поскольку дескрипторы сегментов всегда
 имеют размер восемь байтов, то граница всегда должна быть на
 единицу меньше целочисленного произведения восьми, (т.е. 8N-1).
 Команды LGDT и SGDT читают и записывают регистр GDTR; команды
 LIDT и SIDT читают и записывают регистр IDTR.
 
 Третья таблица дескрипторов - это локальная таблица (LDT). Она
 идентифицируется при помощи 16-битового селектора сегмента,
 хранимого в регистре LDTR. Команды LLDT и SLDT читают и
 записывают селектор сегмента в регистр LDTR. Регистр LDTR также
 содержит базовый адрес и границу для LDT, но эти значения
 загружаются процессором автоматически из дескриптора сегмента
 для LDT. Для максимизации быстродействия за счет заполнения
 строки кеша LDT должна быть выравнена по границе адреса,
 кратного 16 байтам.
 
 При попытке сохранения псевдо-дескриптора в режиме пользователя
 (уровень привилегированности 3) может быть сгенерирована ошибка
 контроля выравнивания. Обычно программы в режиме пользователя не
 выполняют сохранение псевдо-дескрипторов, но возможности
 генерации такой ошибки можно избежать, поместив
 псевдо-дескриптор в адрес нечетного слова (т.е. адрес 2 MOD 4).
 Это заставит процессор сохранить выравненное слово, за которым
 следует выравненное двойное слово.
 
      47                      16 15               0
      ----------------------------------------------
      |     Базовый адрес       |    Граница       |
      ----------------------------------------------
      5                        2 1                0
 
      Порядок следования байтов показан внизу
 
             Рисунок 5-11. Формат псевдо-дескриптора
 
 5.3  Трансляция страниц
 -----------------------------------------------------------------
 
 Линейный адрес представляет собой 32-битовый адрес в однородном,
 несегментированном адресном пространстве. Это адресное
 пространство может являться большим физическим адресным
 пространством (т.е. адресным пространством, состоящим из 4
 гигабайт оперативной памяти), либо может использоваться средство
 подкачки страниц, моделирующее это адресное пространство при
 помощи небольшой области оперативной памяти и некоторого
 количесства дисковой памяти. При использовании подкачки страниц
 линейный адрес транслируется в соответствующий физический адрес,
 либо генерируется исключение. Это исключение дает операционной
 системе возможность прочитать страницу с диска (возможно,
 вытеснив на диск другую страницу), а затем перезапустить
 команду, вызвавшую данное исключение.
 
 Механизм подкачки отличается от механизма сегментации тем, что в
 данном случае используются небольшие, имеющие фиксированный
 размер страницы. В отличие от сегментов, которые обычно имеют
 размер, равный размеру содержащихся в них структур данных,
 страницы процессора i486 всегда имеют размер 4К. Если
 сегментация является единственной используемой формой трансляции
 адреса, структура данных, находящаяся в физической памяти, будет
 иметь в памяти все свои компоненты одновременно. При
 использовании механизма подкачки страниц структура данных может
 частично находиться в оперативной памяти, и частично в дисковой
 памяти.
 
 Информация, обеспечивающая отображение линейных адресов в
 физические адреса и отвечающая за генерацию исключений в случае
 несоответствий, хранится в структурах данных оперативной памяти,
 которые называются таблицами страниц. Как и в случае
 сегментации, эта информация кешируется в регистрах процессора с
 тем, чтобы минимизировать число циклов шины, требуемое для
 трансляции адреса. В отличие от механизма сегментации, эти
 регистры процессора полностью невидимы для прикладных программ.
 (Для целей тестирования эти регистры видны программам,
 выполняемым с максимальным уровнем привилегированности:
 подробности см. в Главе 10).
 
 Мехпнизм подкачки страниц рассматривает 32-разрядный линейный
 адрес как состоящий из трех частей, а именно двух 10-разрядных
 индексов страничных таблиц и 12-заррядное смещение в таблице,
 адресуемой страничными таблицами. Поскольку как виртуальные
 страницы в линейном адресном пространстве, так и физические
 страницы памяти выравнены по 4Кбайтной границе страниц,
 модифицировать младшие 12 битов адреса нет необходимости. Эти 12
 битов напрямую передаются аппаратному обеспечению, работающему с
 подкачкой страниц, независимо от того, разрешена ли подкачка в
 текущий момент, или запрещена. Отметим, что в этом состоит
 отличие от сегментации, поскольку сегменты могут начинаться с
 любого адреса байта.
 
 Старшие 20 битов адреса используется для индексации страничных
 таблиц. Если все страницы линейного адресного пространства
 отображались бы в одной таблице страниц в оперативной памяти, то
 для этого потребовалось бы 4Мб памяти. Делается это не так. Для
 экономии памяти используются страничные таблицы двух уровней.
 Страничная таблица верхнего уровня называется страничным
 каталогом. В нем отображаются старшие 10 битов линейного адреса
 табличных страниц второго уровня. Во втором уровне страничных
 таблиц отображаются средние 10 битов линейного адреса, задающего
 базовый адрес страницы в физической памяти (который называется
 адресом страничного блока).
 
 На базе содержимого таблицы страниц или каталога страниц может
 генерироваться исключение. Оно дает операционной системе
 возможность подкачать отсутствующую таблицу страниц с диска.
 Благодаря тому, что страничные таблицы второго уровня могут
 находиться на диске, механизм подкачки страниц может
 поддерживать отображение всего линейного адресного пространства
 при помощи всего нескольких страниц памяти.
 
 Регистр CR3 содержит адрес страничного блока каталога страниц.
 Поэтому он называется базовым регистром каталога страниц, или
 PDBR. Старшие 10 битов линейного адреса умножаются на масштабный
 коэффициент четыре (число байтов каждого элемента таблицы
 страниц) и складывается со значением регистра PDBR для получения
 физического адреса элемента в каталоге страниц. Поскольку адрес
 страничного блока всегда имеет незаполненными младшие 12 бит, то
 такое сложение выполняется методом конкатенации (замещения
 младших 12 битов масштабированным индексом).
 
 При доступе к элементу каталога страниц выполняется несколько
 проверок: исключения могут генерироваться, если страница
 защищена или отсутствует в памяти. Если особая ситуация не
 генерировалась, то старшие 20 битов элемента таблицы страниц
 используются в качестве адреса страничного блока таблицы страниц
 второго уровня. Средние 10 битов линейного адреса масштабируются
 коэффициентом четыре (снова это число равно размеру элемента
 таблицы страниц) и конкатенируются с адресом страничного блока
 для получения физического адреса элемента в таблице страниц
 второго уровня.
 
 И опять, выполняются проверки доступа, в результате которых
 возможна генерация исключений. Если же исключений не возникло,
 то старшие 20 битов элемента таблицы страниц второго уровня
 конкатенируются с младшими 12 битами линейного адреса, образуя
 физический адрес операнда (данных) в оперативной памяти.
 
 Хотя такой процесс и может показаться сложным, затраты
 процессорного сремени на него невелики. Процессор имеет кеш
 элементов таблицы страниц, который называется ассоциативным
 буфером трансляции адреса (TBL). TBL удовлетворяет большинство
 запросов чтения страничных таблиц. дополнительные циклы шины
 затрачиваются только при доступе к новым страницам памяти.
 Размер страницы (4К) достаточно велик, поэтому по сравнению с
 числом циклов шины, затрачиваемых на выполнение команд и
 обращение к данным, число циклов для доступа к таблицам страниц
 относительно невелико. Одновременно с этим размер страницы
 достаточно мал, чтобы память использовалась наиболее эффективно.
 (Независимо от фактической величины структуры данных, она
 занимает не меньше одной страницы памяти).
 
 5.3.1  Бит разрешения подкачки страниц PG
 -----------------------------------------------------------------
 
 Если подкачка страниц разрешена, используется второй этап
 трансляции адреса, генерирующий физический адрес из линейного.
 Если подкачка страниц запрещена, то линейный адрес совпадает и
 используется как физический адрес.
 
 Подкачка страниц разрешена, если установлен бит 31 (бит PG)
 регистра CR0. Этот бит обычно устанавливается операционной
 системой во время программной инициализации. Бит PG должен быть
 установлен, если в операционной системе должно выполняться более
 одной программы в виртуальном режиме 8086, либо при
 использовании виртуальной памяти с подкачкой страниц по
 требованию.
 
 5.3.2  Линейный адрес
 -----------------------------------------------------------------
 
 Формат линейного адреса показан на Рисунке 5-12.
 
 
          31             22 21         12 11           0
         -----------------------------------------------
         |    Каталог     |   Таблица   |   Смещение   |
         -----------------------------------------------
 
              Рисунок 5-12. Формат линейного адреса
 
 
                                                        Страничный
      -----------------------------------------------      блок
      |    Каталог     |   Таблица   |   Смещение   |  -----------
      -----------------------------------------------  |         |
            |               |               |          |         |
            |               |               |          | Операнд |
   ---------                |                --------->|         |
  |     Каталог страниц     |    Таблица страниц       |         |
  |     -----------------   |    ------------------    -----------
  |     |               |   |    |                |
  |     |---------------|   |    |----------------|
  ----->|Элемент таблицы|   ---->|Элемент каталога|
        |     страниц   |---     |     страниц    |
        |---------------|  |     |----------------|
        |               |  |     |                |
        |               |  |     |                |
        -----------------  |     ------------------
                ^          |              ^
                |          |              |
      -------   |          ----------------
 CR3  |     |---
      -------
 
           Рисунок 5-13. Трансляция страничного адреса
 
 На Рисунке 5-13 показано, каким образом процессор транслирует
 поля линейного адреса Каталога, Таблицы и Смещения в физический
 адрес с использованием двух уровней страничных таблиц. Механизм
 подкачки страниц использует поле Каталога в качестве индекса
 каталога страниц, поле Таблицы в качестве индекса таблицы
 страниц, определяемой в каталоге страниц, и поле Смещение для
 адресации операнда в странице, заданной в таблице страниц.
 
 5.3.3 Таблицы страниц
 -----------------------------------------------------------------
 
 Таблица страниц представляет собой массив, состоящий из
 32-разрядных элементов. Таблица страниц сама является страницей
 и содержит 4096 байтов памяти, или максимум 1Кб 32-разрядных
 элементов. Все страницы, включая каталоги страниц и таблицы
 страниц, выровнены по границе 4Кб.
 
 Для адресации страницы памяти используется два уровня таблиц.
 Старший уровень называется каталогом страниц. Он адресует до 1К
 страничных таблиц второго уровня. Таблица страниц второго уровня
 адресует до 1К страниц в физической памяти. Таким образом, все
 таблицы, адресуемые одним каталогом страниц, могут адресовать до
 1М или 2**20 страниц. Поскольку каждая страница содержит 4К, или
 2**12 байтов, таблицы одного каталога страниц покрывают все
 линейное адресное пространство процессора i486 (2**20 x 2**12 =
 2 **32).
 
 Физический адрес текущего страничного каталога хранится в
 регистре CR3, который также называется базовым регистром
 каталога страниц (PDBR). Программное обеспечение организации
 памяти имеет опции использования одного каталога страниц для
 всех задач, одного каталога страниц для каждой задачи, либо
 некоторой комбинации этих двух опций. В Главе 10 приводится
 информация об инициализации регистра CR3. О том, как содержимое
 CR3 может изменяться для каждой задачи, см. в Главе 7.
 
 5.3.4  Элементы таблицы страниц
 -----------------------------------------------------------------
 
 Элементы страничных таблиц обоих уровней имеют одинаковый
 формат. Этот формат показан на Рисунке 5-14.
 
 5.3.4.1  Адрес страничного блока
 -----------------------------------------------------------------
 
 Адрес страничного блока является базовым адресом страницы. В
 элементе страничной таблицы старшие 20 битов используются для
 задания адреса страничного блока, а младшие 12 битов задают
 управляющие биты и биты состояния для данной страницы. В
 каталоге страниц адрес страничного блока представляет собой
 адрес таблицы страниц второго уровня. В таблице страниц второго
 уровня адрес страничного блока - это адрес страницы, которая
 содержит команды или данные.
 
 5.3.4.2  Бит присутствия
 -----------------------------------------------------------------
 
 Бит Присутствия указывает на то, отображается ли адрес
 страничного блока из таблицы страниц страницей в физической
 памяти. Если данный бит установлен, то страница находится в
 памяти.
 
 Если бит Присутствия очищен, то страница не находится в памяти,
 и остальная часть данного элемента таблицы страниц доступна для
 использования операционной системой, например, для хранения
 информации о том, где находится эта отсутствующая страница. На
 Рисунке 5-15 показан формат элемента таблицы страниц, когда бит
 Присутствия очищен.
 
 
      31                           12 11                    0
     ---------------------------------------------------------
     |                               |     |   | | |P|P|U|R| |
     |Адрес страничного блока 31..12 |AVAIL|0 0|D|A|C|W|/|/|P|
     |                               |     |   | | |D|T|S|W| |
     ---------------------------------------------------------
 
     P        - Присутствие
     R/W      - Чтение/З пись
     U/S      - Пользователь/Супервизор
     PWT      - Запись Страницы прозрачна
     PCD      - Кеширование на уровне страниц запрещено
     A        - Доступ произошел
     D        - "Грязная"
     AVAIL    - Доступны для использования системным программистом
 
     Примечание: 0 означает резервирование Intel. Не выполняйте
                 определение этих битов.
 
          Рисунок 5-14. Формат элемента таблицы страниц
 
 
      31                                1 0
      --------------------------------------
      |        Доступны                  |0|
      --------------------------------------
 
          Рисунок 5-15.  Формат элемента таблицы страниц
                  для не-Присутствующей таблицы
 
 Если бит Присутствия на любом уровне таблицы страниц очищен,
 когда делается попытка использовать данный элемент таблицы для
 адресной трансляции, то происходит такая последовательность
 событий:
 
      1. Операционная система копирует страницу с дисковой памяти
         в физическую память.
 
      2. Операционная система загружает адрес страничного блока в
         элемент таблицы страниц и устанавливает бит Присутствия.
         Прочие биты, например, бит Чтения/Записи, также могут
         при этом быть установлены.
 
      3. Поскольку в буфере ассоциативной трансляции (TLB) все
         еще может находиться копия старого элемента таблицы
         страниц, то операционная система очищает этот буфер.
         Буфер TLB и способы его очистки рассматриваются в
         разделе 5.3.5.
 
      4. Выполняется рестарт программы, вызвавшей исключение.
 
 Поскольку CR3 не имеет бита Присутствия, который указывал бы на
 те случаи, когда каталог страниц не находится в оперативной
 памяти, каталог страниц, на который указывает CR3, должен
 находиться в физической памяти всегда.
 
 5.3.4.3  Биты Доступа и "Грязная"
 -----------------------------------------------------------------
 
 Эти биты содержат данные об использовании страницы на обоих
 уровнях страничных таблиц. Бит Доступа используется для
 сообщения о доступе на чтение или запись к странице или
 страничной таблице второго уровня. Бит "Грязная" сообщает о
 доступе к странице для записи.
 
 За исключением бита "грязная" в элементах каталога страниц, эти
 биты устанавливаются аппаратным обеспечением; однако процессор
 не очищает ни один из этих битов. Процессор устанавливает биты
 Доступа на обоих уровнях страничных таблиц до операции чтения
 или записи страницы. Процессор устанавливает бит "Грязная" в
 таблице страниц второго уровня, прежде чем выполнить операцию
 записи по адресу, отображаемому данным элементом таблицы. Бит
 "Грязная" в элементах каталога страниц не определен.
 
 Операционная система может использовать бит Доступа, когда ей
 требуется создать некоторую свободную область памяти, посылая
 страницу или таблицу страниц второго уровня на диск.
 Периодически очищая биты Доступа в страничных таблицах, она
 может определять, какие страницы были использованы последними.
 Не используемые страницы являются кандидатами на пересылку в
 дисковую память.
 
 Операционная система может использовать бит "Грязная", когда
 страница посылается обратно на диск. Очищая бит "Грязная" при
 пересылке страницы в оперативную память, операционная система
 может определить, произошел ли какой-либо доступ записи к этой
 странице. Если имеется копия этой страницы на диске и копия в
 оперативной памяти не была изменена операциями записи, то
 обновлять соответствующую копию на диске из оперативной памяти
 нет необходимости.
 
 О том, как процессор i486 обновляет биты Доступа и "Грязная" в
 многопроцессорных системах, написано в Главе 13.
 
 5.3.4.4  Биты Чтения/Записи и Пользователя/Супервизора
 -----------------------------------------------------------------
 
 Биты Чтения/Записи и Пользователя/Супервизора используются для
 защитных проверок страниц, выполняемых процессором одновременно
 с трансляцией адреса. Более подробную информацию о защите см. в
 Главе 6.
 
 5.3.4.5  Биты управления кешем страничного уровня
 -----------------------------------------------------------------
 
 Биты PCD и PWT используются для организации кеша страничного
 уровня. Программное обеспечение может при помощи этих битов
 управлять кешированием отдельных страниц или страничных таблиц
 второго уровня. Более подробную информацию о кешировании см. в
 Главе 12.
 
 5.3.5  Ассоциативный буфер трансляции
 -----------------------------------------------------------------
 
 Процессор хранит использованные последними элементы страничных
 таблиц во входящем в состав микросхемы кеше, который называется
 буфером ассоциативной трансляции, или TLB. Большая часть
 подкачки страниц выполняется на базе содержимого TLB. Циклы шины
 для обращения к страничным таблицам затрачиваются только при
 использовании новых страниц.
 
 TLB невидим для прикладных программ, но видим для операционной
 системы. Системные программисты должны очищать TLB (освобождая
 его содержимое от элементов страничных таблиц) при изменении
 элементов страничных таблиц. Если этого не сделать, то старые
 данные, не получившие изменений, могут быть ошибочно
 использованы для адресной трансляции. Изменение элемента для
 страницы, которая не находится в оперативной памяти, не требует
 очистки TLB, поскольку элементы для отсутствующих в памяти
 страниц не кешируются.
 
 TLB очищается при загрузке регистра CR3. Регистр CR3 может быть
 загружен одним из следующих способов:
 
      1. Явной загрузкой при помощи команды MOV, например
 
         MOV CR3,EAX
 
      2. Неявной загрузкой при помощи переключателя задач, который
         изменяет содержимое регистра CR3. (Более подробную
         информацию о переключении задач см. в Главе 7).
 
 Неверный элемент в TBL может быть очищен при помощи команды
 INVLPG. Эта команда бывает полезна при изменении образа
 конкретной страницы.
 
 5.4  Объединение сегментной и страничной трансляции
 -----------------------------------------------------------------
 
 На Рисунке 5-16 показано объединение Рисунков 5-5 и 5-13,
 которое суммирует оба этапа трансляции от логического адреса к
 физическому, когда разрешен механизм подкачки страниц. Опции,
 предоставляемые обоими этапами адресной трансляции, могут быть
 использованы для поддержки различных стилей организации памяти.
 
 5.4.1  Плоская модель
 -----------------------------------------------------------------
 
 Когда процессор i486 используется для выполнения программного
 обеспечения, не использующего механизма сегментации, может
 оказаться желательным удаление средств сегментации процессора.
 Процессор i486 не имеет бита режима, который позволял бы
 включать и выключать средства сегментации, но точно такой же
 эффект может быть достигнут и при помощи отображения адресных
 пространств стека, кода и данных в одном и том же диапазоне
 линейных адресов. Используемые командами процессора 32-разрядное
 смещения позволяют покрывать все линейное адресное пространство.
 
 При использовании механизма подкачки страниц сегменты могут
 отображаться во всем линейном адресном пространстве. При
 одновременном выполнении более чем одной программы механизм
 подкачки страниц может быть использован для того, чтобы дать
 отдельное адресное пространство каждой выполняемой программе.
 
 
 
             15                0    31                           0
 Логический  -----------------------------------------------------
 адрес       |    Селектор        |          Смещение            |
             -----------------------------------------------------
                  |         |                     |
           -------          \/                    |
           |       Таблица                        |
           |    дескрипторов                      |
           |   --------------                     |
           |   |            |                     |
           |   |            |                     |
           |   |------------|                     |
           |   | Дескриптор | Базовый   -----     |
            -->|  сегмента  |---------->| + |<----
               |------------| адрес     -----
               |            |             |
               --------------             |
                                          |
                               -----------
                              |
  Линейный                    |
  адрес                       \/                       Страничный
      -----------------------------------------------      блок
      |    Каталог     |   Таблица   |   Смещение   |  -----------
      -----------------------------------------------  |         |
            |               |               |          |         |
            |               |               |          | Операнд |
   ---------                |                --------->|         |
  |     Каталог страниц     |    Таблица страниц       |         |
  |     -----------------   |    ------------------    -----------
  |     |               |   |    |                |
  |     |---------------|   |    |----------------|
  ----->|Элемент таблицы|   ---->|Элемент каталога|
        |     страниц   |---     |     страниц    |
        |---------------|  |     |----------------|
        |               |  |     |                |
        |               |  |     |                |
        -----------------  |     ------------------
                ^          |              ^
                |          |              |
      -------   |          ----------------
 CR3  |     |---
      -------
 
      Рисунок 5-16. Объединенная  сегментная  и  страничная
                        трансляция адреса
 
 5.4.2  Сегменты, занимающие несколько страниц
 -----------------------------------------------------------------
 
 Архитектура процессора допускает существование сегментов,
 превышающих по размеру одну страницу (4К). Например, большие
 структуры данных могут занимать тысячи страниц. Если подкачка
 страниц не используется, то для доступа к любой части структуры
 данных требуется присутствие в физической памяти всей структуры
 данных. При использовании механизма подкачки страниц в памяти
 обязательно присутствие только страницы, содержащей ту часть
 данных, к которой в текущий момент выполняется доступ.
 
 5.4.3  Страницы, содержащие несколько сегментов
 -----------------------------------------------------------------
 
 Сегменты могут также быть по размеру меньше страницы. Если такой
 сегмент будет помещен в отдельную, не содержащую других
 сегментов страницу, это означает бесполезную трату памяти.
 Например, при помещении в отдельную страницу небольшой структуры
 данных, например, занимающего 1 байт семафора, будет
 израсходовано 4К памяти. Если используется много таких
 семафоров, гораздо эффективней будет упаковать их в одну
 страницу.
 
 5.4.4  Невыравненные границы страниц и сегментов
 -----------------------------------------------------------------
 
 Архитектура процессора не устанавливает каких-либо
 принудительных соотношений между границами страниц и сегментов.
 Страница может содержать конец одного сегмента и начало
 следующего. Аналогичным образом, сегмент может содержать конец
 одной страницы и начало следующей.
 
 5.4.5  Выравненные границы страниц и сегментов
 -----------------------------------------------------------------
 
 Программное обеспечение организации памяти может стать проще и
 эффективнее при установке некоторого принудительного
 выравнивания границ страниц и сегментов. Например, если сегмент,
 который может поместиться в пределах одной страницы, размещен в
 двух страницах, то доступ к такому сегменту потребует в два раза
 больше времени на подкачку содержащих его страниц.
 
 5.4.6  Страничная таблица на каждый сегмент
 -----------------------------------------------------------------
 
 Метод объединения механизмов подкачки страниц и сегментации,
 упрощающий программное обеспечение организации памяти,
 заключается в том, чтобы дать каждому сегменту свою страничную
 таблицу, как показано на Рисунке 5-17. Тем самым в каталоге
 страниц каждому сегменту будет соответствовать один элемент
 таблицы, обеспечивая информацию об управлении доступом для
 подкачки страниц, соответствующих данному сегменту.
 
                                                       Страничные
                                                         блоки
                                                      ------------
     LDT         Каталог страниц   Таблицы страниц -->|          |
 -------------    -------------     ------------- |   ------------
 |           |    |           |     |           | |
 |-----------|    |-----------|     |-----------| |
 |           |    |           |     | элемент   |-    ------------
 |-----------|    |-----------|     |-----------|     |          |
 |           |    |           |     | элемент   |---->------------
 |-----------|    |-----------|     |-----------|
 |           |    |           |     | элемент   |-
 |-----------|    |-----------| --->------------- |   ------------
 |Дескриптор |--->|  элемент  |-'                  -->|          |
 |-----------|    |-----------|                       ------------
 |Дескриптор |--->|  элемент  |-
 |-----------|    |-----------| |   -------------
 |           |    |           | |   |           |
 |-----------|    |-----------| |   |-----------|
 |           |    |           | |   |           |     ------------
 |-----------|    |-----------| |   |-----------|     |          |
 |           |    |           | |   |  элемент  |---->------------
 |-----------|    |-----------| |   |-----------|
 |           |    |           | |   |  элемент  |-    ------------
 -------------    -------------  -->------------- |   |          |
     LDT         Каталог страниц   Таблицы страниц -->------------
                                                       Страничные
                                                          блоки
 
       Рисунок 5-17. Каждый сегмент может иметь собственную
                        страничную таблицу
 
 
 
 Глава 6  Защита
 -----------------------------------------------------------------
 
 Защита необходима при работе в мультизадачном режиме. Средства
 защиты могут быть использованы для предотвращения взаимного
 влияния одновременно выполняемых задач. Например, может
 выполняться защита от затирания одной задачей команд и данных
 другой задачи.
 
 При разработке программы механизм защиты поможет получить более
 четкую картину программных ошибок. Когда программа выполняет
 неожиданную ссылку к недопустимой в данный момент области
 памяти, механизм защиты может блокировать данное событие и
 сообщить о нем.
 
 В системах, предназначенных для конечных пользователей механизм
 защиты может предохранять систему от программных сбоев,
 вызываемых невыявленными ошибками в программах. При сбое в
 программе действие его распространится таким образом лишь на
 ограниченный домен памяти. Операционная система при этом может
 быть защищена от нарушений ее областей, что позволяет
 зарегистрировать диагностическое сообщение об ошибке и сделать
 попытку автоматического восстановления программы.
 
 Защита может применяться к сегментам и страницам памяти. Два
 бита регистра процессора определяют уровень привилегированности
 текущей выполняемой программы (этот уровень называется текущим
 уровнем привилегированности, или CPL). Во время трансляции
 адреса для доступа к сегменту или странице выполняется проверка
 CPL.
 
 Хотя для выключения механизма защиты специального управляющего
 регистра или бита режима не предусмотрено, тот же эффект можно
 получить, назначив уровень привилегированности 0 (это старший
 уровень привилегированности) всем селекторам сегментов,
 дескрипторам сегментов и элементам страничной таблицы.
 
 6.1  Защита на уровне сегментов
 -----------------------------------------------------------------
 
 Механизм защиты позволяет ограничить влияние неправильно
 работающей программы на другие выполняемые программы и их
 данные. Защита представляет собой ценное свойство при разработке
 программных продуктов, поскольку она обеспечивает сохранность в
 памяти при любых ситуациях средств разработки программного
 обеспечения (операционной системы, отладчика). При сбое в
 прикладной программе в полной исправности сохраняется
 программное обеспечение, позволяющее выдать диагностические
 сообщения, а отладчик имеет возможность произвести "посмертный"
 анализ содержимого памяти и регистров сбойной программы. В
 системах, эксплуатирующих готовое программное обеспечение,
 защита позволяет повысить его надежность и дает возможность
 инициировать восстановительные процедуры в системе.
 
 Каждая ссылка к памяти контролируется с точки зрения
 удовлетворения защитным проверкам. Все проверки выполняются до
 начала цикла обращения к памяти; любые нарушения защиты
 предотвращают начало цикла доступа к памяти и генерируют
 исключение. Поскольку проверки защиты выполняются параллельно с
 трансляцией адреса, они не влияют на характеристики
 быстродействия системы. Существует пять проверок:
 
      1. Проверка типа
      2. Проверка границы
      3. Ограничение адресуемого домена
      4. Ограничение точек входа в процедуру
      5. Ограничение набора команд
 
 Нарушение защиты ведет к генерации исключения. Механизм
 исключений описан в Главе 9. В данной главе описаны нарушения
 защиты памяти, ведущие к генерации исключений.
 
 6.2  Дескрипторы сегмента и защита
 -----------------------------------------------------------------
 
 На Рисунке 6-1 показаны поля дескриптора сегмента, используемые
 механизмом защиты. Отдельные биты поля Типа именуются по
 выполняемым ими функциям.
 
 Параметры защиты помещаются в дескриптор при его создании. В
 целом, прикладным программистам эти параметры знать не
 требуется.
 
 
                Дескриптор сегмента данных
 
                        2 1 1 1 1 1 1 1 1 1 1
 31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ----------------------------------------------------------------
 |               | | | | |       | | D | | | | | |              |
 | BASE  31:24   | | | | |LIMIT  | | P |1|0|E|W|A|  BASE 23:16  | +4
 |               | | | | |19:16  | | L | | | | | |              |
 |--------------------------------------------------------------|
 |      База сегмента 15:00      |    Граница сегмента 15:00    | +0
 ----------------------------------------------------------------
 
                Дескриптор сегмента кода
 
                        2 1 1 1 1 1 1 1 1 1 1
 31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ----------------------------------------------------------------
 |               | | | | |       | | D | | | | | |              |
 | BASE  31:24   | | | | |LIMIT  | | P |1|1|C|R|A|  BASE 23:16  | +4
 |               | | | | |19:16  | | L | | | | | |              |
 |--------------------------------------------------------------|
 |      База сегмента 15:00      |    Граница сегмента 15:00    | +0
 ----------------------------------------------------------------
 
 
 A         Доступ произошел
 C         Конформный
 DPL       Уровень привилегированности дескриптора
 E         Расширение вниз
 R         Доступный для чтения
 LIMIT     Граница сегмента
 W         Доступный для записи
 
      Рисунок 6-1. Поля дескриптора, используемые для защиты
                          (Часть 1 из 2)
 
 
                Дескриптор системного сегмента
 
                        2 1 1 1 1 1 1 1 1 1 1
 31                     0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ----------------------------------------------------------------
 |               | | | | |       | | D | |       |              |
 | BASE  31:24   | | | | |LIMIT  | | P |0|  Тип  |  BASE 23:16  | +4
 |               | | | | |19:16  | | L | |       |              |
 |--------------------------------------------------------------|
 |      База сегмента 15:00      |    Граница сегмента 15:00    | +0
 ----------------------------------------------------------------
 
 
 DPL       Уровень привилегированности дескриптора
 LIMIT     Граница сегмента
 
      Рисунок 6-2. Поля дескриптора, используемые для защиты
                          (Часть 2 из 2)
 
 Когда программа загружает в сегментный регистр селектор
 сегмента, процессор автоматически загружает туда базовый адрес
 этого сегмента и информацию о его защите. Невидимая часть
 каждого сегментного регистра хранит базовый адрес, границу, тип
 и уровень привилегированности. Благодаря тому, что эта
 информация резидентно находится в сегментном регистре, все
 последующие проверки защиты для этого регистра могут быть
 выполнены без дополнительных затрат времени на ее поиск.
 
 6.2.1  Проверка типа
 -----------------------------------------------------------------
 
 Помимо дескрипторов для сегментов кода и данных прикладной
 программы, процессор i486 имеет дескрипторы для системных
 сегментов и шлюзов. Это структуры данных, используемые для
 организации выполнения задач (Глава 7), также исключений и
 прерываний (Глава 9). В Таблице 6-1 перечислены все типы,
 определенные для системных сегментов и шлюзов. Отметим, что не
 все дескрипторы определяют сегменты: дескрипторы шлюзов содержат
 точки входа в процедуры.
 
 Поля Типа дескрипторов сегментов кода и данных включают в себя
 биты, более подробно определяющие назначение сегмента (см.
 Рисунок 6-1):
 
 - Бит "Доступный для записи" в дескрипторе сегмента данных
   управляет возможностью выполнения записи из программ в данный
   сегмент.
 
 - Бит "Доступный для чтения" дескриптора выполняемого сегмента
   задает возможность выполнения чтения программами из данного
   сегмента (например для доступа к константам, записанным
   непосредственно в область кода). Доступный для чтения
   выполняемый сегмент может быть прочитан двумя способами:
 
      1. С помощью регистра CS, используя префикс переопределения
         сегмента CS.
      2. С помощью загрузки селектора для данного дескриптора в
         регистр сегмента данных (DS, ES, FS или GS).
 
          Таблица 6-1. Типы системных сегментов и шлюзов
 
 -----------------------------------------------------------------
      Тип                             Описание
 -----------------------------------------------------------------
       0         Резервируется
       1         Доступный сегмент состояния задачи (TSS) 80286
       2         LDT
       3         Занятый сегмент состояния задачи (TSS) 80286
       4         Шлюз вызова
       5         Шлюз задачи
       6         Шлюз прерываний 80286
       7         Шлюз ловушек 80286
       8         Резервируется
       9         Доступный TSS ЦПУ i486
      10         Резервируется
      11         Занятый TSS ЦПУ i486
      12         Шлюз вызова ЦПУ i486
      13         Резервируется
      14         Шлюз прерываний ЦПУ i486
      15         Шлюз задачи ЦПУ i486
 -----------------------------------------------------------------
 
 Проверка типа может использоваться для определения программных
 ошибок, состоящих в попытке использования сегментов способом, не
 подразумевавшимся программистом. Процессор рассматривает
 информацию о типе в двух возможных случаях:
 
      1. Когда селектор для дескриптора загружается в сегментный
         регистр. Конкретные сегментные регистры могут содержать
         только конкретные типы дескрипторов; например:
 
         - Регистр CS может быть загружен только селектором
           выполняемого сегмента.
 
         - Селекторы выполняемых сегментов, не являющиеся
           "Доступными для чтения", не могут быть загружены в
           регистры сегментов данных.
 
         - В регистр SS могут быть загружены только селекторы
           сегментов данных, "Доступных для записи".
 
      2. Конкретные сегменты могут использоваться командами
         только конкретными, предопределенными способами;
         например:
 
         - Никакая команда не может выполнять запись в
           выполняемый сегмент.
 
         - Никакая команда не может выполнять запись в сегмент
           данных, если для него не установлен бит "Доступен для
           записи".
 
         - Никакая команда не может выполнять чтение
           выполняемого сегмента, если для него не установлен бит
           "Доступен для чтения".
 
 6.2.2  Проверка границы
 -----------------------------------------------------------------
 
 Поле Границы дескриптора сегмента не дает программам выполнить
 адресацию вне сегмента. Действующее значение границы зависит от
 установки бита G (бит грануляции). Для сегментов данных граница
 также зависит от бита E (бит направления расширения сегмента). В
 качестве бита E назначается один из битов поля Типа при ссылках
 к дескрипторам сегментов данных.
 
      Когда бит G очищен, граница сегмента равна значению
 20-разрядного поля Границы дескриптора. В этом случае граница
 может изменяться в диапазоне от 0 до 0FFFFFH (2**20-1, или 1
 мегабайт). Если бит G установлен, то процессор умножает значение
 поля Границы на масштабный коэффициент 2**12. В этом случае
 граница будет изменяться в диапазоне от 0FFFH (2**12-1, или 4K),
 до 0FFFFFFFFH (2**32-1, или 4 гигабайта).Отметим, что при
 использовании такого масштабирования, проверка границы для
 младших 12 битов адреса не выполняется; когда бит G установлен,
 а граница сегмента равна 0, допустимые значения смещения в
 сегменте лежат в диапазоне от 0 до 4095.
 
 Для всех типов сегментов, за исключением сегментов, расширяемых
 вниз (т.е. стековых сегментов), значение границы на единицу
 меньше размера сегмента в байтах. Процессор генерирует
 исключение общей защиты в любом из следующих случаев:
 
      - Попытка доступа к байту памяти по адресу, превышающему
        границу сегмента.
      - Попытка доступа к слову памяти по адресу, превышающему
        границу сегмента - 1.
      - Попытка доступа к двойному слову памяти по адресу,
        превышающему границу сегмента - 3.
 
      Для сегментов, расширяющихся вниз, граница служит для той
 же функции проверки, но интерпретируется иначе. В этом случае
 диапазон допустимых значений адреса определяется от (граница+1)
 до 2** 32-1. Сегмент с расширением вниз имеет максимальный
 размер при значении границы, равном 0.
 
 Контроль границы позволяет отлавливать такие программные ошибки,
 как неверно вычисленные индексы массивов и недопустимые
 указатели. Эти ошибки определяются сразу же, как только они
 произошли, поэтому идентификация вызвавшей их причины
 существенно упрощается. Без такого контроля границ указанные
 ошибки могут иметь следствием разрушение важных областей памяти
 в других модулях, а их существование невозможно обнаружить, пока
 не произойдет сбой в испорченном таким образом модуле, а такое
 событие может наступить намного позже, чем фактическая вызвавшая
 его ошибка. Защита позволяет блокировать такие ошибки и сообщить
 об их источнике.
 
      В дополнение к проверке границ сегментов существует также
 проверка границ таблиц дескрипторов. Регистры GDTR и IDTR
 содержат 16-разрядное значение границы. Оно используется
 процессором для защиты программ от выбора дескриптора сегмента
 из области, лежащей вне данной таблицы. Граница таблицы
 дескрипторов идентифицирует последний допустимый байт этой
 таблицы. Поскольку каждый дескриптор имеет длину восемь байтов,
 таблица, содержащая до N дескрипторов, должна иметь значение
 Границы, равное 8N-1.
 
 Дескриптору может быть задано нулевое значение. Это относится к
 первому дескриптору в таблице GDT, который не используется. Хотя
 этот дескриптор может быть загружен в сегментный регистр, любая
 попытка ссылки к памяти при помощи этого дескриптора приведет к
 генерации исключения общей защиты.
 
 6.2.3  Уровни привилегированности
 -----------------------------------------------------------------
 
      Механизм защиты распознает четыре уровня привилегированности,
 нумеруемые от 0 до 3. Чем больше номер, тем ниже уровень
 привилегированности. При удовлетворении всех прочих проверок
 защиты исключение общей защиты генерируется при попытке
 программы доступа к сегменту с меньшим уровнем
 привилегированности (т.е. с большим числом, задающим уровень),
 чем имеет данный сегмент.
 
 Хотя для отмены механизма защиты никакого управляющего регистра
 или бита режима не предусмотрено, того же эффекта можно
 достигнуть путем присвоения всем уровням привилегированности
 значения 0. (Бит PE регистра CR0 не является разрешающим битом
 собственно для механизма защиты; он используется для включения
 "защищенного режима", режима выполнения программы, в котором
 доступной является вся 32-разрядная архитектура процессора в
 целом. Если защищенный режим выключен, то процессор работает в
 режиме "реальных адресов", который просто реализует возможности
 обладающего более высоким быстродействием и улучшенного
 процессора 8086).
 
 Уровни привилегированности могут использоваться для повышения
 надежности операционной системы. В случае присвоения
 операционной системе наивысшего уровня привилегированности она
 становится защищенной от сбоев в случае ошибок в других
 программах. При таких программных сбоях операционная система
 имеет возможность сгенерировать соответствующие диагностические
 сообщения и попытаться выполнить восстановительные процедуры.
 
 Следующий уровень привилегированности может быть установлен для
 других частей программного обеспечения, таких как программы,
 управляющие периферийными устройствами, которые называются
 драйверами устройств. При сбое в драйвере устройства
 операционная система должна иметь возможность выдать
 диагностическое сообщение, поэтому имеет смысл защитить
 операционную систему от возможных сбоев драйверов устройств.
 Однако, драйвер устройства может работать с важным периферийным
 оборудованием, например с дисководом. Сбои прикладных программ
 не должны приводить к разрушению структуры директорий на диске,
 поэтому имеет смысл защищать драйверы устройств от сбоев
 прикладных программ. Драйверы устройств должны иметь уровень
 привилегированности промежуточный, между операционной системой и
 прикладными программами. Прикладным программам присваивается
 самый низкий уровень привилегированности.
 
 На Рисунке 6-2 показано, как эти уровни привилегированности
 могут быть интерпретированы в качестве колец защиты. Центральное
 кольцо защиты содержит сегменты, в которых находится наиболее
 важное программное оеспечение, обычно ядро операционной системы.
 Прочие кольца используются для менее важного программного
 обеспечения.
 
 Уровни привилегированности хранятся в следующих структурах
 данных:
 
      - Два младших бита сегментного регистра CS содержат текущий
        уровень привилегированности (CPL). Это уровень
        привилегированности выполняемой в текущий момент
        программы. Младшие два бита регистра SS также содержат
        копию CPL. Обычно CPL равен уровню привилегированности
        кодового сегмента, из которого происходит выборка команд
        программы. CPL изменяется при передаче управления
        кодовуму сегменту с другим уровнем привилегированности.
 
      - Дескрипторы сегмента содержат поле, которое называется
        уровнем привилегированности дескриптора (DPL). DPL
        представляет собой уровень привилегированности
        применительно к сегменту.
 
      - Селекторы сегмента содержат поле, которое называется
        запрошенным уровнем привилегированности (RPL) RPL
        представляет собой уровень привилегированности процедуры,
        создавшей данный селектор. Если RPL имеет меньший уровень
        привилегированности, чем CPL, то он замещает CPL. Когда
        более привилегированная программа принимает селектор
        сегмента из менее привилегированной программы, RPL
        вызывает доступ к памяти с меньшим уровнем
        привилегированности.
 
 Уровни привилегированности проверяются, когда селектор
 дескриптора загружается в сегментный регистр. Проверки,
 используемые для доступа к данным, отличаются от проверок при
 передаче выполнения между выполняемыми сегментами;
 следовательно, существует два типа доступа, рассматриваемые в
 следующих разделах в отдельности.
 
 
                        Кольца  защиты
                              **
                          *        *
                              **
                     *    *        *    *
                              **
                   *   *   *      *   *    *
 
 Ядро           *   *   *     * *     *   *   *
 операционной -----------> *      *
 системы       *   *   *  *Уровень 0*  *  *  *
                           *      *
                *   *   *     * *     *  *   *
 Вспомогательные --------> Уровень 1
 средства                 *         *
 операционной      *   *       **       *   *
 системы (драйверы ------> Уровень 2
 устройств и т.д.)   *    *         *     *
                               **
 Прикладные программы----> Уровень 3
                          *         *
                               **
 
                    Рисунок 6-2. Кольца защиты
 
 6.3  Ограничения доступа к данным
 -----------------------------------------------------------------
 
 Для адресации операнда в памяти селектор сегмента данных должен
 быть загружен в регистр сегмента данных (регистры DS, ES, FS, GS
 или SS). Процессор проверяет уровни привилегированности
 сегментов. Проверка выполняется при загрузке селектора сегмента.
 Как показано на Рисунке 6-3, в проверке привилегированности
 этого типа участвуют три различных уровня привилегированности.
 
 Три проверяемых уровня привилегированности:
 
 1. CPL (текущий уровень привилегированности программы). Он
    хранится в двух младших битах регистра CS.
 2. DPL (уровень привилегированности дескриптора) дескриптора
    сегмента, содержащего операнд.
 3. RPL (уровень привилегированности источника запроса) из
    селектора, используемого для задания сегмента, содержащего
    операнд. Этот уровень хранится в двух младших битах
    сегментного регистра, используемого для доступа к операнду
    (регистра SS, DS, ES, FS или GS). Если операнд находится в
    стековом сегменте, то RPL и CPL совпадают.
 
                Дескриптор сегмента, содержащего операнд
 
                                    1 1
 31                                 4 3           7            0
 ----------------------------------------------------------------
 |               | | | | |       | | D | | | | | |              |
 |               | | | | |       | | P | | | | | |              | +4
 |               | | | | |       | | L | | | | | |              |
 |--------------------------------------------------------------|
 |                               |   |__________________        | +0
 -------------------------------------------------------|--------
                                                        |
                 Текущий кодовый сегментный регистр     |
                                                        |
 --------------------                                   |
 |            | CPL |------------------------------     |
 --------------------                              |    |
                 Селектор сегмента, содержащего    |    |
 --------------------               операнд        |    |
 |            | RPL |-------------------------     |    |
 --------------------                         |    |    |
                                              |    |    |
                                              \/   \/   \/
                                          ---------------------
                                          |      Проверка     |
                                          |привилегированности|
                                          ---------------------
 CPL       Текущий уровень привилегированности
 DPL       Уровень привилегированности дескриптора
 RPL       Запрошенный уровень привилегированности
 
  Рисунок 6-3. Проверка привилегированности при доступе к данным
 
 Команды могут загружать сегментный регистр только если DPL
 сегмента имеет такой же или меньший уровень привилегированности
 (больший номер привилегированности), чем у наименее
 привилегированного CPL и RPL селектора.
 
 Адресуемый домен задачи изменяется при изменении его CPL. Если
 CPL равен 0, то сегменты данных всех уровней привилегированности
 доступны; когда CPL равен 1, то доступны только сегменты данных
 с уровнями привилегированности от 1 до 3; а когда CPL равен 3,
 то доступны только сегменты данных с уровнем привилегированности
 3.
 
 Доступ к данным в кодовых сегментах
 -----------------------------------------------------------------
 
 Может оказаться желательным хранить данные в кодовом сегменте;
 например, когда и код, и данные хранятся в ПЗУ. Кодовые сегменты
 вполне допускают хранение там констант, однако выполнять запись
 в сегмент, определенный в качестве кодового сегмента,
 недопустимо, если в том же адресном пространстве не отображен
 сегмент данных. Возможны следующие способы доступа к данным в
 кодовом сегменте:
 
 1. Загрузка в регистр сегмента данных селектора неконформного,
    доступного для чтения выполняемого сегмента.
 
 2. Загрузка в регистр сегмента данных селектора комформного,
    доступного для чтения выполняемого сегмента.
 
 3. Использование префикса переопределения сегмента для чтения из
    доступного для чтения выполняемого сегмента, селектор
    которого уже загружен в регистр CS.
 
 Для случая 1 применимы те же правила доступа, что и для сегмента
 данных. Случай 2 допустим всегда, поскольку уровень
 привилегированности кодового сегмента с установленным битом
 Конформности такой же, как и CPL, независимо от его DPL. Случай
 3 также допустим всегда, поскольку DPL кодового сегмента,
 выбранного при помощи регистра CS, совпадает с CPL.
 
 6.4  Ограничения передачи управления
 -----------------------------------------------------------------
 
 В процессоре i486 передача управления выполняется командами JMP,
 CALL, RET, INT и IRET, а также механизмами исключений и
 прерываний. Исключения и прерывания - это особые случаи и они
 рассматриваются в Главе 9. В данной же главе обсуждаются только
 команды JMP, CALL и RET.
 
 "Ближние" формы команд JMP, CALL и RET передают управление в
 пределах содержащего их кодового сегмента, и следовательно,
 подлежат только проверки границы перехода. Процессор проверяет,
 чтобы адрес назначения команд JMP, CALL и RET не выходил за
 границу текущего сегмента кода. Граница кешируется в регистре
 CS, поэтому проверка границы для ближних переходов не требует
 дополнительных затрат времени.
 
 Операнды "дальних" форм команд JMP и CALL ссылаются на другие
 сегменты, поэтому процессор выполняет проверку
 привилегированности. Существует два способа ссылки из команд JMP
 или CALL на другие сегменты:
 
 1. Операнд выбирает дескриптор другого выполняемого сегмента.
 
 2. Операнд выбирает дескриптор шлюза вызова. Такая форма
    передачи управления с использованием шлюзования
    рассматривается в Главе 7.
 
 Как показано на Рисунке 6-4, два различных уровня
 привилегированности вызывают проверку привилегированности
 передачи управления без использования шлюза вызова:
 
 1. CPL (текущий уровень привилегированности).
 
 2. DPL дескриптора кодового сегмента назначения перехода.
 
 Обычно CPL равен DPL сегмента, выполняемого процессором в
 текущий момент. CPL может быть, однако, больше (т.е. менее
 привилегированным), чем DPL, если текущий кодовый сегмент
 является конформным сегментом (конформность указывается в поле
 Типа сегментного дескриптора). Конформный сегмент выполняется на
 уровне привилегированности вызывающей процедуры. Процессор все
 время кеширует CPL в регистре CS; это значение может быть
 отличным от значения DPL в сегментном дескрипторе текущего
 кодового сегмента.
 
 
 
                Дескриптор кодового сегмента назначения перехода
 
                                  1 1 1 1 1 1
 31                               5 4 3 2 1 0 9 8 7            0
 ----------------------------------------------------------------
 |               | | | | |       | | D |  Тип    |              |
 |               | | | | |       | | P | | | | | |              | +4
 |               | | | | |       | | L |1|1|C|R|A|              |
 |--------------------------------------------------------------|
 |                               |   |      |___________        |
 |                               |   |_____________     |       | +0
 --------------------------------------------------|----|--------
                                                   |    |
             Текущий кодовый сегментный регистр    |    |
                                                   |    |
 --------------------                              |    |
 |            | CPL |--------------------------    |    |
 --------------------                         |    |    |
                                              |    |    |
                                              \/   \/   \/
                                          ---------------------
                                          |      Проверка     |
                                          |привилегированности|
                                          ---------------------
 C         Бит конформности
 CPL       Текущий уровень привилегированности
 DPL       Уровень привилегированности дескриптора
 
      Рисунок 6-4. Проверка привилегированности при передаче
                    управления без шлюзования
 
 Процессор разрешает передачу управления командами JMP или CALL
 напрямую в другой сегмент только в том случае, если выполняются
 следующие правила привилегированности:
 
 - DPL сегмента равен текущему CPL.
 
 - Сегмент является конформным кодовым сегментом, и его DPL
   меньше (привилегированность выше), чем текущий CPL.
 
 Конформные сегменты используются для таких программ, как
 библиотеки математических функций или некоторые виды
 обработчиков прерываний, которые поддерживают прикладные
 программы, но не требуют доступа к защищенным системным
 средствам. При передаче управления конформному сегменту CPL не
 изменяется, даже если селектор, использованный для адресации
 сегмента, имеет другой RPL. Это единственное условие, когда CPL
 может быть отличным от DPL текущего кодового сегмента.
 
 Большинство кодовых сегментов является не-конформными. Для таких
 сегментов управление может передаваться без шлюзования только к
 другим кодовым сегментам, имеющим тот же уровень
 привилегированности. Однако, иногда бывает необходимо передавать
 управление сегментам с высшими уровнями привилегированности. Это
 выполняется при помощи команды CALL, использующей дескрипторы
 шлюза вызова, которые рассматриваются в Главе 7. Команда JMP
 никогда не может передавать управление не-конформным сегментам,
 DPL которых не равен CPL.
 
 6.5  Шлюзовые дескрипторы
 -----------------------------------------------------------------
 
 Для обеспечения защиты при передаче управления между
 выполняемыми сегментами с разными уровнями привилегированности
 процессор i486 использует шлюзовые дескрипторы. Существует
 четыре типа шлюзовых дескрипторов:
 
 - Шлюзы вызова
 
 - Шлюзы ловушки
 
 - Шлюзы прерываний
 
 - Шлюзы задач
 
 Шлюзы задач используются для переключения задач и описываются в
 Главе 7. В Главе 9 объясняется, как шлюзы ловушек и прерываний
 используются для обработки исключений и прерываний. В данной
 главе рассматриваются только шлюзы вызова. Шлюзы вызовов
 представляют собой некоторую форму защищенной передачи
 управления. Они используются для передачи управления между
 различными уровнями привилегированности. Их использование
 необходимо только в системах, где имеется более одного уровня
 привилегированности. На Рисунок 6-5 показан формат шлюза вызова.
 
 Шлюз вызова имеет две основные функции:
 
 1. Определение точки входа в процедуру.
 
 2. Задание уровня привилегированности, требуемого для входа в
    процедуру.
 
 
                    32-битовый шлюз вызова
 
 31                          6 5 4 3 2 1 0 9 8 7 6 5 4 3       3
 ----------------------------------------------------------------
 |                            | | D | | | | | | | | | |Счетчик  |
 | Смещение в сегменте  31:16 |P| P |0|1|1|0|0|0|0|0|0|двойных  |+4
 |                            | | L | | | | | | | | | |слов     |
 |                            | |   | | | | | | | | | |         |
 ----------------------------------------------------------------
 |   Селектор сегмента        |     Смещение в сегменте 15:00   |+0
 ----------------------------------------------------------------
 
 DPL    Уровень привилегированности дескриптора
 P      Присутствие сегмента
 
                    Рисунок 6-5.  Шлюз вызова
 
 Дескрипторы шлюзов вызова используются командами CALL и JUMP
 используются аналогичным способом, что и дескрипторы кодовых
 сегментов. Когда аппаратная часть распознает, что селектор
 сегмента назначения ссылается к шлюзовому дескриптору,
 выполнение команды определяется содержимым шлюза вызова.
 Дескриптор шлюза вызова может находиться в GDT или в LDT, но не
 в таблице дескрипторов прерывания (IDT).
 
 Поля Селектора и Смещения в шлюзе образуют указатель на точку
 входа в процедуру. Шлюз вызова гарантирует, что любые передачи
 управления другим сегментам будут происходить в правильные точки
 входа процедуры, а не куда-нибудь в середину процедуры (или, что
 еще хуже, в середину команды). Операнд команды передачи
 управления не является селектором сегмента и смещением в
 сегменте точки входа желаемой процедуры. Вместо этого селектор
 сегмента указывает на шлюзовой селектор, а смещение не
 используется. Такая форма адресации показана на Рисунке 6-6.
 
 
 |<---------------- Адрес назначения --------------->|
 
 15           0     31                              0
 ---------------    ----------------------------------
 |   Селектор  |    |    Смещение в сегменте         |
 ---------------    ----------------------------------
          \                         |
           \                        \/
            \                 Не используется
             \
              \
               \           Таблица дескрипторов
                \   ----------------------------------
                 \  |        |       |       |       |
                  \ |--------------------------------|
                   \|                |               |
                    |--------------------------------|
   -----------------|    Смещение    |  DPL  |Счетчик| Дескриптор
   |                |--------------------------------| шлюза
   |      ----------|    Селектор    |  Смещение     |
   |      |         |--------------------------------|
   |      |         |        |       |       |       |
   |      |         |--------------------------------|
   |      |         |                |               |
   |      |-----    |--------------------------------|
   |            \   |        |       |       |       |
   |             \  |--------------------------------|
   |              \ |                |               |
   |               \|--------------------------------| Дескриптор
   |                | База   |       |  DPL  | База  | кодового
 -----              |--------------------------------| сегмента
 | + |<------------ |      База      |               |
 -----              |--------------------------------|
   |                |        |       |       |       |
   |                |--------------------------------|
   \/               |                |               |
 Точка входа        ----------------------------------
 в процедуру
 
               Рисунок 6-6. Механизм шлюза вызова
 
 Как показано на Рисунке 6-7, для проверки допустимости передачи
 управления через шлюз вызова используется четыре различных
 уровня привилегированности.
 
 Уровни привилегированности, проверяемые при передаче управления
 шерез шлюз вызова, это:
 
 1. CPL (текущий уровень привилегированности).
 
 2. RPL (уровень привилегированности источника запроса) селектора
    сегмента, который был использован для задания шлюза вызова.
 
 3. DPL (уровень привилегированности дескриптора) дескриптора
    шлюза.
 
 4. DPL дескриптора сегмента кодового сегмента назначения
    перехода.
 
 Поле DPL дескриптора шлюза определяет, из каких уровней
 привилегированности может использоваться данный шлюз. Один
 кодовый сегмент может содержать несколько различных процедур,
 предназначенных для использования из различных уровней
 привилегированности. Так, операционная система может иметь
 некоторые служные процедуры, используемые как прикладными
 программами, так и самой операционной системой, например,
 подпрограммы ввода/вывода символов, тогда как другие служебные
 процедуры могут быть предназначены только для использования их
 операционной системы, например, подпрограммы инициализации
 драйверов устройств.
 
 Шлюзы могут использоваться для передачи управления как на более
 привилегированные уровни, так и на тот же уровень
 привилегированности (хотя в последнем случае их использование не
 обязательно). Для передачи управления на менее привилегированные
 уровни шлюзы могут использоваться только командами CALL. Команда
 JMP может использовать шлюз только для передачи управления либо
 кодовому сегменту с тем же уровнем привилегированности, либо
 конформному кодовому сегменту с тем же или более высоким уровнем
 привилегированности.
 
 Для команды перехода JMP к неконформному сегменту должны
 удовлетворяться следующие два правила привилегированности (в
 противном случае генерируется исключение общей защиты):
 
 MAX(CPL,RPL) <= DPL шлюза
 DPL кодового сегмента назначения = CPL
 
 Для команды CALL (или команды перехода JMP к конформному
 сегменту) должны удовлетворяться следующие два правила
 привилегированности (в противном случае генерируется исключение
 общей защиты):
 
 MAX(CPL,RPL) <= DPL шлюза
 DPL кодового сегмента назначения <= CPL
 
 6.5.1  Переключение стека
 -----------------------------------------------------------------
 
 При вызове процедуры более привилегированного уровня выполняется
 следующее:
 
 1. Изменяется CPL.
 
 2. Передается управление (выполнением).
 
 3. Происходит переключение стеков.
 
 
                Шлюз вызова
 
 
 31                               15              7            0
 ----------------------------------------------------------------
 |                               | | D |         |     |        |
 |                               | | P |         |     |        | +4
 |                               | | L |         |     |        |
 |--------------------------------------------------------------|
 |                               |   |__________________        | +0
 -------------------------------------------------------|--------
                                                        |
                                                        |
                Дескриптор сегмента кода назначения     |
                                                        |
                                                        |
 31                               15              7     |      0
 -------------------------------------------------------|--------
 |               | | | | |       | | D |         |      |       |
 |               | | | | |       | | P |         |      |       | +4
 |               | | | | |       | | L |         |      |       |
 |------------------------------------------------------|-------|
 |                               |   |_______________   |       | +0
 ----------------------------------------------------|--|--------
                                                     |  |
                 Текущий регистр кодового сегмента   |  |
                                                     |  |
 --------------------                                |  |
 |            | CPL |-----------------------------   |  |
 --------------------                            |   |  |
                 Селектор шлюза вызова           |   |  |
 --------------------                            |   |  |
 |            | RPL |-------------------------   |   |  |
 --------------------                         |  |   |  |
                                              |  |   |  |
                                              \/ \/  \/ \/
                                          ---------------------
                                          |      Проверка     |
                                          |привилегированности|
                                          ---------------------
 CPL       Текущий уровень привилегированности
 DPL       Уровень привилегированности дескриптора
 RPL       Запрошенный уровень привилегированности
 
          Рисунок 6-7. Проверка привилегированности при
           передаче управления при помощи шлюза вызова
 
 Внутренние кольца защиты (уровень привилегированности 0, 1 и 2)
 имеют свои собственные стеки для приема вызовов из менее
 привилегированных уровней. Если стек должна была обеспечить
 вызывающая процедура, и стек оказался слишком мал, то в
 результате недостаточного размера стека может произойти сбой
 вызываемой процедуры. Поэтому обеспечивается защита более
 привилегированных программ от сбоя вследствие менее
 привилегированных программ путем создания нового стека при
 вызове менее привилегированными процедурами более
 привилегированных. Создается новый стек, параметры вызова
 копируются из старого стека в новый, а значения регистров
 сохраняются, после чего продолжается обычное выполнение
 вызванной процедуры. При возврате из этой процедуры содержимое
 сохраненных регистров восстанавливается в исходном стеке. Полное
 описание механизма переключения задач приводится в Главе 7.
 
 Процессор находит место для создания новых стеков при помощи
 сегмента состояния задачи (TSS), как показано на Рисунке 6-8.
 Каждая задача имеет собственный TSS. TSS содержит исходные
 указатели стека для внутренних колец защиты. Операционная
 система отвечает за создание каждого TSS и инициализацию
 соответствующих им указателей стека. Исходный указатель стека
 состоит из селектора сегмента и исходного значения регистра ESP
 (исходное смещение в сегменте). Исходные указатели стеков
 представляют собой значения, предназначенные исключительно для
 чтения. Процессор не изменяет их во время выполнения задач. Эти
 указатели стеков используются только для создания новых стеков
 при выполнении вызовов процедур с более высоким уровнем
 привилегированности. При возврате из вызванных процедур эти
 стеки исчезают. При следующем вызове процедуры происходит
 создание нового стека с использованием для этого исходного
 указателя стека.
 
 
           32-разрядный сегмент состояния задачи
 31                                                 0
 ----------------------------------------------------
 |                                                  | 64
 |                                                  |
 |                                                  |
 |                                                  |
 |                                                  |
 |--------------------------------------------------|
 |                         |         SS2            | 18
 |--------------------------------------------------|
 |                        ESP2                      | 14
 |--------------------------------------------------|
 |                         |         SS1            | 10
 |--------------------------------------------------|
 |                        ESP1                      | 0C
 |--------------------------------------------------|
 |                         |         SS0            | 8
 |--------------------------------------------------|
 |                        ESP0                      | 4
 |--------------------------------------------------|
 |                         |         SS2            | 0
 ----------------------------------------------------
 
 Примечание:  адреса приведены в шестнадцатиричном формате
 
      Рисунок 6-8. Исходные указатели стека в TSS
 
 При использовании шлюза вызова для изменения уровней
 привилегированности новый стек создается загрузкой адреса из
 TSS. Процессор использует DPL кодового сегмента назначения
 (новый CPL) для выбора исходного указателя стека для уровней
 привилегированности 0, 1 или 2.
 
 DPL нового стекового сегмента должен быть равен новому CPL: в
 противном случае генерируется исключение сбоя в стеке.
 Ответственность за создание стеков и дескрипторов стекового
 сегмента для всех используемых уровней привилегированности лежит
 на операционной системе. Стеки должны быть доступны для
 чтения/записи, как задано в поле Типа соответствующих сегментных
 дескрипторов. Они должны содержать достаточно памяти, как задано
 полем Граница, чтобы там могло поместиться содержимое регистров
 SS и ESP, адрес возврата, параметры и временные переменные,
 требуемые для работы вызываемой процедуры.
 
 Как и при вызове в пределах одного уровня привилегированности,
 параметры для всех процедур помещаются в стек. Затем эти
 параметры копируются в новый стек. Доступ к этим параметрам из
 вызываемой процедуры происходит по тем же адресам, по которым
 эти параметры находились бы без переключения стека. Поле Счетчика
 шлюза вызова сообщает процессору, сколько двойных слов (до 31)
 должно копироваться из стека вызывающей процедуры в стек
 вызываемой процедуры. Если этот счетчик равен 0, то копирования
 параметров не происходит.
 
 Если требуется передать в вызываемую процедуру более 31 двойного
 слова данных, то один из параметров можно сделать указателем на
 структуру данных, либо сохраненные в нем значения регистров SS и
 ESP могут использоваться для доступа к параметрам в старой
 области стека.
 
 Во время вызова процедуры с другим уровнем привилегированности
 процессор выполняет следующие связанные со стеком действия:
 
 1. Проверяется стек вызываемой процедуры, чтобы убедиться, что
    он достаточно велик для того, чтобы хранить параметры и
    сохраняемые значения регистров; в противном случае
    генерируется исключение переполнения стека.
 
 2. Старое содержимое регистров SS и ESP помещается в стек
    вызываемой процедуры в виде двух двойных слов (16-разрядный
    регистр SS расширяется нулем до 32 битов; это заполненное
    нулем старшее слово резервировано Intel для внутреннего
    пользования; не должно использоваться).
 
 3. Параметры копируются из стека вызывающей программы в стек
    вызываемой программы.
 
 4. В новый стек помещается указатель команды, находящейся после
    команды CALL (старое содержимое регистров CS и IP).
    Содержимое регистров SS и ESP после вызова указывает на этот
    указатель адреса возврата в стеке.
 
 На Рисунке 6-9 показаны кадры стека до, во время и после
 успешного вызова и возврата между процедурами с разными уровнями
 привилегированности.
 
 TSS не имеет указателя стека для стека с уровнем
 привилегированности 3, поскольку процедура с уровнем
 привилегированности 3 не может быть вызвана процедурой с еще
 более низким уровнем. Стек для уровня привилегированности 3
 предохраняется содержимым регистров SS и EIP, которые
 сохраняются в стеке привилегированного уровня, вызванного из
 уровня 3.
 
 
   Старый стек         Новый стек           Старый стек
   до вызова           после вызова,        после возврата
                       до возврата
 
                       ----------------
 |             |       | Старый SS    |     |             |
 |-------------|       |--------------|     |-------------|
 |             |       | Старый ESP   |     |             |<-ESP
 |-------------|       |--------------|     |-------------|
 | Параметр 1  |       | Параметр 1   |     |             |
 |-------------|       |--------------|     |-------------|
 | Параметр 2  |       | Параметр 2   |     |             |
 |-------------|       |--------------|     |-------------|
 | Параметр 3  |<-ESP  | Параметр 3   |     |             |
 |-------------|       |--------------|     |-------------|
 |             |       | Старый CS    |     |             |
 |-------------|       |--------------|     |-------------|
                       | Старый EIP   |<-ESP
                       |--------------|
                       |              |
                       |--------------|
 
          Рисунок 6-9. Кадры стека при вызове процедуры
               с другим уровнем привилегированности
 
 Вызов, использующий шлюз вызова, не проверяет значений слов,
 копируемых в новый стек. Вызванная процедура должна проверять
 допустимость каждого параметра. В следующих разделах обсуждается
 использование команд ARPL, VERR, VERW, LSL и LAR для проверки
 значений указателей.
 
 6.5.2  Возврат из процедуры
 -----------------------------------------------------------------
 
 "Ближние" формы команды RET выполняют передачу управления только
 в пределах текущего кодового сегмента, и следовательно, для них
 выполняется только контроль границ. Смещение для команды,
 следующей после команды вызова CALL, извлекается из стека и
 помещается в регистр EIP. Процессор контролирует, чтобы это
 смещение не превосходило границу текущего кодового сегмента.
 
 "Дальняя" форма команды RET извлекает адрес возврата, помещенный
 в стек предыдущей командой CALL. В нормальных условиях указатель
 возврата всегда достоверен, поскольку он был сгенерирован
 командой CALL или INT. Тем не менее, процессор выполняет
 проверку привилегированности вследствие возможности того, что
 текущая процедура изменила указатель или не смогла правильно
 обработать стек. RPL селектора кодового сегмента, извлеченный из
 стека командой возврата, должен иметь уровень
 привилегированности вызывающей процедуры.
 
 Возврат в другой сегмент может изменить уровни
 привилегированности, но только в сторону более низких уровней.
 Когда команда RET встречает сохраненное значение CS, RPL
 которого численно больше CPL (т.е. имеет более привилегированный
 уровень), происходит возврат через уровни привилегированности.
 Такого рода возврат выполняет следующие шаги:
 
 1. Выполняются проверки, показанные в Таблице 6-2 и регистры CS,
    EIP, SS и ESP загружаются их предыдущими значениями, которые
    были сохранены в стеке.
 
 2. Старое содержимое регистров SS и ESP (из вершины текущего
    стека) настраивается по размеру в байтах, заданному в команде
    RET. Результирующее значение ESP не проверяется на границу
    стекового сегмента. Если значение ESP выходит за эту границу,
    то этот факт не распознается процессором до следующей
    стековой операции. (Содержимое регистров SS и ESP для
    возвращаемой процедуры не сохраняются; обычно их значения те
    же, что и хранимые в TSS).
 
 3. Проверяется содержимое сегментных регистров DS, ES, FS и GS.
    Если хоть один из этих регистров ссылается на сегмент, DPL
    которого меньше нового CPL (включая конформные кодовые
    сегменты), сегментный регистр загружается пустым селектором
    (Индекс=0, TI=0). Сама команда RET в таких случаях не
    сообщает об исключениях; однако любые последующие ссылки к
    памяти при помощи сегментного регистра, содержпщего пустой
    селектор, вызовут исключение общей защиты. Это не позволяет
    менее привилегированным кодам обращаться к более
    привилегированным сегментам посредством селекторов,
    оставленных в сегментных регистрах более привилегированной
    процедурой.
 
       Таблица 6-2. Проверки при возврате между процедурами
              с разными уровнями привилегированности
 
 ------------------------------------------------------------------
 |Тип проверки |                  Тип особой ситуации | Код ошибки|
 ------------------------------------------------------------------
 |Вершина стека должна быть                                       |
 |в пределах границы сегмента                                     |
 |стека                            Стек                 0         |
 |                                                                |
 |Адрес Вершины стека+7 должен быть                               |
 |в пределах границы сегмента                                     |
 |стека                            Стек                 0         |
 |                                                                |
 |RPL кодового сегмента возврата                                  |
 |должен превышать CPL             Защита              CS возврата|
 |                                                                |
 |Селектор кодового сегмента                                      |
 |возврата не должен быть пустым   Защита              CS возврата|
 |                                                                |
 |Дескриптор кодового сегмента                                    |
 |возврата должен быть в пределах                                 |
 |границы таблицы дескрипторов     Защита              CS возврата|
 |                                                                |
 |Дескриптор сегмента возврата                                    |
 |должен относиться к кодовому                                    |
 |сегменту                         Защита              CS возврата|
 |                                                                |
 |Присутствие кодового сегмента    Сегмент не                     |
 |возврата                         присутствует        CS возврата|
 |                                                                |
 |DPL не-конформного кодового                                     |
 |сегмента возвратв должен быть                                   |
 |равен RPL селектора кодового                                    |
 |сегмента возврата, либо DPL                                     |
 |конформного кодового сегмента                                   |
 |возврата должен быть меньше                                     |
 |или равен RPL селектора кодового                                |
 |сегмента возврата                Защита              CS возврата|
 |                                                                |
 |ESP+N+15*  должно находиться                                    |
 |в пределах границы сегмента                                     |
 |стека                            Сбой в стеке        CS возврата|
 |                                                                |
 |Селектор сегмента в ESP+N+12*                                   |
 |не должен быть пустым            Защита              CS возврата|
 |                                                                |
 |Дескриптор сегмента в ESP+N+12*                                 |
 |должен находиться в пределах                                    |
 |границы таблицы дескрипторов     Защита              CS возврата|
 |                                                                |
 |Дескриптор стекового сегмента                                   |
 |должен быть доступен для                                        |
 |чтения/записи                    Защита              CS возврата|
 |                                                                |
 |Должен присутствовать стековый                                  |
 |сегмент                          Сбой в стеке        CS возврата|
 |                                                                |
 |DPL старого стекового сегмента                                  |
 |должен быть равен RPL старого                                   |
 |кодового сегмента                Защита              CS возврата|
 |                                                                |
 |Селектор старого стекового                                      |
 |сегмента должен иметь RPL,                                      |
 |равный DPL старого стекового                                    |
 |сегмента                         Защита              CS сегмента|
 ------------------------------------------------------------------
 
 * N - это значение непосредственного операнда, заданного в
   команде RET.
 
 6.6  Команды, зарезервированные для работы операционной системы
 -----------------------------------------------------------------
 
 Команды, которые могут воздействовать на механизм защиты или
 повлиять на общие характеристики производительности системы,
 могут выполняться только наиболее проверенными процедурами.
 Процессор i486 имеет два класса таких команд:
 
 1. Привилегированные команды - команды, используемые для
    управления системой.
 
 2. Чувствительные команды - команды, используемые для ввода/
    вывода и действий, связанных с вводом/выводом.
 
 6.6.1  Привилегированные команды
 -----------------------------------------------------------------
 
 Команды, которые оказывают влияние на средства защиты системы,
 могут быть выполнены только при CPL равном 0 (наивысший уровень
 привилегированности). Если какая-либо из этих команд выполняется
 при CPL не равном 0, генерируется исключение общей защиты. В
 число этих команд входят:
 
 CLTS               - Очистить флаг переключения задачи
 HLT                - Выполнить останов процессора
 LGDT               - Загрузить регистр GDT
 LIDT               - Загрузить регистр IDT
 LLDT               - Загрузить регистр LDT
 LMSW               - Загрузить слово состояния машины
 LTR                - Загрузить регистр задачи
 MOV в/из CR0       - Пересылка с управляющим регистром 0
 MOV в/из DRn       - Пересылка с отладочным регистром n
 MOV в/из TRn       - Пересылка с тестовым регистром n
 
 6.6.2  Чувствительные команды
 -----------------------------------------------------------------
 
 Команды, работающие с вводом/выводом, должны быть защищенными,
 но они также должны давать возможность выполнения их и из
 уровней привилегированности, не равных 0 (т.е выполнения их не
 из наиболее привилегированного уровня). Механизмы защиты
 операций ввода/вывода подробно описаны в Главе 8.
 
 6.6  Команды проверки достоверности указателей
 -----------------------------------------------------------------
 
 Проверка достоверности указателей необходима для поддержания
 изолированности разных уровней привилегированности. Она состоит
 из следующих шагов:
 
 1. Проверка того, что процедура, создавшая данный указатель,
    имеет права доступа к данному сегменту.
 
 2. Проверка того, что тип сегмента совместим с запрошенным
    способом его использования.
 
 3. Проверка того, что смещение указателя не превышает границу
    сегмента.
 
 Хотя процессор i486 автоматически выполняет проверки 2 и 3 при
 выполнении команды, в выполнении первой проверки должно
 участвовать программное обеспечение. Для этого предназначена
 команда ARPL. Программное обеспечение может также выполнять
 проверки 2 и 3 не дожидаясь, пока будет сгенерировано исключение
 процессора. Для этого предназначены команды LAR, LSL, VERR и
 VERW.
 
 В режиме пользователя может выполняться дополнительная проверка
 выравнивания. Когда одновременно установлены бит AM регистра CR0
 и флаг AC, невыравненные ссылки к памяти ведут к генерации
 исключения. Это свойство полезно для программ, которые
 используют два младшие бита указателя для идентификации типа
 данных адресуемой указателем структуры. Например, подпрограмма в
 библиотеке математических функций может принимать указатели на
 числовые структуры данных. Если типу такой структуры присвоен
 код 10 (двоичный), записанный в двух младших битах указателей на
 этот тип, то математические подпрограммы могут выполнять
 коррекцию по коду типа, прибавляя смещение -10 (двоичное). При
 получении подпрограммой неверного указателя типа ссылка будет
 невыравненной, что приведет к генерации исключения. Проверка
 выравнивания ускоряет работу программ, написанных на языках
 искуственного интеллекта, таких как Lisp, Prolog, Smalltalk и
 C++. Она также может использоваться для ускорения проверки
 признака типа указателя.
 
 LAR (Загрузить права доступа) используется для верификации того,
 что указатель ссылается на сегмент с совместимостью по уровню
 привилегированности и типу. Команда LAR имеет один операнд -
 селектор сегмента для дескриптора, права доступа которого должны
 быть проверены. Дескриптор сегмента должен быть доступным для
 чтения на уровне привилегированности, численно большем (т.е.
 менее привилегированном), чем CPL и RPL селектора. Если
 дескриптор доступен для чтения, то команда LAR принимает второе
 двойное слово дескриптора, маскирует его значением 00FxFF00H,
 записывает результат в заданный 32-разрядный регистр назначения
 и устанавливает флаг ZF. (x означает, что соответствующие четыре
 бита записанного значения неопределены). Будучи однажды
 загруженным, прова доступа могут быть затем проверены. Команда
 LAR позволяет тестировать все допустимыке типы дескрипторов.
 Если RPL или CPL превышает DPL, или если селектор сегмента
 превышает границу для таблицы дескрипторов, права доступа не
 возвращаются, и флаг ZF очищается. Доступ к конформным кодовым
 сегментам допускается из любых уровней привилегированности.
 
 LSL (Загрузить границу сегмента) позволяет программно
 тестировать границу дескриптора сегмента, если дескриптор, на
 который ссылается селектор сегмента (в памяти или в регистре),
 доступен для чтения на текущем CPL. Команда LSL загружает
 заданнный 32-разрядный регистр 32-разрядным гранулированным
 побайтно значением границы, вычисленным на основе
 конкатенированных полей границы и бита грануляции G дескриптора.
 Это может быть сделано только для дескрипторов, описывающих
 сегменты (данных, кода, состояния задачи и таблиц дескрипторов);
 дескрипторы шлюзов таким способом недоступны. (В таблице 6-3
 подробно перечислено, какие типы допустимы, а какие нет).
 Интерпретация границы зависит от типа сегмента. Например,
 сегменты данных, расширяющиеся вниз (стековые сегменты)
 рассматривают границу иначе, чем все прочие типы сегментов. Для
 обеих команд, LAR и LSL, флаг ZF устанавливается в том случае,
 если загрузка была выполнена успешно; в противном случае флаг ZF
 очищается.
 
      Таблица 6-3. Допустимые типы дескрипторов команды LSL
 -----------------------------------------------------------------
 Код типа             Тип дескриптора                  Допустим?
 -----------------------------------------------------------------
    0                 Зарезервирован                   Нет
    1                 Зарезервирован                   Нет
    2                 LDT                              Да
    3                 Зарезервирован                   Нет
    4                 Зарезервирован                   Нет
    5                 Шлюз задачи                      Нет
    6                 Зарезервирован                   Нет
    7                 Зарезервирован                   Нет
    8                 Зарезервирован                   Нет
    9                 Доступен TSS центрального
                      процессора i486                  Да
    A                 Зарезервирован                   Нет
    B                 Занят TSS центрального
                      процессора i486                  Да
    С                 Шлюз вызова центрального
                      процессора i486                  Нет
    D                 Зарезервирован                   Нет
    E                 Шлюз прерывания центрального
                      процессора i486                  Нет
    С                 Шлюз ловушки центрального
                      процессора i486                  Нет
 -----------------------------------------------------------------
 
 6.7.1  Проверка достоверности дескриптора
 -----------------------------------------------------------------
 
 Процессор i486 имеет две команды, VERR и VERW, которые
 определяют, указывает ли селектор сегмента на сегмент, который
 доступен для чтения или записи для текущего CPL. Ни одна их этих
 команд не вызывает защитного исключения, если сегмент
 недоступен.
 
 VERR (Верификация доступности чтения) выполняет верификацию
 доступности сегмента для чтения и устанавливает флаг ZF, если
 для текущего CPL этот сегмент доступен для чтения. Команда VERR
 проверяет следующее:
 
 - Селектор сегмента указывает на дескриптор сегмента в пределах
   границ GDT или LDT.
 
 - Селектор сегмента индексирует дескриптор сегмента кода или
   данных.
 
 - Сегмент доступен для чтения и  имеет  совместимый  уровень
   привилегированности.
 
 Проверка привилегированности для сегментов данных и
 не-конформных кодовых сегментов удостоверяет, что DPL имеет
 меньший уровень привилегированности, чем CPL или RPL селектора.
 Конформные сегменты на уровень привилегированности не
 проверяются.
 
 VERW (Верификация доступности записи) аналогична команде VERR :
 она выполняет верификацию доступности сегмента для записи и
 устанавливает флаг ZF, если этот сегмент доступен для чтения.
 Команда VERW удостоверяет, что дескриптор попадает в нужные
 границы, действительно является дескриптором сегмента, сегмент
 доступен для чтения и имеет DPL с менее привилегированным
 уровнем, нежели CPL или RPL селектора. Кодовые сегменты никогда
 не бывают доступными для записи: как конформные, так и
 не-конформные.
 
 6.7.2  Целостность указателя и RPL
 -----------------------------------------------------------------
 
 Запрошенный уровень привилегированности (RPL) может
 предотвратить случайное использование указателей, разрушающих
 более привилегированный код из кода с меньшим уровнем
 привилегированности.
 
 Распространенным примером может служить файловая системная
 процедура FREAD (идентификатор_файла, n_байтов,
 указатель_буфера). Эта гипотетическая процедура считывает данные
 из дискового файла в буфер, затирая любое ранее записаное
 содержимое этого буфера. Она обслуживает запросы программ,
 работающих на прикладном уровне, но сама должна работать на
 привилегированном уровне, чтобы всегда иметь возможность
 обслуживать ввод/вывод операционной системы. Если прикладная
 программа передаст этой процедуре неверный указатель буфера,
 который указывает на важные участки кода или данных в
 привилегированном адресном пространстве, процедура может
 выполнить действия, ведущие к разрушению системы.
 
 Избежать подобной проблемы позволяет использование RPL. RPL
 позволяет назначить селектору переопределенную
 привилегированность. Такая переопределенная привилегированность
 представляет собой уровень привилегированности кодового
 сегмента, сгенерировавшего данный селектор сегмента. В
 вышеприведенном примере RPL должен представлять собой CPL
 прикладной программы, вызвавшей процедуру системного уровня.
 Процессор i486 автоматически проверяет любой загруженный в
 сегментный регистр селектор, определяя, допускает ли его RPL
 выполнить запрошенный доступ.
 
 Для того, чтобы воспользоваться преимуществами, даваемыми такой
 проверкой процессором RPL, вызываемая процедура должна только
 проверять, чтобы все передаваемые ей селекторы сегмента имели
 RPL с тем же или меньшим уровнем привилегированности, что и CPL
 исходного источника запроса. Если селектор используется для
 доступа к сегменту, к которому источник запроса не может
 обратиться напрямую, т.е. RPL которого имеет меньшую
 привилегированность, чем DPL запрошенного сегмента, то при
 загрузке селектора в сегментный регистр генерируется исключение
 общей защиты.
 
 ARPL (Настроить запрошенный уровень привилегированности)
 настраивает поле RPL селектора сегмента в большее из значений
 (меньший уровень привилегированности), выбирая из его исходного
 значения и значения поля RPL для селектора сегмента, записанного
 в регистр общего назначения. Поля RPL находятся в двух младших
 битах селектора сегмента и регистра. Последний обычно
 представляет собой копию регистра CS вызывающей процедуры в
 стеке. Если при такой настройке RPL селектора изменяется, то
 происходит установка флага ZF; в противном случае флаг ZF
 очищается.
 
 6.8  Защита на уровне страниц
 -----------------------------------------------------------------
 
 Защита работает как на уровне сегментов, так и на уровне
 страниц. При использовании плоской модели сегментации памяти
 защита на уровне страниц также предотвращает недопустимое
 взаимное влияние между программами.
 
 Каждая ссылка к памяти контролируется на удовлетворение проверок
 защиты. Все проверки выполняются до начала цикла обращения к
 памяти; любое нарушение защиты предотвращает начало этого цикла
 и генерирует исключение. Поскольку эти проверки выполняются
 параллельно с трансляцией адреса, они не влекут дополнительных
 затрат времени процессора. Существует два вида проверки защиты
 на уровне страниц:
 
 1. Ограничения на адресуемый домен памяти.
 
 2. Проверка типа.
 
 Нарушение защиты приводит к генерации исключения. Механизм
 исключений описан в Главе 9. В данной главе описаны нарушения
 защиты, ведущие к исключениям.
 
 6.8.1  Элементы страничных таблиц содержат параметры защиты
 -----------------------------------------------------------------
 
 На Рисунке 6-10 показаны поля элемента страничной таблицы,
 которые управляют доступом к странице. Проверки защиты
 применяются к страничным таблицам как первого, так и второго
 уровня.
 
 6.8.1.1  Ограничения адресуемого домена памяти
 -----------------------------------------------------------------
 
 Для страниц и сегментов понятие привилегированности
 интерпретируется по-разному. Для сегментов существует четыре
 уровня привилегированности, лежащих в диапазоне от 0 (высший
 уровень привилегированности) до 3 (низший уровень
 привилегированности). для страниц существует два уровня
 привилегированности:
 
 1. Уровень супервизора (U/S=0) - для операционной системы,
    прочего системного программного обеспечения (например,
    драйверов устройств), а также для защищаемых системных данных
    (например, страничных таблиц).
 
 2. Уровень пользователя (U/S=1) - для прикладных кодов и данных.
 
 Уровни привилегированности, используемые в сегментации,
 отображаются в уровнях привилегированности страниц. Если CPL
 равен 0, 1 или 2, то процессор работает на уровне супервизора.
 Если же CPL равен 3, то процессор работает на уровне
 пользователя. Когда процессор работает на уровне супервизора,
 все страницы являются доступными. Когда процессор работает на
 уровне пользователя, доступны только страницы, имеющие уровень
 пользователя.
 
 31                               12 11                      0
 --------------------------------------------------------------
 |                                  |       |   | | |P|P|U|R| |
 | Адрес страничного блока 31...12  |Доступн|0 0|D|A|C|W|/|/|P|
 |                                  |       |   | | |D|T|S|W| |
 --------------------------------------------------------------
 
 R/W   Чтение/Запись
 U/S   пользователь/Супервизор
 
      Рисунок 6-10. Поля защиты элемента страничной таблицы
 
 6.8.1.2  Проверка типа
 -----------------------------------------------------------------
 
 Механизмом защиты распознаются только два вида страниц:
 
 1. Доступ Только для Чтения (R/W=0)
 
 2. Доступ на Чтение/Запись (R/W=1).
 
 Когда процессор работает на уровне супервизора при очищенном
 бите WP в регистре CR0 (в состоянии бита, соответствующем
 инициализации при сбросе системы), все страницы являются
 одновременно доступными для чтения и записи (признак защиты
 записи игнорируется). Когда процессор работает на уровне
 пользователя, то для записи доступны лишь страницы уровня
 пользователя, помеченные признаком Чтение/Запись. Страницы
 уровня пользователя, помеченные для Чтения/Записи или Только для
 Чтения, являются доступными для чтения. Страницы уровня
 супервизора с уровня пользователя недоступны ни для чтения, ни
 для записи. При попытке нарушения прав доступа к защищенным
 страницам генерируется исключение общей защиты.
 
 В отличие от процессора 386 DX процессор i486 позволяет защищать
 страницы уровня пользователя от записи в режиме доступа
 супервизора. Установка бита WP в регистре CR0 включает
 чувствительность режима супервизора к защите страниц от записи в
 режиме пользователя. Это средство полезно для реализации
 стратегии "записи-на-копии", используемой некоторыми
 операционными системами, например UNIX, для создания задачи (это
 средство также называется порождением параллельных процессов или
 просто порождением).
 
 При создании новой задачи можно скопировать все адресное
 пространство порождающей задачи. Это дает порожденной задаче
 полный, дубликатный набор сегментов и страниц порождающей
 задачи. Стратегия "записи-на-копии" экономит область памяти и
 время, отображая порожденные сегменты и страницы в тех же
 сегментах и страницах, что используются порождающей задачей.
 Частная копия страницы создается только в случае, когда одна из
 задач выполняет запись в эту страницу.
 
 6.8.2  Объединение защиты страничных таблиц обоих уровней
 -----------------------------------------------------------------
 
 Для каждой отдельной страницы аттрибуты защиты соответствующего
 ей элемента каталога страниц (таблицы страниц первого уровня)
 могут отличаться от аттрибутов защиты элемента таблицы страниц
 второго уровня. Процессор i486 проверяет защиту страницы,
 рассматривая атртрибуты защиты, заданные в таблицах обоих
 уровней. В Таблице 6-4 показана защита, обеспечиваемая
 возможными комбинациями аттрибутов защиты при очищенном бите WP.
 
        Таблица 6-4. Объединенная защита каталога страниц
                        и таблицы страниц
 ----------------------------------------------------------------
 |  Элемент каталога     Элемент таблицы       Объединенный     |
 |      страниц              страниц               эффект       |
 |--------------------------------------------------------------|
 |Привиле|Тип         |Привеле|Тип         |Привеле|Тип         |
 |гирован|доступа     |гирован|доступа     |гирован|доступа     |
 |ность  |            |ность  |            |ность  |            |
 |--------------------------------------------------------------|
 |Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
 |Пользов|ТолькоЧтение|Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|
 |Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
 |Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|
 |Пользов|ТолькоЧтение|Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|
 |Пользов|ТолькоЧтение|Суперв |ЧтениеЗапись|Пользов|ТолькоЧтение|
 |Пользов|ЧтениеЗапись|Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|
 |Пользов|ЧтениеЗапись|Суперв |ЧтениеЗапись|Пользов|ЧтениеЗапись|
 |Суперв |ТолькоЧтение|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
 |Суперв |ТолькоЧтение|Пользов|ЧтениеЗапись|Пользов|ТолькоЧтение|
 |Суперв |ЧтениеЗапись|Пользов|ТолькоЧтение|Пользов|ТолькоЧтение|
 |Суперв |ЧтениеЗапись|Пользов|ЧтениеЗапись|Пользов|ЧтениеЗапись|
 |Суперв |ТолькоЧтение|Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|
 |Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|
 |Суперв |ЧтениеЗапись|Суперв |ТолькоЧтение|Суперв |ЧтениеЗапись|
 |Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|Суперв |ЧтениеЗапись|
 ----------------------------------------------------------------
 
 
 6.8.3  Переопредлеление защиты страниц
 -----------------------------------------------------------------
 
 Некоторые виды доступа проверяются, как имеющие уровень
 привилегированности 0, для любых значений CPL:
 
 - Доступ к дескрипторам сегментов (LDT, GDT, TSS и IDT).
 
 - Доступ к внутреннему стеку по время выполнения команды CALL,
   или исключений и прерываний, когда происходит изменение уровня
   привилегированности.
 
 6.9 Объединение защиты сегментов и страниц
 -----------------------------------------------------------------
 
 При разрешенном механизме подкачки страниц процессор i486
 сначала выполняет проверки защиты сегмента, а затем проверки
 защиты страницы. Если процессор обнаруживает нарушение защиты на
 любом из уровней защиты, как сегмента, так и страницы,
 выполнение не продолжается: генерируется исключение. Если
 исключение генерируется механизмом защиты сегментов, исключение
 защиты страниц не генерируется.
 
 Например, можно определить большой сегмент данных, имеющий
 некоторые части с аттрибутом доступа Только для Чтения, а другие
 части - для Чтения/Записи. В этом случае элементы каталога
 страниц (или таблицы страниц) для частей с доступом Только для
 Чтения будут иметь биты U/S и R/W, задающие отсутствие прав
 доступа ко всем страницам, описанным данным элементом каталога
 (или отдельным страницам, заданным в страничных таблицах второго
 уровня). Данный метод может быть использован, например, для
 определения большого сегмента данных, часть которого
 предназначена Только для Чтения (для разделяемых или
 ПЗУ-резидентных данных). Тем самым определяется "плоское"
 пространство данных как один большой сегмент, с "плоскими"
 указателями, используемыми для доступа к этому "плоскому"
 пространство, с защитой разделяемых данных, разделяемых файлов,
 отображаемых в виртуальном пространстве, а также областей
 супервизора.
 
 
 
 Глава 7  Мультизадачность
 -----------------------------------------------------------------
 
 Процессор i486 обеспечивает аппаратную поддержку
 мультизадачности. Задачей называется программа, выполняемая в
 текущий момент, либо ожидающая выполнения во время работы другой
 программы. Задача запускается прерыванием, исключением,
 переходом или вызовом. Когда одна из этих форм передачи
 управления используется с назначением, заданным элементом одной
 из дескрипторных таблиц, этот дескриптор может иметь тип,
 вызывающий начало выполнение новой задачи после сохранения
 состояния текущей задачи. Существует два типа
 задаче-ориентированных дескрипторов, которые могут находиться в
 таблице дескрипторов: дескрипторы сегмента состояния задачи и
 шлюзы задачи. Когда управление передается любому из таких
 дескрипторов, происходит переключение задачи.
 
 Переключение задачи похоже на вызов процедуры, но оно выполняет
 сохранение большего количества информации о состоянии
 процессора. Вызов процедуры сохраняет только содержимое
 регистров общего назначение, а в некоторых случаях содержимое
 только одного регистра (EIP). При вызове процедуры содержимое
 сохраняемых регистров помещается в стек, чтобы процедура имела
 возможность вызвать сама себя. Когда процедура вызывает сама
 себя, она называется реентерабельной.
 
 Переключение задачи передает выполнение в полностью иную среду,
 среду задачи. Для этого требуется сохранить содержимое
 практически всех регистров процессора, таких как регистр EFLAGS.
 В отличие от процедур, задачи не реентерабельны. Переключение
 задачи ничего не помещает в стек. Информация о состоянии
 процессора сохраняется в структуре данных в памяти, которая
 называется сегмент состояния задачи.
 
 В число регистров и структур данных, поддерживающих
 мультизадачность, входят:
 
 - Сегмент состояния задачи.
 
 - Дескриптор сегмента состояния задачи.
 
 - Регистр задачи
 
 - Дескриптор шлюза задачи.
 
 Используя эти структуры, процессор i486 может переключать
 выполнение с одной задачи на другую, сохраняя контекст текущей
 задачи, допуская тем самым рестарт другой задачи. Помимо
 простого переключения задач, процессор i486 предлагает еще два
 средства организации мультизадачности:
 
 1. Переключение задачи может выполняться вследствие прерываний и
    исключений (если это требуется конструкции системы).
    Процессор не только выполняет переключение задачи для
    обработки прерывания или исключения, но и автоматическое
    переключение назад, на прерванную задачу, после возврата из
    прерывания или исключения. Прерывания могут происходить и во
    время задач обработки прерывания.
 
 2. При каждом переключении на другую задачу процессор i486 может
    также выполнять переключение на другую LDT. Это может
    использоваться для того, чтобы дать каждой задаче собственное
    отображение логических адресов в физические. Тем самым
    обеспечивается дополнительное средство защиты, поскольку
    задачи могут быть таким образом изолированы, и их взаимное
    влияние друг на друга исключено. Регистр PDBR также
    перезагружается. Это позволяет использовать механизм подкачки
    страниц для обеспечения изолированности задач.
 
 Использование механизма мультизадачности является
 необязательным. Для некоторых прикладных программ этот способ
 организации выполнения программ не является лучшим. При
 необходимости наибольшей скорости реакции на прерывания, время,
 которое потребуется на сохранение состояния процессора при
 переключении задачи может оказаться слишком большим. В этой
 ситуации возможный компромисс может состоять в том, чтобы
 использовать задаче-ориентированные структуры данных, но
 выполнять переключение задач программными, а не аппаратными
 средствами. Это позволяет сохранять меньшее количество
 информации о состоянии процессора. Этот метод может являться
 одним из методов оптимизации, используемых для улучшения
 характеристик быстродействия системы после реализации базовых
 функции системы.
 
 7.1  Сегмент состояния задачи
 -----------------------------------------------------------------
 
 Информация о состоянии процессора, необходимая для
 восстановления контекста задачи, хранится в типе сегмента,
 называемом сегментом состояния задачи, или TSS. На Рисунке 7-1
 показан формат TSS для задачи, выполняемой центральным
 процессором i486 (совместимость с задачами 80286 обеспечивается
 другим типом TSS: см. Главу 21). Поля TSS делятся на две
 основные категории:
 
 1. Динамические поля, обновляемые процессором при каждом
    переключении задачи. В число этих полей входят:
 
    - Регистры общего назначения (EAX, ECX, EDX, EBX, ESP,EBP,
      ESI и EDI).
 
    - Сегментные регистры (ES, CS, SS, DS, FS и GS).
 
    - Регистр флагов (EFLAGS).
 
    - Указатель команд (EIP),
 
    - Селектор для TSS предыдущей задачи (обновляется только
      когда ожидается возврат).
 
 2. Статические поля, которые процессор считывает, но не
    изменяет. Эти поля устанавливаются при создании задачи. Эти
    поля:
 
    - Селектор для LDT задачи.
 
    - Логический адрес для стеков привилегированных уровней 0, 1
      и 2.
 
    - Бит T (бит отладочной ловушки), который, будучи
      установленным, заставляет процессор устанавливать при
      переключении задачи отладочное исключение. (Более подробную
      информацию об отладке см. в Главе 11).
 
    - Базовый адрес битового массива разрешения ввода/вывода. При
      наличии, данный массив всегда хранится в TSS по старшим
      адресам. Базовый адрес указывает на начало массива. (Более
      подробную информацию о битовом массиве разрешения
      ввода/вывода см. в Главе 8).
 
 При использовании механизма подкачки страниц важно избегать
 помещения границы страницы в пределах части TSS, считываемой
 процессором при переключении задачи (первые 108 байтов). Если
 граница страницы находится в пределах этой части TSS, то
 страницы по обеим сторонам границы должны присутствовать в
 памяти одновременно. При отсутствии страницы или генерации
 исключения общей защиты после того, как процессор начал
 чтение TSS, возникает состояние невосстановимой ошибки.
 
 7.2  Дескриптор TSS
 -----------------------------------------------------------------
 
 Сегмент состояния задачи, как и все прочие сегменты,
 определяется дескриптором. Формат дескриптора TSS показан на
 Рисунке 7-2.
 
 
 31                       15                     0
 --------------------------------------------------
 |Базовый адрес массива   |    000000000000000  |T|  64
 |  ввода/вывода          |                     | |
 |------------------------------------------------|
 |  0000000000000000      |Селектор для LDT задачи|
 |------------------------------------------------|
 |  0000000000000000      |         GS            |
 |------------------------------------------------|
 |  0000000000000000      |         FS            |
 |------------------------------------------------|
 |  0000000000000000      |         DS            |
 |------------------------------------------------|
 |  0000000000000000      |         SS            |
 |------------------------------------------------|
 |  0000000000000000      |         CS            |
 |------------------------------------------------|
 |  0000000000000000      |         ES            |
 |------------------------------------------------|
 |                       EDI                      |
 |------------------------------------------------|
 |                       ESI                      |
 |------------------------------------------------|
 |                       EBP                      |
 |------------------------------------------------|
 |                       ESP                      |
 |------------------------------------------------|
 |                       EBX                      |
 |------------------------------------------------|
 |                       EDX                      |
 |------------------------------------------------|
 |                       ECX                      |
 |------------------------------------------------|
 |                       EAX                      |
 |------------------------------------------------|
 |                     EFLAGS                     |
 |------------------------------------------------|
 |                       EIP                      |
 |------------------------------------------------|
 |                    Резервируется               |
 |------------------------------------------------|
 |  0000000000000000      |         SS2           |
 |------------------------------------------------|
 |                      ESP2                      |
 |------------------------------------------------|
 |  0000000000000000      |         SS1           |
 |------------------------------------------------|
 |                      ESP1                      |
 |------------------------------------------------|
 |  0000000000000000      |         SS0           |
 |------------------------------------------------|
 |                      ESP0                      |
 |------------------------------------------------|
 |  0000000000000000      |Компоновка задач       |
 |                        |(старый селектор TSS)  |
 --------------------------------------------------
 
 Адреса показаны в шестнадцатиричном формате
 ПРИМЕЧАНИЕ: Биты, помеченные как 0, резервируются. Не используйте
 их.
              Рисунок 7-1. Сегмент состояния задачи
 
 Бит "Занят" в поле Типа указывает на то, что задача занята.
 Занятой задачей называется текущая выполняемая или ожидающая
 выполнения задача. Поле Типа со значением 9 указывает на
 не-активную задачу; значение 11 (десятичное) указывает на
 занятую задачу. Задачи не-реентерабельны. Процессор i486
 использует бит Занятости для обнаружения попыток вызова задачи,
 выполнение которой прервано.
 
                        Дескриптор TSS
 
                2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 31             4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7            0
 ---------------------------------------------------------------
 |               | | | |A|      | | D | |       |              |
 | BASE  31:24   |G|D|0|V|LIMIT |P| P | | TYPE  |  BASE 23:16  |+4
 |               | | | |L|19:16 | | L |0|1|1|B|1|              |
 |-------------------------------------------------------------|
 |      Базовый адрес 15:00     |    Граница сегмента 15:00    |+0
 ---------------------------------------------------------------
 
 AVL       Доступно для использования системным программным
           обеспечением
 B         Бит "Занятости"
 BASE      Базовый адрес сегмента
 DPL       Уровень привилегированности дескриптора
 G         Грануляция
 Граница   Граница сегмента
 P         Присутствие сегмента
 TYPE      Тип сегмента
 
      Рисунок 7-2. Дескриптор TSS
 
 Поля Базового адреса сегмента, Границы и DPL, а также биты
 Грануляции и Присутствия выполняют функции, аналогичные тем, что
 были у них в дескрипторах сегментов данных. Поле Границы должно
 иметь значение, равное или больше чем 67H, на один байт меньше
 минимального размера сегмента состояния задачи. Попытка
 выполнить переключение на задачу, дескриптор TSS которой имеет
 границу меньше чем 67H, генерирует исключение. При использовании
 битового массива разрешения ввода/вывода требуется большее
 значение Границы. Большее значение Границы может также
 понадобиться для самой операционной системы, если система хранит
 в TSS дополнительные данные.
 
 Процедура с доступом к дескриптору TSS может вызвать
 переключение задачи. В большинстве систем поля DPL дескрипторов
 TSS должны быть очищены, чтобы только привилегированное
 программное обеспечение могло выполнить переключение задачи.
 
 Доступ к дескриптору TSS не дает процедуре возможности читать
 или модифицировать дескриптор. Чтение и модификация его возможны
 только путем отображения в тот же адрес памяти дескриптора
 данных. Загрузка дескриптора TSS в сегментный регистр вызывает
 исключение. Дескрипторы TSS могут находиться только в таблице
 GDT. Попытка доступа к TSS при помощи селектора с установленным
 битом TI (который обозначает текущую LDT) генерирует исключение.
 
 7.3  Регистр задачи
 -----------------------------------------------------------------
 
 Регистр задачи (TR) используется для поиска текущего TSS. На
 Рисунке 7-3 показан путь, по которому процессор выполняет доступ
 к TSS.
 
 
 Сегмент состояния задачи    -----
 --------------------- <-----| + |<------------------
 |                   |       -----                   |
 |                   |         ^                     |
 |                   |         |                     |
 |                   |         |                     |
 |                   |         |                     |
 |                   |         |                     |
 |                   |         |                     |
 |                   |         |                     |
 |                   |         |                     |
 ---------------------         |                     |
                               |                     |
    Видимая часть              |  Невидимая часть    |
 ---------------------------------------------------------------
 |   Селектор        |  Базовый адрес     | Граница сегмента   |TR
 ---------------------------------------------------------------
        |                     ^                     ^
        |                     |                     |
        |                      ----------------     |
        |                                      |    |
        |                                      |    |
        |              Глобальная              |    |
        |        таблица дескрипторов          |    |
        |       ------------------------       |    |
        |       |           |          | N     |    |
        |       |----------------------|       |    |
        |       |                      |       |    |
        |       |----------------------|       |    |
        |       |           |          |       |    |
        |       |----------------------|       |    |
        |       |                      |       |    |
        |       |----------------------|       |    |
        |       |           |          |       |    |
        |       |----------------------|       |    |
        |       |                      |       |    |
        |       |----------------------|       |    |
        |       |                      |-------     |
         ------>|     Дескриптор TSS   |            |
                |                      |------------
                |----------------------|
                |           |          |
                |----------------------|
                |                      |
                |----------------------|
                |           |          |
                |----------------------|
                |                      |
                |----------------------|
                |           |          |
                |----------------------|
                |                      |
                |----------------------|
                |           |          |
                |----------------------|
                |                      | 0
                ------------------------
 
                     Рисунок 7-3. Регистр TR
 
 Регистр задачи имеет "видимую" часть (т.е. часть, которую может
 считывать и изменять программное обеспечение) и "невидимую"
 часть (т.е. часть, обслуживаемую процессором и недоступную
 программному обеспечению). Селектор, находящийся в видимой
 части, индексирует дескриптор TSS в GDT. Процессор использует
 невидимую часть регистра TR для приема туда значений базы и
 границы из дескриптора TSS. Хранение в регистре этих значений
 делает выполнение задачи более эффективным, поскольку для ссылки
 к TSS текущей задачи процессору не требуется извлекать эти
 значения из памяти.
 
 Команды LTR и STR используются для модификации и чтения видимой
 части регистра задачи. Обе эти команды принимают один операнд, а
 именно 16-разрядный селектор сегмента, расположенный в памяти
 или в регистре общего назначения.
 
 LTR (Загрузить регистр задачи) загружает в видимую часть
 регистра задачи операнд, который должен индексировать позицию
 дескриптора TSS в GDT. Команда LDT также загружает в невидимую
 часть информацию из дескриптора TSS. Команда LTR является
 привилегированной командой: она может быть выполнена только при
 CPL равном 0. Команда LTR обычно используется во время
 инициализации системы для помещения в регистр задачи исходного
 значения: далее содержимое регистра TR изменяется событиями,
 вызывающими переключение задачи.
 
 STR (Сохранить регистр задачи) записывает видимую часть регистра
 задачи в регистр общего назначения или в память. Команда STR не
 является привилегированной командой.
 
 7.4  Дескриптор шлюза задачи
 -----------------------------------------------------------------
 
 Дескриптор шлюза задачи обеспечивает косвенные, защищенные
 ссылки к задаче. Формат шлюза задачи показан на Рисунке 7-4.
 
 Поле Селектор шлюза задачи индексирует дескриптор TSS. RPL в
 данном селекторе не используется.
 
 DPL шлюза задачи управляет доступом к дескриптору для
 переключения задачи. Процедура не может выбрать дескриптор шлюза
 задачи до тех пор, пока RPL селектора и CPL процедуры не будут
 численно меньше или равны DPL дескриптора. Тем самым
 предотвращается переключение задачи менее привилегированными,
 чем она сама, процедурами. (Отметим, что при использовании шлюза
 задачи DPL дескриптора TSS назначения не используется).
 
 
                     Дескриптор шлюза задачи
 
                                1 1 1 1 1 1 1
 31                             6 5 4 3 2 1 0 9 8 7            0
 ---------------------------------------------------------------
 |                              | | D |         |              |
 |        Резервируется         |P| P |0 0 1 0 1| Резервируется|+4
 |                              | | L |         |              |
 |-------------------------------------------------------------|
 |      Селектор сегмента TSS   |       Резервируется          |+0
 ---------------------------------------------------------------
 
 DPL       Уровень привилегированности дескриптора
 P         Присутствие сегмента
 
               Рисунок 7-4. Дескриптор шлюза задачи
 
 Процедура с доступом к шлюзу задачи может вызвать переключение
 задачи, как и процедура с доступом к дескриптору TSS. Как шлюзы
 задачи, так и дескрипторы TSS предназначены для решения
 следующих вопросов:
 
 1. Необходимость иметь для задач только один бит Занятости.
    Поскольку этот бит хранится в дескрипторе TSS, каждая задача
    должна иметь только один такой дескриптор. Однако, может
    существовать несколько шлюзов задачи, выбирающих один
    дескриптор TSS.
 
 2. Необходимость обеспечить селективный доступ к задачам. Шлюзы
    задачи позволяют решить эту проблему, поскольку они могут
    размещаться в LDT и иметь DPL, отличный от DPL дескриптора
    TSS. Процедура, недостаточно привилегированная для
    использования дескриптора TSS в GDT (который обычно имеет
    DPL, равный 0), может тем не менее вызвать другую задачу,
    если она имеет доступ к шлюзу задачи в LDT. Благодаря шлюзам
    задачи операционная система может ограничить переключение
    задач конкретными задачами.
 
 3. Необходимость выполнения переключения задачи в случае
    прерывания или особой ситуации. Если прерывание или
    исключение передает в шлюз задачи вектор, процессор i486
    выполняет переключение на указанную задачу.
 
 На Рисунке 7-5 показано, как шлюз задачи в LDT и шлюз задачи в
 IDT могут идентифицировать одну и ту же задачу.
 
 7.5  Переключение задачи
 -----------------------------------------------------------------
 
 Процессор i486 передает управление другой задаче в одном из
 следующих четырех случаев:
 
 1. Текущая задача выполняет команду JMP или CALL для дескриптора
    TSS.
 
 2. Текущая задача выполняет команду JMP или CALL для шлюза
    задачи.
 
 3. Прерывание или исключение индексирует шлюз задачи в IDT.
 
 4. Текущая задача выполняет команду IRET при установленном флаге
    NT.
 
 Команды JMP, CALL и RET, равно как прерывания и исключения,
 представляют собой обычные механизмы процессора i486, которые
 могут быть использованы и при обстоятельствах, не приводящих к
 переключению задачи. Тип дескриптора (при вызове задачи) или
 флаг NT (при возврате из задачи) определяют разницу между
 стандартным механизмом и его формой, вызывающей переключение
 задачи.
 
 Для того, чтобы произошло переключение задачи, команда JMP или
 CALL может передать управление либо дескриптору TSS, либо шлюзу
 задачи. Эффект в обоих случаях одинаковый: процессор i486
 передает управление требуемой задаче.
 
 Исключение или прерывание вызывают переключение задачи,
 индексируя шлюз задачи в IDT. Если они индексируют в IDT шлюз
 прерывания или шлюз ловушки, то переключения задачи не
 происходит. Более подробную информацию о механизме прерываний
 см. в Главе 9.
 
 
                                                Сегмент
                                                состояния задачи
                                                -----------------
 Локальная                Глобальная            |               |
 таблица дескрипторов     таблица дескрипторов  |               |
 -----------------        -----------------     |               |
 |       |       |        |       |       |     |               |
 |---------------|        |---------------|     |               |
 |               |        |               |     |               |
 |---------------|        |---------------|     |               |
 |       |       |        |       |       |     |               |
 |---------------|        |---------------|     |               |
 |               |        |               |     |               |
 |---------------|        |---------------|     |               |
 |       |       |------->|       |       |     |               |
 |- Шлюз задачи -|      ->|Дескриптор TSS |---->-----------------
 |---------------|     |  |---------------|
 |       |       |     |  |       |       |
 |---------------|     |  |---------------|
 |               |     |  |               |
 |---------------|     |  |---------------|
 |       |       |     |  |       |       |
 |---------------|     |  |---------------|
 |               |     |  |               |
 |---------------|     |  |---------------|
 |       |       |     |  |       |       |
 |---------------|     |  |---------------|
 |               |     |  |               |
 -----------------     |  -----------------
                       |
                       |
                       |
                       |
 Таблица дескрипторов  |
 прерываний            |
 -----------------     |
 |       |       |     |
 |---------------|     |
 |               |     |
 |---------------|     |
 |       |       |     |
 |---------------|     |
 |               |     |
 |---------------|     |
 |       |       |     |
 |-Шлюз задачи --|-----
 |---------------|
 |       |       |
 |---------------|
 |               |
 |---------------|
 |       |       |
 |---------------|
 |               |
 |---------------|
 |       |       |
 |---------------|
 |               |
 -----------------
 
         Рисунок 7-5. Задачи со ссылками на шлюзы задачи
 
 Подпрограмма обслуживания прерывания всегда возвращает
 выполнение в прерванную процедуру, которая может находиться в
 другой задаче. Если флаг NT очищен, происходит нормальный
 возврат. Если флаг NT установлен, происходит переключение
 задачи. Задача, принимающая переключение, задается селектором
 TSS в TSS подпрограммы обслуживания прерывания.
 
      Переключение задачи имеет следующие этапы:
 
 1. Проверка того, что текущей задаче разрешено выполнить
    переключение на другую задачу. К командам JMP и CALL
    применимы правила привилегированности доступа к данным. DPL
    дескриптора TSS и шлюза задачи должен быть больше чем или
    равен одновременно CPL и RPL селектора шлюза. исключения,
    прерывания и команды IRET имеют право переключать задачу
    независимо от DPL шлюза задачи или дескриптора TSS
    назначения.
 
 2. Проверка того, что дескриптор TSS новой задачи помечен как
    присутствующий и имеет допустимую границу (превышающую или
    равную 67H). Любые случившиеся до этой точки ошибки
    принадлежат контексту текущей задачи. При попытке выполнить
    приводящую к ошибке команду эти ошибки восстанавливают любые
    изменения состояния процессора. Благодаря этому адрес
    возврата для обработчика прерываний указывает на команду,
    вызвавшую ошибку, а не на команду, следующую за ней.
    Обработчик исключений может зафиксировать условие, вызвавшее
    ошибку, и выполнить рестарт задачи. Вмешательство обработчика
    исключений может быть полностью прозрачно для прикладной
    программы.
 
 3. Сохранение состояния текущей задачи. Процессор находит
    базовый адрес текущего TSS в регистре задачи. Регистры
    процессора копируются в текущий TSS (регистры EAX, ECX, EDX,
    EBX, ESP, EBP, ESI, EDI, ES, CS, SS, DS, FS, GS и EFLAGS).
 
 4. Загрузка в регистр TR селектора для дескриптора TSS новой
    задачи, установка бита Занятости новой задачи и установка
    бита TS в регистре CR0. Селектор либо является операндом
    команды JMP или CALL, либо берется из шлюза задачи.
 
 5. Загрузка состояния новой задачи из ее TSS и продолжение ее
    выполнения. При этом загружаются регистры LDTR, EFLAGS,
    регистры общего назначения EIP, EAX, ECX, EDX, EBX, ESP, EBP,
    ESI, EDI, а также сегментные регистры Es, CS, SS, DS, FS и
    GS. Любые ошибки, обнаруживаемые на этом шаге, принадлежат к
    контексту новой задачи. С точки зрения обработчика исключений
    первая команда новой задачи не является выполненной.
 
 Отметим, что состояние старой задачи при переключении задачи
 всегда сохраняется. При возобновлении этой задачи выполнение ее
 продолжается с той команды, которая была бы выполнена следующей
 при обычной работе. Регистры восстанавливаются в те значения,
 которые они имели к моменту останова задачи для переключения.
 
 Каждое переключение задачи устанавливает бит TS (Задача
 Переключена) регистра CR0. Бит TS полезен системным программам
 для координации работы целочисленного блока и блока операций с
 плавающей точкой или сопроцессора. Бит TS указывает на то, что
 содержимое блока операций с плавающей точкой или сопроцессора
 может отличиться от соответствующего содержимого для текущей
 задачи. В главе 10 бит TS и сопроцессоры рассматриваются более
 подробно.
 
 Подпрограммы обслуживания исключений, вызванных переключением
 задачи (исключения вследствие шагов 5 - 17 в таблице 7-1)
 могут начать вызываться рекурсивно в случае попытки
 перезагрузить селектор сегмента, сгенерировавшего данное
 исключение. Причина исключения (или одна из нескольких
 причин) до повторения загрузки сегмента должна быть
 зафиксирована.
 
 Уровень привилегированности, с которым выполнялась старая
 задача, не имеет отношения к уровню привилегированности новой
 задачи. Поскольку задачи изолированы друг от друга благодаря
 отдельным адресным пространствам и сегментам состояния задачи, и
 поскольку доступ к TSS выполняется по правилам
 привилегированности, переключение задачи не требует никаких
 проверок привилегированности. Новая задача начинает выполняться
 с уровнем привилегированности, указанным в RPL нового
 содержимого регистра CS, загружаемого из TSS.
 
 Проверки, выполняемые при переключении задачи         Таблица 7-1
 -----------------------------------------------------------------
 Шаг  Проверяемое условие               Особая  1)   Ссылка
                                        ситуация     на код ошибки
 -----------------------------------------------------------------
  1   Дескриптор TSS присутствует         NP      TSS новой задачи
      в памяти
 
  2   Дескриптор TSS не Занят             GP      TSS новой задачи
 
  3   Граница сегмента TSS больше чем     TS      TSS новой задачи
      или равна 103
 -----------------------------------------------------------------
  4   Загрузка регистров из значений, хранимых в TSS
 -----------------------------------------------------------------
  5   Допустимость селектора LDT          TS      TSS новой задачи
      новой задачи
 
  6   DPL кодового сегмента               TS    Новый сегмент кода
      соответствует RPL селектора
                                2)
  7   Допустимость селектора SS           GP   Новый сегмент стека
 
  8   Сегмент стека присутствует в памяти SF   Новый сегмент стека
 
  9   DPL сегмента стека                  SF   Новый сегмент стека
      соответствует CPL
 
 10   LDT новой задачи присутствует       TS      TSS новой задачи
      в памяти
                                2)
 11   Допустимость селектора CS           TS    Новый сегмент кода
 
 12   Сегмент кода присутствует           NP    Новый сегмент кода
      в памяти
 
 13   DPL сегмента стека                  GP   Новый сегмент стека
      соответствует RPL селектора
 
 14   Допустимость селекторов             GP  Новый сегмент данных
      DS,ES,FS и GS             2)
 
 15   Сегменты DS,ES,FS и GS доступны     GP  Новый сегмент данных
      для чтения
 
 16   Сегменты DS,ES,FS и GS              NP  Новый сегмент данных
      присутствуют в памяти
 
 17   DPL сегментов DS,ES,FS и GS         GP  Новый сегмент данных
      больше или равен CPL (если эти
      сегменты не являются конформными)
 -----------------------------------------------------------------
 
 Примечание: Следующие процессоры Intel могут использовать другой
 порядок проверок.
 
      1. NP = исключение "Сегмент не присутствует"; GP=
         исключение общей защиты; TS= исключение "Неверный TSS";
         SF=исключение "Сбой в стеке".
      2. Селектор является допустимым, если он находится в таблице
         совместимого типа (например, селектор LDT не может
         находиться ни в одной таблице, кроме GDT), занимает
         адрес в пределах границы табличного сегмента и ссылается
         на совместимый тип дескриптора (например, селектор в
         регистре CS является допустимым только в том случае,
         если он индексирует дескриптор кодового сегмента; тип
         дескриптора задается в его поле Типа).
 
 7.6  Компоновка задач
 -----------------------------------------------------------------
 
 Для возврата выполнения на предыдущую задачу используются поле
 Компоновки в TSS и флаг NT. Флаг NT указывает на то, является ли
 текущая выполняемая задача вложенной в выполнение другой задачи,
 а поле Компоновки в TSS текущей задачи содержит селектор TSS для
 задачи более старшего уровня, если таковая имеется (см. Рисунок
 7-6).
 
 Когда прерывание, исключение, переход или вызов вызывают
 переключение задачи, процессор i486 копирует селектор сегмента
 состояния текущей задачи в TSS для новой задачи и устанавливает
 флаг NT. Флаг NT указывает на то, что поле Компоновки TSS было
 загружено селектором сохраненного TSS. Новая задача возвращает
 управление командой IRET. При выполнении команды IRET происходит
 проверка флага NT. Если он установлен, то процессор выполняет
 переключение на предыдущую задачу. В Таблице 7-2 показано
 использование полей TSS, на которые воздействует переключение
 задачи.
 
 Отметим, что флаг NT может быть модифицирован программным
 обеспечением, выполняемым на любом уровне привилегированности.
 Программа может установить свой бит NT и выполнить команду IRET,
 что будет иметь эффект запуска задачи, заданной в поле
 Компоновки TSS текущей задачи. Для предотвращения
 непредусмотренных переключений задачи операционная система
 должна инициализировать поле Компоновки каждого создаваемого ей
 TSS.
 
 
   Задача        Вложенная     Задача самого   Текущая
   старшего      задача        глубокого       выполняемая
   уровня                      уровня          задача
                               вложенности
 
    TSS             TSS            TSS           EFLAGS
 ------------   ------------   ------------   ------------
 |          |   |          |   |          |   |   NT=1   |
 |          |   |          |   |          |   ------------
 |          |   |          |   |          |
 |  NT=0    |   |  NT=0    |   |  NT=0    |
 |          |   |          |   |          |
 |          |   |          |   |          |
 |          |   |          |   |          |
 |     -----|   |     -----|   |     -----|   ------------
 |     |LINK|   |     |LINK|   |     |LINK|   |Регистр TR|
 ------------   ------------   ------------   ------------
             \           |  \          |   \        |
              \__________|   \_________|    \_______|
 
 LINK = Поле Компоновки задач
 
                  Рисунок 7-6.  Вложенные задачи
 
           Таблица 7-2. Воздействие переключения задачи
                на поля Занятости, NT и Компоновки
 -----------------------------------------------------------------
   Поле         Воздействие JUMP   Воздействие        Воздействие
                                   команды CALL       команды IRET
                                   или прерывания
 -----------------------------------------------------------------
 Бит Занятости  Бит установлен.    Бит установлен.    Изменений нет
 новой задачи   Перед этим должен  Перед этим должен  Должен быть
                быть очищен        быть очищен        установлен
 
 Бит Занятости  Бит очищен         Изменений нет.     Бит очищен
 старой задачи                     В текущий момент
                                   бит установлен
 
 Флаг NT        Флаг очищен        Флаг установлен    Изменений нет
 новой задачи
 
 Флаг NT        Изменений нет      Изменений нет      Флаг очищен
 старой задачи
 
 Поле           Изменений нет      Загружено          Изменений нет
 Компоновки                        селектором для TSS
 новой задачи                      старой задачи
 
 Поле           Изменений нет      Изменений нет      Изменений нет
 Компоновки
 старой задачи
 -----------------------------------------------------------------
 
 7.6.1  Бит Занятости предотврашает зацикливание
 -----------------------------------------------------------------
 
 Бит Занятости дескриптора TSS предотвращает реентерабельные
 переключения задач. Существует лишь один сохраненный контекст
 каждой задачи, а именно контекст, сохраненный в TSS,
 следовательно, задача до своего завершения может быть вызвана
 только один раз. Цепочка отложенных задач может вырасти до любой
 длины вследствие множественных прерываний, исключений, переходов
 и вызовов. Бит Занятости предотвращает вызов задачи,
 поставленной в такую цепочку. Реентерабельное же переключение
 задачи затрет старый TSS задачи, что приведет к разрушению всей
 цепочки.
 
 Процессор организует бит Занятости следующим образом:
 
 1. При переключении задачи процессор устанавливает бит Занятости
    новой задачи.
 
 2. При обратном переключении из задачи процессор очищает бит
    занятости старой задачи, если эта задача не должна быть
    поставлена в цепочку (т.е. команда, вызвавшая переключение
    задачи, это команда JMP или IRET). Если задача поставлена в
    цепочку, то ее бит Занятости остается установленным.
 
 3. При переключении на задачу процессор генерирует исключение
    общей защиты, если бит Занятости новой задачи оказывается уже
    установленным.
 
 Таким образом, процессор предотвращает переключение задачи самой
 на себя, либо на любую задачу в цепочке задач, что исключает
 реентерабельное переключение задачи.
 
 Бит Занятости может использоваться в многопроцессорной
 конфигурации системы, поскольку при установке или очистке бита
 Занятости процессор захватывает шину. Это исключает
 одновременный запуск одной и той же задачи двумя процессорами.
 (Более подробную информацию о многопроцессорной обработке см. в
 главе 13).
 
 7.6.2  Модификация компоновки задач
 -----------------------------------------------------------------
 
 Для возобновления выполнения прерванной задачи до выполнения
 прервавшей ее задачи может понадобиться модификация цепочки
 отложенных задач. Надежный способ состоит в следующем:
 
      1. Запретить прерывания.
 
      2. Сначала изменить поле Компоновки TSS задачи прерывания,
         а затем очистить бит Занятости в дескрипторе TSS задачи,
         удаляемой из цепочки.
      3. Снова разрешить прерывания.
 
 7.7  Адресное пространство задачи
 -----------------------------------------------------------------
 
 Для того, чтобы каждая задача имела собственную LDT и
 собственные таблицы страниц, могут быть использованы селектор
 LDT и поле PDBR (в CR3) TSS. Поскольку дескрипторы сегментов в
 LDT представляют собой связки между задачами и сегментами, для
 установки индивидуального управления этими связками для каждой
 задачи могут использоваться отдельные LDT. Доступ к любому
 конкретному сегменту может быть передан любой конкретной задаче
 путем помещения дескриптора этого сегмента в LDT задачи. При
 разрешенном механизме подкачки каждая задача может иметь свой
 собственный набор страничных таблиц для отображения линейных
 адресов в физические.
 
 Задачи могут также иметь общую LDT. Это простой и эффективный по
 затратам памяти способ организации коммуникации между задачами
 или управления одних задач другими, не снимая защитных барьеров
 в системе в целом.
 
 Поскольку все задачи имеют доступ к GDT, также возможно создание
 разделяемых сегментов, доступ к которым будет происходить через
 сегментные дескрипторы из данной таблицы.
 
 7.7.1  Отображение линейного адресного пространства задачи
        в физическое
 -----------------------------------------------------------------
 
 Способы организации отображения линейного адресного пространства
 задачи в физическое делятся на два общих класса:
 
 1. Единое отображение линейного адресного пространства в
    физическое, разделяемое всеми задачами. Если механизм
    подкачки страниц запрещен, то этот способ единственный. Без
    подкачки страниц все линейные адреса отображаются в те же
    физические адреса. При разрешенной подкачке страниц данная
    форма отображения достигается путем использования одного
    каталога страниц для всех задач. Линейное адресное
    пространство может превышать физическое пространство, если
    поддерживается виртуальная память с подкачкой по обращению.
 
 2. Независимое отображение линейного адресного пространства в
    физическое. Эта форма отображения существует при
    использовании собственного каталога страниц для каждой
    задачи. Поскольку PDBR (базовый регистр каталога страниц)
    загружается из TSS при каждом переключении задачи, каждая
    задача может иметь собственный страничный каталог.
 
 Линейные адресные пространства различных задач могут
 отображаться в полностью раздельные физические адреса. Если
 элементы разных страничных каталогов указывают на разные
 страничные таблицы, а эти таблицы указывают на разные страницы
 физической памяти, то такие задачи не разделяют никаких
 физических адресов памяти.
 
 Сегменты состояния задачи должны находиться в пространстве,
 доступном всем задачам, таким образом чтобы отображение адресов
 TSS не изменялось во время чтения или обновления процессором TSS
 при переключении задачи. Линейное пространство, в которое
 отображается GDT, также должно быть разделяемым физическим
 пространством; в противном случае теряется смысл GDT. На Рисунке
 7-7 показано, как линейные пространства двух задач могут
 перекрываться в физическом адресном пространстве при разделении
 ими страничных таблиц.
 
 7.7.2  Логическое адресное пространство задачи
 -----------------------------------------------------------------
 
 Само по себе отображение линейного адресного пространства в
 физическое с перекрытием не позволяет разделение данных
 задачами. Для разделения данных задачи должны также иметь общее
 отображение логического адресного пространства в линейное, т.е.
 они также должны иметь доступ к дескрипторам, указывающим на
 разделяемое линейное адресное пространство. Существует три
 способа создания разделяемого отображения логического адресного
 пространства в физическое:
 
 1. При помощи сегментных дескрипторов в GDT. Все задачи имеют
    доступ к дескрипторам в GDT. Если эти дескрипторы указывают
    на линейное адресное пространство, отображаемое в общее для
    всех задач физическое адресное пространство, то задачи могут
    разделять данные и команды.
 
 2. При помощи разделяемых LDT. Две или более задачи могут
    использовать одну и ту же LDT, если селекторы LDT в их TSS
    для использовании при трансляции адресов выбирают одну и ту
    же LDT. Сегментные дескрипторы в LDT, адресующие линейные
    пространства, отображаемые в перекрывающиеся физическое
    адресное пространство, обеспечивают разделяемую физическую
    память. Этот метод разделения более селективен, чем метод
    организации разделения посредством GDT, поскольку он
    позволяет ограничить разделение конкретными задачами. Прочие
    задачи в системе могут иметь другие LDT, не дающие им доступ
    к разделяемым областям памяти.
 
 3. При помощи сегментных дескрипторов в LDT, отображающихся
    в одно и то же линейное адресное пространство. Если линейное
    адресное пространство отображается в то же самое физическое
    адресное пространство за счет постраничного отображения
    участвующих задач, эти дескрипторы позволяют задачам
    разделение адресного пространства. Такие дескрипторы обычно
    называют "алиасами". Такой метод разделения даже более
    селективен, чем предыдущий: прочие дескрипторы в LDT могут
    указывать на независимые линейные адреса, не являющиеся
    разделяемыми.
 
 
 
                                                     Страничные
     TSS                                               блоки
                                                    -------------
                                                    | Страница  |
                    Каталоги        Таблицы         |  задачи   |
 TSS задачи A       страниц         страниц       ->|     А     |
 ------------     ------------     ------------  |  -------------
 |          |     |          |     |          |  |
 |          |     |----------|     |----------|  |  -------------
 |          |     |          |     | элемент  |--   | Страница  |
 |          |     |----------|     |----------|     |  задачи   |
 |          |     |          |     | элемент  |---->|     A     |
 |----------|     |----------|     |----------|     -------------
 |   PDBR   |---->|  элемент |---->| элемент  |--
 |----------|     |----------|     ------------ |   -------------
 |          |     |  элемент |--                |   | Страница  |
 ------------     ------------  |               --->|  задачи   |
                                |                   |     A     |
                                |  Разделяемые      -------------
                                |  таблицы страниц
                                |  ------------
                                |  |          |
                                |  |----------|     -------------
                                |  |          |     |Разделяемая|
                                |  |----------|     |  страница |
                                |  |  элемент |---->|           |
                                |  |----------|     -------------
                                 ->|  элемент |--
                                 ->------------ |   -------------
 TSS задачи B                   |               |   |Разделяемая|
 ------------     ------------  |               |   |  страница |
 |          |     |          |  |               |   |           |
 |          |     |----------|  |  ------------  -->-------------
 |          |     |          |  |  |          |
 |          |     |----------|  |  |----------|     -------------
 |          |     |          |  |  |          |     | Страница  |
 |----------|     |----------|  |  |----------|     |  задачи   |
 |  PDBR    |---->|  элемент |--   |  элемент |---->|     В     |
 |----------|     |----------|     |----------|     -------------
 |          |     |  злемент |---->|  элемент |--
 ------------     ------------     ------------ |   -------------
    TSS             Каталоги         Таблицы    |   | Страница  |
                    страниц          страниц    |   |  задачи   |
                                                |   |     В     |
                                                 -->-------------
                                                      Страничные
                                                         блоки
 
    Рисунок 7-7. Отображение линейного адресного пространства
                    в физическое с перекрытием
 
 
 
 Глава 8  Ввод/вывод
 -----------------------------------------------------------------
 
 В данной главе рассматривается архитектура ввода/вывода
 процессора i486. Ввод/вывод выполняется через порты
 ввода/вывода, которые представляют собой регистры, подключенные
 к периферийным устройствам. Порт ввода/вывода может быть портом
 ввода, портом вывода, либо двунаправленным портом. Некоторые
 порты используются для переноса данных, например, регистры
 приема и передачи последовательного интерфейса. Другие порты
 ввода/вывода используются для управления периферийными
 устройствами, например, регистры управления контроллером
 дисковода.
 
 Процессор i486 всегда синхронизирует выполнение команд ввода
 /вывода с работой внешней шины. Все предыдущие команды к моменту
 начала операций ввода/вывода завершаются. В частности, прежде
 чем будет выполнен ввод/вывод на чтение или запись, будут
 завершены все отложенные операции записи в буферы записи ЦПУ
 i486.
 
 Архитектура ввода/вывода представляет собой с точки зрения
 программиста модель того, как происходит доступ к портам
 ввода/вывода. В рассмотрение этой модели входят:
 
      - Методы адресации портов ввода/вывода.
      - Команды, выполняющие операции ввода/вывода.
      - Механизм защиты ввода/вывода.
 
 8.1  Адресация ввода/вывода
 -----------------------------------------------------------------
 
 Процессор i486 позволяет адресовать порты ввода/вывода одним из
 следующих способов:
 
 - Через отдельное адресное пространство ввода/вывода, доступ к
   которому выполняется посредством команд ввода/вывода.
 
 - Через ввод/вывод, управляемый памятью, где порты ввода/вывода
   представлены в адресном пространстве физической памяти.
 
 Использование отдельного адресного пространства ввода/вывода
 поддерживается специальными командами и механизмом аппаратной
 поддержки. При использовании пространства ввода/вывода,
 отображенного на памятью, для доступа к портам ввода/вывода
 используется обычный набор команд общего назначения, а защита
 осуществляется при помощи механизма сегментации или подкачки
 страниц. Некоторые разработчики систем могут предпочесть
 использовать средства ввода /вывода, встроенные в процессор,
 тогда как другим больше подходит простота единого физического
 адресного пространства.
 
 Если для защиты адресного пространства ввода/вывода используется
 сегментация или подкачка страниц, то поля AVL в дескрипторах
 сегментов или элементах страничной таблицы позволяют пометить
 страницы, содержащие ввод/вывод, как непереместимые и не
 подлежащие подкачке. Поля AVL предназначены для такого рода
 использования, когда системному программисту требуется расширить
 механизмы трансляции адреса и защиты.
 
 Разработчики аппаратного обеспечения используют эти способы
 отображения портов ввода/вывода в адресном пространстве при
 разработке схем декодирования адресов в системе. Порты
 ввода/вывода могут быть отображены в памяти таким образом, чтобы
 находиться либо в адресном пространстве ввода/вывода, либо в
 адресном пространстве физической памяти (или и там, и там).
 Системным программистам может понадобиться обсудить с
 разработчиками аппаратного обеспечения предпочтительный для них
 тип адресации ввода/вывода.
 
 8.1.1  Адресное пространство ввода/вывода
 -----------------------------------------------------------------
 
 Процессор i486 обеспечивает отдельное адресное пространство
 ввода/вывода, отличное от адресного пространства физической
 памяти, в которое могут быть помещены порты ввода/вывода.
 Адресное пространство ввода/вывода состоит из 2**16 (64К)
 индивидуально адресуемых 8-битовых портов; любые два
 последовательно расположенные 8-битовые порта могут
 рассматриваться как один 16-битовый порт, а любые четыре - как
 один 32-битовый порт. Если порт пересекает границу между двумя
 двойными словами физической памяти, то используются лишние циклы
 шины.
 
 Штырек M/IO# процессора i486 указывает, когда происходит цикл
 шины обращения к адресному пространству ввода/вывода. При
 использовании отдельного адресного пространства ввода/вывода
 ответственность за применение данного сигнала для выбора портов
 ввода/вывода вместо памяти лежит на разработчике аппаратного
 обеспечения. Действительно, использование отдельного адресного
 пространства ввода/вывода упрощает аппаратную конструкцию
 системы, поскольку выбор этих портов может быть выполнен одним
 сигналом: в отличие от других процессоров, здесь не требуется
 декодировать сигналы нескольких проводов шины старшего адреса
 для установки отдельного адресного пространства ввода/вывода.
 
 Программа может задать адрес порта двумя способами. С
 использованием непосредственно задаваемой байтовой константы в
 команде:
 
      - 256 8-битовых портов с нумерацией от 0 до 255.
      - 128 16-битовых портов с нумерацией 0, 2, 4, ... ,252, 254.
      - 64 32-битовых порта с нумерацией 0,4,8, ... , 248,252
 
 Используя значение регистра DX, программа может задать:
 
      - 8-битовые порты с нумерацией от 0 до 65535.
      - 16-битовые порты с нумерацией 0,2,4, ... ,65532,65534.
      - 32-битовые порты с нумерацией 0,4,8, ... ,65528,65532.
 
 Процессор i486 может пересылать по 8, 16 или 32 бита в
 устройство, отображаемое в пространстве ввода/вывода. Подобно
 словам в памяти, 16-битовые порты должны быть выравнены по
 четным адресам, таким образом, чтобы все 16 битов могли быть
 пересланы за один цикл шины. Подобно двойным словам в памяти, 32
 -битовые порты должны быть выравнены по границе адресов, кратным
 четырем. Процессор поддерживает пересылку и к невыравненным
 портам, но тогда происходит уменьшение быстродействия за счет
 лишнего цикла шины.
 
 Команды IN и OUT пересылают данные между регистром и портом в
 адресном пространстве ввода/вывода. Команды INS и OUTS
 пересылают строки данных между адресным пространством памяти и
 портами в адресном пространстве ввода/вывода.
 
 Адеса портов ввода/вывода от 0F8H до 0FFH резервируются для
 внутреннего использования Intel. Не назначайте порты
 ввода/вывода на эти адреса.
 
 Точная последовательность циклов шины при доступе к портам,
 требующим более одного цикла, не определена. Например, команда
 OUT, загружающая невыравненный порт размером в двойное слово в
 адрес памяти 2H, выполняет доступ к слову по адресу 4H раньше,
 чем доступ к слову по адресу 2H. Точная последовательность не
 определена, и не гарантируется ее сохранение следующими
 продуктами Intel.
 
 Если программному обеспечению требуется установить конкретную
 последовательность циклов шины, то она должна быть задана в
 явном виде. Например, для загрузки сначала порта длиной в слово
 по адресу 4H, а затем порта длиной в слово по адресу 2H, нужно
 использовать две команды формата слова вместо одной команды
 формата двойного слова.
 
 Отметим, что хотя процессор i486 автоматически маскирует ошибки
 контроля четности для конкретных типов циклов шины, например,
 для циклов квитирования прерывания, он не маскирует ошибки
 четности для циклов шины обращения к адресному пространству
 ввода/вывода. Программистам нужно знать о таком поведении
 процессора, как о возможном источнике ложных ошибок контроля
 четности.
 
 8.1.2  Ввод/вывод, управляемый памятью
 -----------------------------------------------------------------
 
 Устройства ввода/вывода могут быть отображены в адресном
 пространстве оперативной памяти. Это называется вводом/выводом,
 управляемым памятью. Если устройства реагируют на обращения, как
 обычные компоненты памяти, они могут быть использованы для ввода
 /вывода, управляемого памятью.
 
 Ввод/вывод, управляемый памятью, обеспечивает дополнительную
 гибкость программирования. Для доступа к порту ввода/вывода,
 расположенному в адресном пространстве памяти, могут
 использоваться любые работающие с памятью команды. Например,
 команда MOV позволяет пересылать данные между портом и любым
 регистром. Команды AND, OR и TEST могут использоваться для
 манипулирования отдельными битами в регистрах управления и
 состояния периферийных устройств (см. Рисунок 8-1). Ввод/вывод,
 управляемый памятью, может использовать для адресации портов
 ввода/вывода полный набор команд и режимов адресации памяти.
 
 
      Физическая память
 ---------------------------N
 |                         |
 |       ПЗУ(ROM)          |
 |                         |
 |-------------------------|
 |  Порт ввода/вывода      |
 |-------------------------|
 |  Порт ввода/вывода      |
 |-------------------------|
 |  Порт ввода/вывода      |
 |-------------------------|
 |                         |
 |                         |
 | Оперативная память (RAM)|
 |                         |
 |                         |
 ---------------------------0
 
           Рисунок 8-1. Ввод/вывод, управляемый памятью
 
 Для оптимизации быстродействия ЦПУ i486 в конкретных точно
 определенных обстоятельствах позволяет менять местами
 последовательность и выполнять чтение раньше буферизованной
 записи. (См. Справочное Руководство по аппаратному обеспечению
 процессора i486, где дается более подробное описание работы
 буфера записи). Используя ввод/вывод, управляемый памятью,
 процессор i486 создает возможность выполнения чтения
 ввода/вывода раньше предшествующей команды записи в память. Для
 исключения этой возможности используйте для чтения команду ввода
 /вывода.
 
 Использование команды ввода/вывода для записи в порт может иметь
 свои преимущества в том, что при этом гарантируется, что запись
 будет завершена до начала выполнения следующей команды. Если
 команды ввода / вывода записи используются для управления
 системным программным обеспечением, то такая последовательность
 событий желательна, поскольку она гарантирует, что следующая
 команда будет выполнена в новом состоянии.
 
 При разрешенном кешировании для предотвращения попытки
 кеширования данных ввода/вывода следует использовать либо
 внешнее программное обеспечение, либо механизм подкачки страниц
 (бит PCD в элементе страничной таблицы).
 
 Ввод/вывод, управляемый памятью, как и любые другие ссылки к
 памяти, подлежит контролю и защите доступа. Защита памяти
 рассматривается в Главе 6.
 
 8.2  Команды ввода/вывода
 -----------------------------------------------------------------
 
 Команды ввода/вывода процессора i486 обеспечивают доступ к
 портам ввода/вывода процессора для пересылки данных. Эти команды
 в качестве операнда имеют адрес порта в адресном пространстве
 ввода/вывода. Существует два вида команд ввода/вывода:
 
 1. Команды, выполняющие пересылку отдельного элемента (байта,
    слова или двойного слова) в регистр или из регистра.
 
 2. Команды, пересылающие строки элементов (строки байтов, слов
    или двойных слов), расположенных в памяти. Эти команды
    называются "строковыми командами ввода/вывода", или "блочные
    команды ввода/вывода".
 
 Эти команды во время цикла шины устанавливают низкое состояние
 (логический 0) сигнала M/IO#, указывая внешнему аппаратному
 обеспечению на то, что происходит доступ к адресному
 пространству ввода/вывода. При использовании ввода/вывода,
 управляемого памятью, использовать команды ввода/вывода не имеет
 смысла.
 
 8.2.1  Регистровые команды ввода/вывода
 -----------------------------------------------------------------
 
 Команды ввода/вывода IN и OUT пересылают данные между портами
 ввода/вывода и регистрами EAX (32-разрядный ввод/вывод), AX (16-
 разрядный ввод/вывод) и AL (8-разрядный ввод/вывод). Команды IN
 и OUT адресуют порты ввода/вывода либо напрямую, по адресу
 одного из 256 портов, задаваемому непосредственно в команде,
 либо косвенно, при помощи адреса в регистре DX, позволяющего
 выбрать один из 64К адресов порта. Эти команды синхронизируют
 выполнение программы с работой внешнего аппаратного обеспечения.
 Буферы записи процессора i486 очищаются, а выполнение программы
 откладывается до тех пор, пока не будет получен сигнал
 готовности (ready) последнего цикла шины.
 
 IN (Ввод из порта) пересылает байт, слово или двойное слово из
 порта ввода в регистры AL, AX или EAX. Байтовая команда IN
 пересылает из выбранного порта 8 битов в регистр AL. Команда IN,
 работающая со словами, переносит из порта 16 битов в регистр AX.
 Команда IN, работающая с двойными словами, переносит из порта 32
 бита в регистр EAX.
 
 OUT (Вывод из порта) пересылает байт, слово или двойное слово в
 порт вывода из регистров AL, AX или EAX. Байтовая команда OUT
 пересылает в выбранный порт 8 битов из регистра AL. Команда OUT,
 работающая со словами, переносит в порт 16 битов из регистра AX.
 Команда OUT, работающая с двойными словами, переносит в порт 32
 бита из регистра EAX.
 
 8.2.2  Блочные команды ввода/вывода
 -----------------------------------------------------------------
 
 Команды INS и OUTS пересылают блоки данных между портами
 ввода/вывода и памятью. Блочные команды ввода/вывода используют
 для адресации порта в адресном пространстве ввода/вывода регистр
 DX. Эти команды задают через регистр DX:
 
      - 8-битовые порты с нумерацией от 0 до 65535.
      - 16-битовые порты с нумерацией 0, 2, 4, ... , 65532, 65534.
      - 32-битовые порты с нумерацией 0, 4, 8, ... , 65528, 65532.
 
 Блочные команды ввода/вывода используют для адресации памяти
 либо регистр SI, либо DI. При каждой пересылке регистр SI или DI
 инкрементируется или декрементируется, что определяется флагом
 направления приращений DF.
 
 Будучи использованы с префиксами повторения, команды INS и OUTS
 выполняют операции блочного ввода или вывода. Префикс повторения
 REP модифицирует команды INS и OUTS таким образом, что они
 выполняют пересылку между портом ввода/вывода и оперативной
 памятью блоков данных. Эти блочные команды ввода/вывода являются
 строковыми командами (более подробное описание строковых команд
 см. в Главе 3). Они упрощают программирование и увеличивают
 скорость пересылки данных, исключая необходимость в
 использовании отдельных команд LOOP или промежуточных регистров
 для хранения данных.
 
 Строковые команды ввода/вывода работают со строками байтов, слов
 или двойных слов. После каждой пересылки адрес памяти,
 находящийся в регистрах ESI или EDI, инкрементируется или
 декрементируется на 1 для байтовых операндов, на 2 для
 операндов-слов или на 4 для операндов-двойных слов. Флаг DF
 управляет тем, выполняется ли инкремент (флаг DF очищен) или
 декремент (Флаг DF установлен) регистра.
 
 INS (Ввод строки из порта) пересылает элемент строки байтов,
 слов или двойных слов из порта ввода в оперативную память.
 Команда INSB пересылает байт из выбранного порта в область
 памяти, адресуемую регистрами ES и EDI. Команда INSW пересылает
 слово. Команда INSD пересылает двойное слово. Префикс
 переопределения сегмента для задания альтернативного сегмента
 назначения использоваться не может. В комбинации с префиксом
 повторения REP команда INS реализует циклическое считывание
 порта и помещение считанных данных в последовательно
 расположенные адреса памяти.
 
 OUTS (Вывод строки в порт) пересылает элемент строки байтов,
 слов или двойных слов в порта вывода из оперативной памяти.
 Команда OUTSB пересылает байт в выбранный порта из области памяти,
 адресуемой регистрами ES и EDI. Команда OUTSW пересылает слово.
 Команда OUTSD пересылает двойное слово. Префикс переопределения
 сегмента для задания альтернативного сегмента источника
 использоваться не может. В комбинации с префиксом повторения REP
 команда OUTS реализует циклическое считывание данных в
 последовательно расположенных адресах оперативной памяти и
 запись их в порт вывода.
 
 
 8.3  Защита и ввод/вывод
 -----------------------------------------------------------------
 
 Архитектура ввода/вывода процессора использует два механизма
 защиты:
 
 1. Поле IOPL регистра EFLAGS управляет доступом к командам ввода
    /вывода.
 
 2. Битовый массив разрешения ввода/вывода в сегменте TSS
    управляет доступом к конкретным портам адресного пространства
    ввода/вывода.
 
 Эти механизмы защиты доступны только при использовании
 отдельного адресного пространства ввода/вывода. При
 использовании ввода/вывода, управляемого памятью, защита
 обеспечивается механизмами сегментации или подкачки страниц.
 
 8.3.1  Уровень привилегированности ввода/вывода
 -----------------------------------------------------------------
 
 В системах, использующих защиту ввода/вывода, доступ к командам
 ввода/вывода управляется полем IOPL регистра EFLAGS. Это
 позволяет операционной системе регулировать уровень
 привилегированности, необходимый для выполнения ввода/вывода. В
 случае типичной модели колец защиты доступ к командам
 ввода/вывода обеспечивается уровнями привилегированности 0 и 1.
 Это позводяет операционной системе и драйверам устройств
 выполнять ввод/вывод, но не дает прикладным программам и менее
 привилегированным драйверам устройств возможности доступа к
 адресному пространству ввода/вывода. Прикладные программы могут
 обращаться к вводу/выводу только через операционную систему.
 
 Следующие команды могут выполняться только при условии CPL <=
 IOPL:
 
      IN      - Ввод
      INS     - Ввод строки
      OUT     - Вывод
      OUTS    - Вывод строки
      CLI     - Очистить флаг разрешения прерываний
      STI     - Установить флаг разрешения прерываний
 
 Эти команды называются "чувствительными" командами, поскольку
 они чувствительны к состоянию поля IOPL. В виртуальном режиме
 8086 IOPL не используется; доступ к портам ввода/вывода
 ограничивается только битовым массивом разрешения ввода/вывода
 (см. Главу 23).
 
 Для использования чувствительных команд процедура должна
 выполняться на уровне привилегированности, как минимум равном
 уровню привилегированности, задаваемому полем IOPL. Попытка
 использования чувствительной команды менее привилегированной
 процедурой приводит к исключению общей защиты. Поскольку каждая
 задача имеет свою собственную копию регистра EFLAGS, каждая
 задача может иметь и собственное поле IOPL.
 
 Задача может изменить IOPL только при помощи команды POPF;
 однако, такие изменения являются привилегированными. Никакая
 процедура не может изменить своего IOPL, если она не работает на
 уровне привилегированности 0. Попытка изменения IOPL менее
 привилегированной процедурой не приводит к генерации ислючения;
 IOPL просто остается без изменений.
 
 Команда POPF может также использоваться для изменения состояния
 флага IF (также как и команды CLI и STI); однако, изменение
 флага IF командой POPF также чувствительно к IOPL. Процедура
 может изменить установку флага IF при помощи команды POPF только
 если она сама выполняется с CPL, как минимум равным уровню
 привилегированности IOPL. Попытка менее привилегированной
 процедуры изменить флаг IF не приводит к исключению; флаг IF
 просто остается без изменений.
 
 8.3.2  Битовый массив разрешения ввода/вывода
 -----------------------------------------------------------------
 
 Процессор i486 может генерировать исключение при ссылках к
 конкретным адресам ввода/вывода. Эти адреса задаются битовым
 массивам разрешения ввода/вывода, находящимся в TSS (см.
 Рисунок 8-2). Размер этого массива и его позиция в TSS
 переменны. Процессор находит битовый массив ввода/вывода при
 помощи базового адреса массива ввода/вывода в TSS. Базовый адрес
 представляет собой 16-разрядное смещение в TSS. Это смещение
 задает начало битового массива. Граница TSS является и границей
 размера битового массива разрешения ввода/вывода.
 
 
        Сегмент состояния задачи (TSS)
      -----------------------------------
      |   11111111  |                   |
      |--------------                   |
      |                                 |
      |          Битовый массив         |
      |      разрешения ввода/вывода    |
   -->|                                 |
  |   |---------------------------------|
  |
  |   |---------------------------------|
   ---|  База массива  |                |
      |  ввода/вывода  |                |
      |---------------------------------|
 
      |---------------------------------|
      |                |                |
      |---------------------------------|
      |                |                |
      -----------------------------------
 
      Примечание: базовый адрес битового массива разрешения
      ввода/вывода не должен превышать DFFF (шестнадцатиричное).
 
      За последним байтом битового массива должен  следовать
      байт, в котором все биты установлены.
 
      Рисунок 8-2. Битовый массив разрешения ввода/вывода
 
 Поскольку каждая задача имеет свой собственный TSS, то каждая
 задача имеет и свой собственный битовый массив разрешения ввода/
 вывода. Доступ к конкретным портам ввода/вывода может быть
 определен для конкретных задач.
 
 Если CPL <= IOPL в защищенном режиме, то процессор позволяет
 выполнение операций ввода/вывода. Если CPL > OPL, либо если
 процессор работает в виртуальном режиме 8086, то процессор
 проверяет битовый массив разрешения ввода/вывода. Каждый бит в
 этом массиве соответствует одному адресу байта ввода/вывода;
 например, управляющий бит для адреса 41 (десятичного) в адресном
 пространстве ввода/вывода будет находиться в позиции 1 шестого
 байта битового массива. Процессор проверяет все биты,
 соответствующие порту ввода/вывода, к которому выполняется
 доступ; например, операция с размером операнда в двойное слово
 проверяет четыре бита, соответствующих четырем смежным адресам
 байтов адресуемого двойного слова. Если хоть один из проверяемых
 битов установлен, то генерируется исключение общей защиты. Если
 же все проверяемые биты очищены, то операция ввода/вывода
 продолжается.
 
 Поскольку допускается существование портов ввода/вывода, не
 выравненных по границе слова или двойного слова, процессору
 может понадобиться при проверке разрешения ввода/вывода доступ к
 двум байтам битового массива. Для максимального быстродействия
 Процессор устроен таким образом, что при каждом доступе к порту
 ввода/вывода прочитывается два байта массива. Для предотвращения
 генерации исключений при доступе к самым старшим адресам портов
 после битового массива находится лишний байт. Все биты этого
 байта должны быть установлены, и он должен лежать в пределах
 границы сегмента.
 
 Битовый массив ввода/вывода не обязан представлять все адреса
 ввода/вывода. Адреса ввода/вывода, не отображаемые в массиве,
 рассматриваются, как если бы соответствующие им биты массива
 были установлены. Например, если граница сегмента TSS находится
 в 10 байтах после базового адреса битового массива, то этот
 массив имеет 11 байтов, отображающих 80 портов ввода/вывода.
 Более старшие адреса при обращении к адресному пространству
 ввода /вывода приведут к генерации исключения.
 
 Если базовый адрес битового массива ввода/вывода больше или
 равен границе сегмента TSS, то битового массива разрешения ввода
 /вывода не существует, и все команды ввода/вывода будут
 генерировать исключение. Базовый адрес должен быть меньше или
 равен 0DFFFH.
 
 
 
 Глава 9   Исключения и прерывания
 -----------------------------------------------------------------
 
 Исключения (особые ситуации) и прерывания представляют собой
 принудительную передачу управления задаче или процедуре. Такая
 задача или процедура называется обработчиком. Прерывания
 происходят в произвольные моменты времени выполнения программы в
 ответ на сигналы аппаратного обеспечения. Исключения
 происходят вследствие выполнения команд, приводящих к этим
 исключениям. Обычно обслуживание прерываний и исключений
 выполняется способом, прозрачным для прикладных программ.
 Прерывания используются для обработки событий, являющихся
 внешними по отношению к процессору, таких как запросы на
 обслуживание периферийных устройств. Исключения обслуживают
 условия, обнаруживаемые процессором во время выполнения команд,
 например деление на 0.
 
 Существует два источника прерываний и два источника исключений:
 
 1. Приерывания
 
      - Маскируемые прерывания, получаемые на входе INTR
        процессора i486. Маскируемые прерывания не происходят до
        тех пор, пока не будет установлен флаг разрешения
        прерываний (IF).
 
      - Немаскируемые прерывания, получаемые на вход NMI
        (Не-Маскируемое Прерывание) процессора. Процессор не
        обеспечивает механизма отключения немаскируемых
        прерываний.
 
 2. Исключения
 
      - Исключения, обнаруживаемые процессором. Далее они
        классифицируются как сбой, ловушка или аварийное
        завершение.
 
 3. Программируемые исключения. Команды INTO, INT 3, INT n и
    BOUND могут служить программными переключателями исключений.
    Эти команды часто называют "программными прерываниями", но
    они обрабатываюся процессором как исключения.
 
 В данной главе рассматриваются средства процессора i486,
 позволяющие управлять и отвечать на прерывания.
 
 9.1  Векторы исключений и прерываний
 -----------------------------------------------------------------
 
 Процессор ассоциирует с каждым отдельным типом прерывания или
 исключением идентифицирующий его номер, называемый вектором.
 
 Немаскируемым (NMI) прерываниям и исключениям присвоены векторы
 в диапазоне от 0 до 31. Не все из этих векторов используются
 процессором в настоящее время; неназначенные векторы из этого
 диапазона резервируются для возможного использования в будущем.
 Использовать неназначенные векторы не следует.
 
 Векторы маскируемых прерываний определяются аппаратно.
 Контроллеры внешних прерываний (например, Intel 8259,
 программируемый Контроллер Прерываний) передают вектор на шину
 процессора i486 во время цикла квитирования прерывания.
 Использоваться могут любые векторы в диапазоне значений от 32 до
 255. Назначения векторов исключений и прерываний показаны в
 Таблице 1-9.
 
           Таблица 9-1. Векторы исключений и прерываний
 
 -----------------------------------------------------------------
   Номер вектора                        Описание
 -----------------------------------------------------------------
      0                  Ошибка деления
      1                  Отладочное исключение
      2                  Немаскируемое (NMI) прерывание
      3                  Точка останова (контрольная точка)
      4                  Переполнение, обнаруженное командой INTO
      5                  Превышение диапазона команды BOUND
      6                  Неверный код операции
      7                  Устройство не доступно
      8                  Двойной сбой
      9                  (Резервировано Intel. Не используйте.
                          ЦПУ i486 не используется)
     10                  Неверный сегмент состояния задачи
     11                  Сегмент не присутствует
     12                  Сбой в стеке
     13                  Общая защита
     14                  Сбой в странице
     15                  (Резервировано Intel. Не используйте)
     16                  Ошибка операции с плавающей точкой
     17                  Проверка выравнивания
    18-31                (Резервировано Intel. Не используйте)
   32-255                Маскируемые прерывания
 -----------------------------------------------------------------
 
 Исключения классифицируются как сбои (отказы), ловушки и
 аварийные завершения, в зависимости о том, как выдается
 сообщение о том, что они произошли, и от того, поддерживается ли
 возможность рестарта вызвавшей их команды.
 
 Сбои (отказ) - Сбой это исключение, сообщение о которой
 выдается на границе команды, предшествующей команде, вызвавшей
 это исключение. После сообщения о сбое машина восстанавливается
 в ситуацию, позволяющую выполнить рестарт команды. Адрес
 возврата для обработчика сбоя указывает на команду,
 сгенерировавшую данный сбой, а не на команду, следующую за ней.
 
 Ловушки - Ловушка это исключение, сообщение о которой выдается
 на границе команды, непосредственно расположенной после команды,
 для которой было обнаружено данное исключение.
 
 Аварийные завершения - Аварийное завершение это исключение, не
 всегда сообщающая адрес команды, вызвавшей данное исключение, и
 не всегда позволяющая рестарт программы, вызвавшей данное
 исключение. Аварийные завершения используются для сообщения о
 тяжелых ошибках, например аппаратных ошибках, или противоречивых
 или недопустимых значениях в системных таблицах.
 
 9.2  Рестарт команды
 -----------------------------------------------------------------
 
 Для большей части исключений и прерываний передача управления не
 происходит до конца текущей команды. Тем самым регистр EIP
 устанавливается таким образом, чтобы указывать на команду,
 следующую за командой, которая выполнялась в момент генерации
 исключения или прерывания. Если эта команда имеет префикс
 повторения, то передача управления происходит в конце текущей
 итерации, причем все регистры будут находиться в состоячнии для
 выполнения следующей итерации. Однако, если данная ситуация
 относится по типу к сбоям, то регистры процессора
 восстанавливаются в состояние, предшествующее выполнению
 вызвавшей сбой команды. Тем самым допускается рестарт команды.
 
 Рестарт команды используется для обработки исключений,
 блокирующих доступ к операндам. Например, прикладная программа
 могла обратиться к данным в сегменте, не присутствующем в
 памяти. В случае такого исключения обработчик исключения должен
 загрузить отсутствующий нужный сегмент (возможно, с жесткого
 диска) и возобновить выполнение, начиная с команды, вызвавшей
 данное исключение. Во время исключения команда могла изменить
 содержимое некоторых регистров процессора. При считывании
 командой значения из стека необходимо восстановить прежнее
 значение указателя стека. Все эти восстановительные операции
 выполняются процессором способом, совершенно прозрачным для
 прикладной программы.
 
 В случае сбоя регистр EIP восстанавливается таким образом, чтобы
 указывать на каманду, вызвавшую исключение. При возврате из
 обработчика исключений выполнение программы продолжается с этой
 же команды.
 
 9.3  Разрешение и запрещение прерываний
 -----------------------------------------------------------------
 
 Некоторые условия и установки флагов приводят к тому, что
 процессор запрещает определенные виды прерываний и исключений.
 
 9.3.1  Немаскируемые прерывания, маскирующие последующие NMI
 -----------------------------------------------------------------
 
 При выполнении обработчика прерываний NMI процессор запрещает
 дополнительные вызовы процедуры или задачи, обрабатывающей
 прерывание, до выполнения следующей команды IRET. Это
 предотвращает помещение в стек вызовов обработчиков прерываний.
 Рекомендуется использовать для немаскируемых прерываний шлюзов
 прерываний, что позволяет запретить вложенные маскируемые
 прерывания, поскольку команда IRET из обработчика маскируемого
 прерывания снова разрешит NMI.
 
 9.3.2  IF маскирует INTR
 -----------------------------------------------------------------
 
 Флаг IF может запретить обслуживание прерываний, полученных на
 штырек INTR процессора. Если флаг IF очищен, прерывания INTR
 игнорируются; если же флаг IF установлен, то прерывания INTR
 обслуживаются. Как и для прочих флаговых битов, процессор
 очищает флаг IF в ответ на сигнал RESET. Команды STI и CLI
 позволяют устанавливать и очищать флаг IF, соответственно.
 
 CLI (Очистить флаг разрешения прерываний) и STI (Установить флаг
 разрешения прерываний) приводят в соответствующее состояние флаг
 IF (бит 9 регистра EFLAGS). Эти команды могут выполняться только
 если CPL равен или имеет более привилегированный уровень, нежели
 IOPL. При попытке выполнения этих команд с менее
 привилегированным уровнем генерируется исключение общей защиты.
 
 Флаг IF зависит также от следующих операций:
 
 - Команда PUSHF записывает все флаги в стек, где их можно
   исследовать и модифицировать. Для обратной загрузки
   модифицированных флагов назад в EFLAGS служит команда POPF.
 
 - Переключения задачи, а также команды POPF и IRET загружают
   регистр EFLAGS, следовательно, они также могут служить для
   модификации состояния флага IF.
 
 - Прерывания, выполняемые через шлюзы прерываний, автоматически
   очищают флаг IF, что запрещает прерывания. (Шлюзы прерывания
   рассматриваются ниже в данной главе).
 
 9.3.3  RF маскирует отладочные сбои
 -----------------------------------------------------------------
 
 Флаг RF в регистре EFLAGS может использоваться для запрещения
 обслуживания отладочных сбоев. Если он очищен, то отладочные
 сбои обслуживаются; если же он установлен, то они игнорируются.
 Это средство используется для подавления множественных вызовов
 обработчика отладочных исключений в контрольных точках.
 
 Например, могла быть установлена контрольная точка для команды,
 ссылающейся к данным в сегменте, не присутствующем в настоящий
 момент в памяти. Когда эта команда выполняется в первый раз,
 контрольная точка генерирует отладочную ситуацию. Прежде чем
 произойдет возврат из обработчика исключения, обработчик должен
 установить флаг RF в копии регистра EFLAGS, сохраненной в стеке.
 Это позволяет сообщить о сбое типа "сегмент не присутствует"
 после того, как обработчик отладочного исключения передаст
 управление назад на эту команду. Если флаг не установлен, то
 после возврата из обработчика отладочного исключения произойдет
 другое отладочное исключение.
 
 Процессор устанавливает бит RF в сохраненном содержимом регистра
 EFLAG, когда происходят другие сбои, поэтому при рестарте
 команды вследствие сбоя типа "сегмент не присутствует"
 множественные отладочные исключения не генерируются. Процессор
 очищает флаг RF при завершении выполнения приводящих к сбою
 команд. (Более подробная информация об отладке приводится в
 Главе 11).
 
 9.3.4 Команды MOV или POP для SS маскируют некоторые исключения
       и прерывания
 -----------------------------------------------------------------
 
 Программное обеспечение, которому требуется изменять стековые
 сегменты, часто использует пары команд, например
 
      MOV  SS, AX
      MOV  ESP, StackTop
 
 Если прерывание или исключение происходит после загрузки
 селектора сегмента, но до загрузки регистра ESP, эти две части
 логического адреса в пространстве стека являются противоречивыми
 на все время работы обработчика прерывания или исключения.
 
 Для предотвращения данной ситуации процессор запрещает
 прерывания, отладочные ситуации и исключения типа ловушки
 для пошагового выполнения после того, как будет выполнена
 команда MOV для SS, или POP для SS, до тех пор, пока не будет
 достигнута граница команды, находящаяся после следующей команды.
 Однако генерирование исключений общей защиты при этом возможно.
 Если для модификации содержимого регистра используется команда
 LSS, то данной проблемы не возникает.
 
 9.4 Приоритеты одновременно происходящих исключений и прерываний
 -----------------------------------------------------------------
 
 Если на границе команды ожидают обработки более одного
 исключения или прерывания, то процессор обслуживает их в
 определенной, предсказуемой последовательности. Приоритеты
 внутри классов исключений и прерываний показаны в Таблице 9 -2.
 Сначала процессор обслуживает отложенное исключение или
 прерывание из класса с высшим приоритетом, передавая выполненике
 первой команде соответствующего обработчика. Исключения с
 низшими прерываниями отменяются; прерывания с низшими
 приоритетами остаются подвешенными. Отмененные исключения затем
 генерируются снова, когда обработчик прерывания возвращает
 управление в точку прерывания.
 
 9.5  Таблица дескрипторов прерываний
 -----------------------------------------------------------------
 
 Таблица дескрипторов прерываний (IDT) ассоциирует каждый вектор
 исключения или прерывания с дескриптором процедуры или задачи,
 которая обслуживает соответствующее событие. Подобно таблицам
 GDT и LDT, IDT представляет собой массив 8-байтовых
 дескрипторов. В отличие от GDT, первый элемент IDT может
 содержать дескриптор. Для формирования индекса в IDT процессор
 умножает вектор исключения или прерывания на масштабный
 коэффициент восемь, т.е. число байтов дескриптора. Поскольку
 всего существует всего 256 векторов, IDT не может содержать
 более 256 дескрипторов. Она может содержать и менее 256
 дескрипторов, поскольку дескрипторы требуются только для тех
 векторов прерывания, которые действительно могут иметь место в
 системе.
 
        Таблица 9-2. Приоритеты одновременно произошедших
                     исключений и прерываний
 
 -----------------------------------------------------------------
 Приоритет                     Описания
 -----------------------------------------------------------------
 Высший       Исключения отладочных ловушек для последней команды
              (флаг TF установлен, бит T в TSS установлен, либо
              встречена контрольная точка данных)
              Исключения типа сбоя при отладке для следующей
              команды (контрольная точка для кода)
              Не-маскируемое прерывание
              Маскируемое прерывание
              Сбои при выборке следующей команды (Сбой "сегмент не
              присутствует" или сбой "общей защиты")
              Сбои при декодирования команды (Неверный код операции,
              слишком длинная команда или нарушение
              привилегированности) для    команды   WAIT,   особая
              ситуация "Сопроцессор  недоступен"  (биты  TS  и  MP
              регистра CR0 установлены) для команды ESC, особая
              ситуация "Сопроцессор недоступен" (биты EM или TS
              регистра CR установлены) для команд WAIT или ESC,
              Исключение "Ошибка  в сопроцессоре" (сигнал на
              штырьке ошибки Error #)
              Сбои "Сегмент не присутствует", Сбои в стеке и сбои
              Общей защиты для операндов памяти
              Сбои Выравнивания для операндов памяти
 
 Низший       Сбои страниц для операндов памяти
 -----------------------------------------------------------------
 
 IDT может находиться в любой области физической памяти. Как
 показано на Рисунке 9-1, процессор находит IDT при помощи регистра
 IDTR. Этот регистр содержит как 32-разрядный базовый адрес, так
 и 16-разрядную границу IDT. Команды LIDT и SIDT выполняют загрузку
 и сохранение содержимого регистра IDTR. Обе команды работают с
 одним операндом, представляющим собой адрес в памяти шести
 байтов.
 
 Если вектор ссылается на дескриптор вне заданной границы,
 процессор входит в режим закрытия. В этом режиме процессор
 прекращает выполнение команд до приема немаскируемого прерывания
 или сброса системы с последующей инициализацией. Процессор
 генерирует специальный цикл шины, указывающий на то, что он
 вошел в режим закрытия. Разработчикам программного обеспечения
 может понадобиться знать, как аппаратное обеспечение реагирует
 на данный сигнал. Например, аппаратное обеспечение может
 включать индикаторный светодиод на передней панели, генерировать
 немаскируемое прерывание для записи диагностической информации
 или выполнять инициализацию сброса системы.
 
                            Регистр IDTR
 47                                   16 15                     0
 -----------------------------------------------------------------
 |            Базовый адрес IDT         |      Граница IDT       |
 -----------------------------------------------------------------
                     |                                |
                     |       -------------------------
                     |       |
                     |       |
                     |       \/
                     |     -----        --------------------------
                     |---->| + |------->|      Прерывание        |
                     |     -----        |---  прерывание #N  ----|
                     |                  |------------------------|
                     |
                     |                  |------------------------|
                     |                  |      Шлюз для          |
                     |                  |---  прерывания #3  ----|
                     |                  |------------------------|
                     |                  |      Шлюз для          |
                     |                  |---  прерывания #2  ----|
                     |                  |------------------------|
                     |                  |      Шлюз для          |
                      ----------------->|---  прерывания #1  ----|
                                        --------------------------
 
   Рисунок 9-1. Регистр IDTR определяет положение IDT в памяти
 
 
 LIDT (Загрузить регистр IDT) загружает регистр IDTR базовым
 адресом и границей, находящимися в операнде памяти. Данная
 команда может быть выполнена только на CPL равном 0. Обычно она
 используется кодом инициализации операционной системы при
 создании IDT. Операционная система может также использовать ее
 для изменения с одной IDT на другую.
 
 SIDT (Сохранить регистр IDT) копирует значения базового адреса и
 границы, хранимые в IDTR, в оперативную память. Эта команда
 может быть использована на любом уровне привилегированности.
 
 9.6  Дескрипторы IDT
 -----------------------------------------------------------------
 
 IDT может содержать любой из трех видов дескрипторов:
 
      - Шлюзы задачи
      - Шлюзы прерывания
      - Шлюзы ловушки
 
 На Рисунке 9-2 показан формат шлюзов задачи, шлюзов прерывания и
 шлюзов ловушки. (Шлюз задачи в IDT это то же самое, что и шлюз
 задачи в GDT или LDT, рассмотренных в Главе 2).
 
 9.7  Задачи и процедуры прерывания
 -----------------------------------------------------------------
 
 Аналогично тому, как команда CALL вызывает процедуру или задачу,
 так и исключение или прерывание может "вызвать" обработчик
 прерывания, представленный в виде процедуры или задачи. Реагируя
 на исключение или прерывание, процессор использует вектор
 особого прерывания или прерывания в качестве индекса дескриптора
 в IDT. Если процессор индексирует шлюз прерывания или шлюз
 ловушки, то вызов обработчика происходит аналогично вызову при
 помощи CALL шлюза вызова. Если процессор индексирует шлюз
 задачи, это приводит к переключению задачи аналогично вызову при
 помощи CALL шлюза задачи.
 
 9.7.1  Процедуры прерывания
 -----------------------------------------------------------------
 
 Шлюз прерывания или шлюз ловушки косвенно обращаются к
 процедуре, выполняемой в контексте текущей выполняемой задачи,
 как показано на Рисунке 9-3. Селектор шлюза указывает на
 дескриптор выполняемого сегмента либо в GDT, либо в текущей LDT.
 Поле смещения в дескрипторе шлюза указывает на начало процедуры
 обработки исключения или прерывания.
 
 Процессор i486 вызывает процедуру обработки исключения или
 прерывания во многом аналогично обычному вызову процедуры:
 рзличия рассматриваются в следующих разделах.
 
                     Шлюз задачи
 
                                1 1 1 1 1 1 1
 31                             6 5 4 3 2 1 0 9 8 7            0
 ----------------------------------------------------------------
 |                               | | D |         |              |
 |       Резервировано           |P| P |0 0 1 0 1| Резервировано| +4
 |                               | | L |         |              |
 |--------------------------------------------------------------|
 |      Селектор сегмента TSS    |       Резервировано          | +0
 ----------------------------------------------------------------
 
                     Шлюз прерывания
 
                2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 31             4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4      0
 ----------------------------------------------------------------
 |                               | | D |         |     |        |
 |       Резервировано           |P| P |0 1 1 1 0|0 0 0|Резерви-| +4
 |                               | | L |         |     | ровано |
 |--------------------------------------------------------------|
 |      Селектор сегмента        |       Смещение 15:00         | +0
 ----------------------------------------------------------------
 
                     Шлюз ловушки
 
                                1 1 1 1 1 1 1
 31                             6 5 4 3 2 1 0 9 8 7 6 5 4      0
 ----------------------------------------------------------------
 |                               | | D |         |     |        |
 |       Смещение 31:16          |P| P |0 1 1 1 1|0 0 0|Резерви-| +4
 |                               | | L |         |     | ровано |
 |--------------------------------------------------------------|
 |      Селектор сегмента        |       Смещение 15:00         | +0
 ----------------------------------------------------------------
 
 
 DPL            Уровень привилегированности дескриптора
 Смещение       Смещение точки входа в процедуру
 P              Бит Присутствия сегмента
 Резервировано  Не использовать
 Селектор       Селектор сегмента кода назначения
 
               Рисунок 9-2. Дескрипторы шлюзов IDT
 
                                            Кодовый сегмент
                  IDT                          назначения
           -----------------              --------------------
           |       |       |              |                  |
           |---------------|              |------------------|
           |               |              |                  |
           |---------------|              |                  |
           |       |       |              |    Процедура     |
           |---------------|              |    прерывания    |
           |               |Смещение      |                  |
           |---------------|      -----   |                  |
 Вектор -->|Шлюз прерывания|----->| + |-->|------------------|
 прерывания| или ловушки   |---   -----   |                  |
           |---------------|   |    |     |                  |
           |       |       |   |    |     |                  |
           |---------------|   |    |     |                  |
           |               |   |    |     |                  |
           |---------------|   |    |     |                  |
           |       |       |   |    |     |                  |
           |---------------|   |    |     |                  |
           |               |   |    |     |                  |
           |---------------|   |    |     |                  |
           |       |       |   |    |     |                  |
           |---------------|   |    |     |                  |
           |               |   |    |     |                  |
           -----------------   |    |---->--------------------
                               |    |
                               |    |
   -----------------------------    |
   |                                |
   |                                |
   |          GDT или LDT           |
   |       -----------------        |   Базовый адрес
   |       |       |       |        |
   |       |---------------|        |
   |       |               |        |
   |       |---------------|        |
   |       |       |       |        |
   |       |---------------|        |
   |       |               |        |
   |       |---------------|        |
   |       |   Дескриптор  |        |
   ------->|   сегмента    |---------
           |---------------|
           |       |       |
           |---------------|
           |               |
           |---------------|
           |       |       |
           |---------------|
           |               |
           |---------------|
           |       |       |
           |---------------|
           |               |
           -----------------
 
             Рисунок 9-3. Вызов процедуры прерывания
 
 
 9.7.1.1  Стек процедуры прерывания
 -----------------------------------------------------------------
 
 Как и в случае передачи управления при помощи команды CALL, при
 передаче управления процедуре обработки исключения или
 прерывания используется стек, предназначенный для хранения
 состояния процессора. На Рисунке 9-4 показано, как прерывание
 помещает в стек содержимое регистра EFLAGS, а затем помещает
 туда адрес прерванной команды.
 
 Некоторые типы исключений и прерываний также помещают в стек код
 ошибки. Обработчик исключений может использовать этот код для
 того, чтобы диагностировать причину, вызвавшую исключение.
 
       Уровень                         Уровень
 привилегированности             привилегированности
    не изменяется,                  не изменяется,
   без кода ошибки                 с кодом  ошибки
 
 |                   |           |                  |
 |-------------------|   Старый  |------------------|   Старый
 |                   |<-- ESP    |                  |<-- ESP
 |-------------------|           |------------------|
 |  Старый EFLAGS    |           |  Старый EFLAGS   |
 |-------------------|           |------------------|
 |         |Старый CS|           |        |Старый CS|
 |-------------------|   Новый   |------------------|
 |  Старый EIP       |<-- ESP    |  Старый EIP      |
 |-------------------|           |------------------|   Новый
 |                   |           |  Код ошибки      |<-- ESP
                                 |------------------|
 
       Уровень                         Уровень
 привилегированности             привилегированности
      изменяется,                     изменяется,
   без кода ошибки                 с кодом  ошибки
 
 ---------------------   ESP из  ---------------------   ESP из
 |  Не используется  |<-- TSS    |  Не используется  |<-- TSS
 |-------------------|           |-------------------|
 |         |Старый SS|           |         |Старый SS|
 |-------------------|           |-------------------|
 |     Старый ESP    |           |     Старый ESP    |
 |-------------------|           |-------------------|
 |     Старый EFLAGS |           |     Старый EFLAGS |
 |-------------------|           |-------------------|
 |         |Старый CS|           |         |Старый CS|
 |-------------------|   Новый   |-------------------|
 |     Старый EIP    |<-- ESP    |     Старый EIP    |
 |-------------------|           |-------------------|   Новый
                                 |   Код ошибки      |<-- ESP
                                 |-------------------|
 
    Рисунок 9-4. Запись активации после выполнения прерывания
 
 9.7.1.2  Возврат из процедуры прерывания
 -----------------------------------------------------------------
 
 Процедура прерывания отличается от обычной процедуры способом
 выхода из процедуры. Для выхода из процедуры прерывания служит
 команда IRET. Команда IRET аналогична команды RET, за
 исключением того, что она инкрементирует содержимое регистра ESP
 на четыре лишние байта и восстанавливает сохраненные флаги в
 регистр EFLAGS. Поле IOPL регистра EFLAGS восстанавливается
 только при CPL, равном 0. Флаг IF изменяется только при CPL <=
 IOPL.
 
 9.7.1.3  Использование флага процедурой прерывания
 -----------------------------------------------------------------
 
 Прерывания, использующие либо шлюзы прерывания, либо шлюзы
 ловушки, вызывают очистку флага TF после того, как его текущее
 значение сохранено в стеке как часть сохраняемого содержимого
 регистра EFLAGS. Поступая таким образом, процессор предотвращает
 воздействие трассировки команды на реакцию прерывания.
 Последующая команда IRET восстанавливает флаг TF в значение,
 сохраненное в регистре EFLAGS в стеке.
 
 Различие между шлюзом прерывания и шлюзом ловушки состоит в их
 воздействии на флаг IF. Прерывание, использующее шлюз
 прерывания, очищает флаг IF, предотвращая тем самым влияние на
 текущий обработчик прерывания прочих возможных прерываний.
 Последующая команда IF восстанавливает флаг IF в состояние,
 которое он имел в сохраненном в стеке регистре EFLAGS.
 Прерывание, проходящее через шлюз ловушки, не изменяет флага IF.
 
 9.7.1.4  Защита в процедурах прерывания
 -----------------------------------------------------------------
 
 Правило привилегированности, управляющее процедурами прерывания,
 аналогично правилу, действующему при вызове процедуры: процессор
 не разрешает прерыванию передавать управление процедуре в менее
 привилегированный сегмент (с численно большим номером уровня
 привилегированности). Попытка нарушить это правило ведет к
 генерации исключения защиты.
 
 Поскольку прерывания как правило происходят не в заранее
 запланированное время, данное правило фактически накладывает
 ограничения на уровни привилегированности, с которыми могут
 выполняться процедуры обработки исключений и прерываний. Для
 защиты от нарушения правила привилегированности можно
 использовать один из следующих способов:
 
 - Обработчик исключения или прерывания должен быть помещен в
   конформный кодовый сегмент. Этот способ может использоваться
   для обработчиков некоторых конкретных исключений (например,
   деления на ноль). Такие обработчики должны использовать только
   данные, доступные через стек. Если обработчику требуются
   данные из сегмента данных, этот сегмент данных должен иметь
   уровень привилегированности 3, то есть он должен быть
   незащищенным.
 
 - Обработчик может быть помещен в кодовый сегмент с уровнем
   привилегированности 0. Такой обработчик будет выполняться
   всегда, независимо от CPL программы.
 
 9.7.2  Задачи прерывания
 -----------------------------------------------------------------
 
 Как показано на Рисунке 9-5, шлюз задачи в IDT косвенно
 ссылается на задачу. Селектор сегмента в шлюзе задачи адресует
 дескриптор TSS в GDT.
 
 Когда исключение или прерывание вызывает шлюз задачи в IDT,
 происходит переключение задачи. Обработка прерывания в отдельной
 задаче имеет два преимущества:
 
 - Автоматически выполняется полное сохранения всего контекста.
 
 - Обработчик прерывания может быть изолирован от прочих задач за
   счет выделяемого ему отдельного адресного пространства. Это
   выполняется за счет отдельной LDT.
 
 
 
                  IDT                       TSS
           -----------------          -----------------
           |       |       |          |               |
           |---------------|          |               |
           |               |          |               |
           |---------------|          |               |
           |       |       |          |               |
           |---------------|          |               |
           |               |          |               |
           |---------------|          |               |
 Вектор -->|       |       |-----     |               |
 прерывания|- Шлюз задачи -|     | -->-----------------
           |---------------|     | |
           |       |       |     | |
           |---------------|     | |
           |               |     | |
           |---------------|     | |
           |       |       |     | |
           |---------------|     | |
           |               |     | |
           |---------------|     | |
           |       |       |     | |
           |---------------|     | |
           |               |     | |
           -----------------     | |
           Селектор TSS          | |
      ---------------------------- |
      |                            |
      |                            |
      |           GDT              | Базовый адрес TSS
      |    -----------------       |
      |    |       |       |       |
      |    |---------------|       |
      |    |               |       |
      |    |---------------|       |
      |    |       |       |       |
      |    |---------------|       |
      |    |               |       |
      |    |---------------|       |
      |    |       |       |       |
      ---->|-Шлюз задачи --|--------
           |---------------|
           |       |       |
           |---------------|
           |               |
           |---------------|
           |       |       |
           |---------------|
           |               |
           |---------------|
           |       |       |
           |---------------|
           |               |
           -----------------
 
           Рисунок 9-5. Переключение задачи прерывания
 
 
 Переключение задачи, вызванное прерыванием, работает аналогично
 другим прерываниям задачи, описанным в Главе 7. Задача
 прерывания возвращается к прерванной задаче, выполняя команду
 IRET.
 
 Некоторые исключения возвращают код ошибки. Если переключение
 задачи вызвано одним из таких исключений, процессор помещает код
 в стек, соответствующий уровню привилегированности обработчика
 прерывания.
 
 Когда задачи прерывания используются в операционной системе для
 процессора i486, фактически существует два механизма, которые
 позволяют создание новых задач: программный планировщик (часть
 операционной системы) и аппаратный планировщик (часть механизма
 прерываний процессора). Программный планировщик должен учитывать
 задачи прерывания, которые могут генерироваться при разрешенных
 прерываниях.
 
 9.8  Код ошибки
 -----------------------------------------------------------------
 
 Поскольку исключения связаны с конкретным сегментом, процессор
 помещает в стек обработчика исключений код ошибки (как для
 процедур, так и для задач). Код ошибки имеет формат, показанный
 на Рисунке 9-6. Код ошибки похож на селектор сегмента, однако вместо
 поля RPL код ошибки содержит два одно-битовых поля:
 
 1. Процессор устанавливает бит EXT, если исключение вызвано
    событием, внешним по отношению к программе.
 
 2. Процессор устанавливает бит IDT, если индексная часть кода
    ошибки ссылается к дескриптору шлюза в IDT.
 
 Если бит IDT не установлен, то бит TI указывает на то, ссылается
 ли код ошибки к GDT (бит TI очищен), или же к LDT (бит TI
 установлен). Остальные 14 битов - это старшие биты селектора
 сегмента. В некоторых случаях код ошибки является пустым (т.е.
 все биты его младшего слова очищены.)
 
 Код ошибки помещается в стек в виде двойного слова. Это делается
 для выравнивания стека по адресам, кратным четырем. Старшая
 половина двойного слова резервируется.
 
 9.9  Условия исключений
 -----------------------------------------------------------------
 
 В следующих разделах описаны условия, генерирующие исключения.
 Каждое описание классифицирует исключение как сбой, ловушку или
 аварийное завершение. Такая классификация обеспечивает
 информацию, необходимую системным программистам для рестарта
 процедуры, в которой встретилось данное исключение.
 
 - Сбои - Сохраненное содержимое регистров CS и EIP указывает на
   команду, сгенерировавшую сбой.
 
 
      31                  15                3 2 1 0
      ----------------------------------------------
      |                  |                   |T| |E|
      |   Резервировано  |  Индекс селектора |I|I|X|
      |                  |                   | | |T|
      ----------------------------------------------
 
                     Рисунок 9-6. Код ошибки
 
 
 - Ловушки - Сохраненное содержимое регистров CS и EIP,
   записанное в момент срабатывания ловушки, указывает на
   команду, которая должна быть выполнена после команды,
   сгенерировавшей ловушку. Если ловушка обнаружена в команде
   передачи управления, сохраненное содержимое регистров CS и EIP
   отражает эту передачу управления. Например, если ловушка
   сработала в команде JMP, то сохраненное значение регистров CS
   и EIP указывает на адрес назначения перехода команды JMP, а не
   на команду в следующем адресе после команды JMP.
 
 - Аварийные завершения - Аварийное завершение - это исключение,
 не позволяющее ни точного определения команды, вызвавшей его, ни
 рестарта программы, в которой произошло это исключение.
 Аварийные завершения используются для сообщения о серьезных
 ошибках, таких как аппаратные ошибки или противоречивые или
 недопустимые значения в системных таблицах.
 
 9.9.1  Прерывание 0 - Ошибка деления
 -----------------------------------------------------------------
 
 Сбой типа "ошибки деления" встречается в командах DIV или IDIV,
 при делителе равном 0.
 
 9.9.2  Прерывание 1 - Отладочные исключения
 -----------------------------------------------------------------
 
 Процессор генерирует исключения для нескольких условий: то,
 является ли данное исключение сбоем или ловушкой, зависит
 от условия, как показано ниже:
 
      - Сбой в контрольной точке адреса команды
 
      - Ловушка в контрольной точке адреса данных
 
      - Ловушка шага выполнения
 
      - Ловушка контрольной точки переключения задачи
 
 Процессор не помещает код ошибки для данного исмключения в стек.
 Обработчик прерывания может исследовать отладочные регистры для
 того, чтобы определить, какое условие вызвало исключение. Более
 подробную информацию об отладке и отладочных регистрах см. в
 Главе 11.
 
 9.9.3  Прерывание 3 - Контрольная точка
 -----------------------------------------------------------------
 
 Команда INT 3 генерирует ловушку типа контрольной точки. Команда
 INT 3 имеет длину один байт, что упрощает замену кода операции в
 кодовом сегменте в оперативной памяти кодом операции контрольной
 точки. Операционная система или система отладки может
 использовать сегмент данных, отображенный в том же физическом
 адресном пространстве, что и кодовый сегмент, для помещения
 команды INT 3 в точках, где желательно вызвать отладчик.
 Отладчики используют контрольные точки для приостановки
 выполнения программы, чтобы иметь возможность исследовать
 регистры, переменные программы и т.д.
 
 Сохраненное содержимое регистров CS и EIP указывает на байт,
 следующий за контрольной точкой. Если отладчик позволяет
 возобновление приостановленной программы, он заменяет команду
 INT 3 исходным кодом операции по адресу контрольной точки, а
 также декрементирует сохраненное содержимое регистра EIP перед
 возвратом. Более подробную информацию об отладке см. в Главе 11.
 
 9.9.4  Прерывание 4 - Переполнение
 ----------------------------------------------------------------
 
 Ловушка переполнения происходит, когда процессор выполняет
 команду INTO при установленном флаге IF. Поскольку
 арифметические операции со знаком и без знака используют
 некоторые общие команды, процессор не в состоянии определить,
 когда фактически происходит переполнение. Вместо этого он
 устанавливает флаг OF, когда результаты, интерпретируемые как
 числа со знаком, выходят за пределы допустимого диапазона. При
 выполнении арифметических операций с операндами, имеющими знак,
 флаг OF можно тестировать непосредственно, либо при помощи
 команды INTO.
 
 9.9.5  Прерывание 5  -  Контроль диапазона
 -----------------------------------------------------------------
 
 Сбой типа "контроля диапазона" генерируется процессором, когда
 при выполнении команды BOUND обнаруживается, что операнд
 превышает заданные границы. Программа может использовать команду
 BOUND для контроля того, что индекс массива, имеющий знак,
 находится в пределах, определенных для этого блока памяти.
 
 9.9.6  Прерывание 6  -  Неверный код операции
 -----------------------------------------------------------------
 
 Сбой "неверного кода операции" генерируется, когда
 исполнительный модуль обнаруживает неверный код операции.
 (Данное исключение не будет обнаружено до тех пор, пока не будет
 сделана попытка выполнить неверный код операции; т.е.
 предварительная выборка неверного кода операции, без выполнения,
 не ведет к данному исключению). Код ошибки в данном случае на
 стек не помещается. Такое исключение может обрабатываться в
 пределах той же задачи.
 
 Это исключение происходит также при неверном типе операнда для
 данного кода операции. Примером может служить команда
 межсегментного перехода JMP, использующая регистровый операнд,
 либо команда LES с регистровым исходным операндом.
 
 Третье условие генерации данного исключения состоит в
 использовании префикса LOCK с командой, для которой захват шины
 невозможен. Только определенные команды могут работать с
 захватом шины, и из них могут использоваться только те, что
 выполняют запись по адресу назначения в памяти. Все прочие
 использования префикса LOCK приводят к генерации исключения
 неверного кода операции.
 
                           ПРИМЕЧАНИЕ:
 
 Таблица 9-3 содержит список неопределенных кодов операции,
 которые резервированы Intel. Эти коды операции прерывания 6 не
 генерируют.
 
 9.9.7  Прерывание 7  -  Устройство недоступно
 -----------------------------------------------------------------
 
 Сбой типа "устройство недоступно" генерируется при одном из двух
 следующих условий:
 
 - Процессор выполняет команду ESC при установленном бите EM
   регистра CR0.
 
 - Процессор выполняет команду WAIT или ESC при установленном
   бите TS регистра CR0.
 
         Таблица 9-3. Резервированные коды операций Intel
 
 -----------------------------------------------------------------
                        Однобайтовые
 -----------------------------------------------------------------
                             82
                             D6
                             F1
 -----------------------------------------------------------------
                        Двухбайтовые
 -----------------------------------------------------------------
                           0F 07
                           0F 10
                           0F 11
                           0F 12
                           0F 13
 
                           F6 XX
                           F7 XX
 
                           C0 XX
                           C1 XX
                           D0 XX
                           D1 XX
                           D2 XX
                           D3 XX
 -----------------------------------------------------------------
 
 Таким образом, прерывание 7 происходит, когда программист хочет,
 чтобы команда ESC обрабатывалась программно (бит EM установлен),
 либо когда встречена команда WAIT или ESC, а контекст модуля
 операций с плавающей точкой отличен от контекста для текущей
 задачи.
 
 Для процессоров 80286 и 386 бит MP регистра CR0 используется с
 битом TS для определения того, должна ли команда WAIT
 генерировать исключение. Для программ, выполняемых на процессоре
 i486, бит MP должен быть установлен всегда.
 
 9.9.8  Прерывание 8 - Двойной сбой
 -----------------------------------------------------------------
 
 Обычно когда процессор обнаруживает исключение при попытке
 вызвать обработчик исключения, происшедшей ранее, эти два
 исключения могут обрабатываться последовательно. Однако, если
 процессор не в состоянии этого сделать, он генерирует исключение
 двойного сбоя. Для того, чтобы определить, когда о двух сбоях
 следует сообщить как о двойном сбое, процессор i486 делит
 исключения на три класса: незначительные исключения,
 значительные исключения и страничные сбои. Эта классификация
 показана в Таблице 9-4.
 
 Когда происходит два незначительных исключения или
 прерывания, либо одно незначительное и одно значительное, то два
 таких события могут обрабатываться последовательно. В случае
 двух значительных событий они не могут быть обработаны, и тогда
 генерируется исключение двойного сбоя.
 
 Если за незначительным или значительным исключением следует
 страничный сбой, то два таких события могут быть обработаны
 последовательно. Это также справедливо и в том случае, когда
 сначала следует страничный сбой, а за ним незначительное
 исключение. Однако, если за страничным сбоем следует
 значительное исключение или еще один страничный сбой, то
 генерируется аварийное завершение типа "двойной сбой".
 
           Таблица 9-4. Классы прерываний и исключений
 
 -----------------------------------------------------------------
 Класс       Номер вектора                  Описание
 -----------------------------------------------------------------
                  1          Отладочные исключения
                  2          Немаскируемое прерывание
 Незначительные   3          Контрольная точка
 исключения       4          Переполнение
 и прерывания     5          Контроль диапазона
                  6          Неверный код операции
                  7          Устройство недоступно
                 16          Ошибка операции с плавающей точкой
 -----------------------------------------------------------------
                  0          Ошибка деления
 Значительные    10          Неправильный TSS
 исключения      11          Сегмент не присутствует
                 12          Сбой в стеке
                 13          Общая защита
 -----------------------------------------------------------------
 Страничные      14          Страничный сбой (отсутствие страницы)
 сбои
 -----------------------------------------------------------------
 
 Исходный сегмент страничного сбоя, встреченного при
 предварительной выборке команды, лежит вне домена Таблицы 9-4.
 Любые последующие сбои, генерируемые при попытках процессора
 передать управление соответствующему обработчику прерывания,
 могут также привести к ситуации двойного сбоя.
 
 Процессор всегда помещает код ошибки в стек обработчика двойного
 сбоя, однако этот код ошибки всегда равен 0. Рестарт вызвавшей
 сбой команды невозможен. Если при попытке вызвать обработчик
 двойного сбоя произойдет еще одно исключение, процессор входит в
 режим закрытия системы. Этот режим аналогичен состоянию,
 следующему за выполнением команды HLT. Никакие дальнейшие
 команды не выполняются до приема немаскируемого прерывания или
 сигнала сброса системы RESET. Если закрытие системы происходит
 во время выполнения процессором обработчика немаскируемого
 прерывания, то рестарт процессора возможен только при помощи
 сигнала RESET. Процессор генерирует специальный цикл шины,
 указывающий на вхождение процессора в режим закрытия.
 
 9.9.9  Прерывание 9  -  (Резервируется Intel. Не использовать)
 
 Прерывание 9, аварийное завершение выхода за границы сегмента
 сопроцессора, генерируется в системе центрального процессора 386
 /математического сопроцессора 387, когда процессор 386
 обнаруживает нарушение границы страницы или сегмента при
 пересылке средней части операнда математического сопроцессора
 387. Это прерывание процессором i486 не генерируется; вместо
 него происходит прерывание 13.
 
 9.9.10  Прерывание 10  -  Неверный TSS
 -----------------------------------------------------------------
 
 Сбой типа "неверный TSS" генерируется при попытке переключения
 задачи на сегмент с неверным TSS. TSS является неверным в
 случаях, описанных в Таблице 9-5. Код ошибки помещается в стек
 обработчика исключений, что помогает идентифицировать причину
 сбоя. Бит EXT указывает, что исключение было вызвано условием
 вне управления программы (например, внешнее прерывание,
 используя шлюз задачи, попыталось выполнить переключение задачи
 на неверный TSS).
 
                Таблица 9-5. Условия неверного TSS
 
 -----------------------------------------------------------------
 Индекс кода ошибки     Описание
 -----------------------------------------------------------------
    Сегмент TSS         Граница сегмента TSS меньше 67H
    Сегмент LDT         Неверная LDT или LDT не присутствует
    Сегмент стека       Селектор сегмента стека превышает границу
                        таблицы дескрипторов
    Сегмент стека       Сегмент стека не доступен для записи
    Сегмент стека       DPL сегмента стека не совместим с CPL
    Сегмент стека       RPL селектора сегмента стека не совместим
                        с CPL
    Сегмент кода        Селектор сегмента кода превышает границу
                        таблицы дескрипторов
    Сегмент кода        Сегмент кода не является выполняемым
    Сегмент кода        DPL не-конформного сегмента кода
                        не равен CPL
    Сегмент кода        DPL конформного  сегмента кода больше  CPL
    Сегмент данных      Селектор сегмента данных превышает границу
                        таблицы дескрипторов
    Сегмент данных      Сегмент данных не доступен для чтения
 -----------------------------------------------------------------
 
 Данный сбой может происходить как в контексте исходной задачи,
 так и в контексте новой задачи. До тех пор, пока процессор
 полностью не убедится в присутствии нового TSS, исключение
 происходит в контексте исходной задачи. Как только присутствие
 нового TSS будет подтверждено, переключение задачи считается
 завершенным, т.е. регистр TR загружен селектором нового TSS, и
 если переключение задачи является следствием CALL или
 прерывания, то поле Компоновки нового TSS будет содержать ссылку
 на старый TSS. Любые ошибки, обнаруженные процессором после этой
 точки, обрабатываются в контексте новой задачи.
 
 Чтобы гарантировать доступность TSS для обработки исключения,
 обработчик исключения типа "неверный TSS" должен вызываться как
 задача посредством шлюза задачи.
 
 9.9.11  Прерывание 11  -  Сегмент не присутствует
 -----------------------------------------------------------------
 
 Сбой типа "сегмент не присутствует" генерируется, когда
 процессор обнаруживает, что бит Присутствия в дескрипторе
 очищен. Процессор может генерировать данный сбой в одном из
 следующих случаев:
 
 - При попытке загрузить регистры CS, DS, ES, FS или GS; однако,
   загрузка регистра SS вызывает сбой стека.
 
 - При попытке загрузить регистр LDT при помощи команды LLDT;
   однако, загрузка регистра LDT во время операции переключения
   задачи вызывает исключение "неверный TSS".
 
 - При попытке использовать дескриптор шлюза, помеченный
   признаком "сегмент не присутствует".
 
 Данный сбой позволяет выполнение рестарта. Если обработчик
 исключений загружает сегмент и возвращается, то прерванная
 программа продолжает выполнение.
 
 Если исключение "сегмент не присутствует" происходит во время
 перключения задачи, то не все шаги переключения задачи
 завершаются. При переключениии задачи процессор сначала
 загружает все сегментные регистры, а затем проверяет
 допустимость их содержимого. При обнаружении исключения "сегмент
 не присутствует" остальные сегментные регистры не проверяются, и
 следовательно, не могут быть использованы для ссылок к памяти.
 Обработчик исключения "сегмент не присутствует" не должен
 полагаться на возможность использования селекторов сегментов,
 находящихся в регистрах CS, SS. DS, ES, FS и GS без
 возникновения еще одного исключения. Обработчик должен проверять
 все сегментные регистры перед тем, как пытаться возобновить
 выполнение новой задачи; в противном случае, далее могут
 произойти сбои общей защиты, причем в условиях, которые сделают
 диагностирование еще более затруднительным. Для обработки этого
 случая имеется три способа:
 
 1. Обработка сбоя "сегмент не присутствует" в задаче. Обратное
    переключение на прерванную задачу заставит процессор
    проверить все регистры при загрузке их из TSS.
 
 2. Использование для всех сегментных регистров команд PUSH и
    POP. Каждая команда POP заставит процессор проверить новое
    содержимое сегментного регистра.
 
 3. Проверка сохраненного в TSS значения каждого сегментного
    регистра при помощи симуляции теста, выполняемого процессором
    при загрузке сегментного регистра.
 
 Данное исключение помещает в стек код ошибки. Бит EXT кода
 ошибки устанавливается в том случае, если внешнее по отношению к
 программе событие вызвало прерывание, которое затем привело к
 ссылке на не-присутствующий сегмент. Бит IDT устанавливается,
 если код ошибки выполняет ссылку на элемент IDT (например,
 команда INT, ссылающаяся на не-присутствующий шлюз).
 
 Операционная система обычно использует исключение "сегмент не
 присутствует" для реализации на сегментном уровне виртуальной
 памяти. Однако, обозначение не-присутствия сегмента в
 дескрипторе шлюза обычно не означает, что сегмент не
 присутствует (поскольку шлюзы не обязательно должны
 соответствовать сегментам). Не-присутствующие шлюзы могут
 использоваться операционной системой для переключения
 исключений, имеющих специальное значение для операционной
 системы.
 
 9.9.12 Прерывание 12 - Исключение в стеке
 -----------------------------------------------------------------
 
 Сбой в стеке генерируется в двух следующих случаях:
 
 - В результате нарушения границы операцией, ссылающейся к
   регистру SS. Сюда входят стек-ориентированные команды, такие
   как POP, PUSH, ENTER и LEAVE, а также прочие ссылки к памяти,
   неявно использующие стек (например, MOV AX,[BP+6]). Команда
   ENTER генерирует данное исключение, когда не хватает памяти
   для распределения локальных переменных.
 
 - При попытке загрузить регистр SS дескриптором, отмеченным
   признаком "сегмент не присутствует", и допустимым во всех
   прочих отношениях. Это может произойти при переключении
   задачи, при выполнении команды CALL к другому уровню
   привилегированности, при возврате к другому уровню
   привилегированности, команде LSS, либо MOV или POP для
   регистра SS.
 
 Когда процессор обнаруживает исключение в стеке, он помещает код
 ошибки в стек обработчика исключений. Если исключение произошло
 вследствии не-присутствующего сегмента стека или переполнения
 нового стека во время выполнения меж-уровневой команды CALL, то
 код ошибки содержит селектор сегмента, вызвавшего исключение
 (обработчик исключений может проверять бит Присутствия в
 дескрипторе для того, чтобы определить, какое исключение имело
 место); в противном случае код ошибки равен 0.
 
 Команда, генерирующая данный сбой, позволяет рестарт во всех
 случаях. Адрес возврата, помещенный в стек обработчика
 исключений, указывает на команду, рестарт которой требуется
 выполнить. Эта команда обычно та, что вызвала исключение;
 однако, в случае исключительной ситуации в стеке вследствие
 загрузки дескриптора не-присутствующего сегмента стека во время
 переключения задачи указанная команда представляет собой первую
 команду новой задачи.
 
 Когда исключение в стеке происходит при переключении задачи,
 сегментные регистры не могут служить для адресации памяти. Во
 время переключения задачи значения селекторов загружаются до
 проверки дескрипторов. При генерации исключения стека остальные
 сегментные регистры остаются непроверенными, что может привести
 при их использовании к исключениям. Обработчик сбоев стека
 должен проверить все сегментные регистры, прежде чем пытаться
 возобновить выполнение новой задачи; в противном случае могут
 быть сгенерированы исключения общей защиты в условиях, когда
 диагностирование более затруднительно.
 
 9.9.13  Прерывание 13  -  Общая защита
 -----------------------------------------------------------------
 
 Исключение общей защиты генерируется для всех нарушений памяти,
 не вызывающих прочих исключений. Сюда входят (но не ограничивают
 перечень):
 
 - Превышение границы сегмента при использовании сегментов CS,
   DS, ES, FS или GS.
 
 - Превышение границы сегмента при ссылке к таблице дескрипторов.
 
 - Передача выполнения сегменту, не являющемуся выполняемым
   (кодовым) сегментом.
 
 - Попытка записи в сегмент данных, доступный только для чтения,
   или в кодовый сегмент.
 
 - Чтение из кодового сегмента, доступного только для выполнения.
 
 - Загрузка регистра SS селектором сегмента, доступного только
   для чтения (если только этот селектор не берется из TSS при
   переключении задачи, так как в этом случае происходит
   исключение "неверный TSS").
 
 - Загрузка регистра SS, DS, ES, FS или GS селектором системного
   сегмента.
 
 - Загрузка регистра DS, ES, FS или GS селектором кодового
   сегмента, доступного только для выполнения.
 
 - Загрузка регистра SS селектором выполняемого сегмента.
 
 - Доступ к памяти при помощи регистров DS, ES, FS или GS, когда
   в них содержится пустой селектор.
 
 - Переключение на Занятую задачу.
 
 - Нарушение правил привилегированности.
 
 - Превышение длины команды предельного значения 15 байтов
   (это может случиться только при использовании перед командой
   избыточных префиксов).
 
 - Загрузка регистра CR0 при установленном бите PG (подкачка
   страниц разрешена) и очищенном бите PE (защита запрещена).
 
 - Прерывание или исключение через шлюз пренрывания или ловушки
   из виртуального режима 8086 к обработчику с уровнем
   привилегированности иному, нежели 0.
 
 Исключение общей защиты по типу относится к сбою. В ответ на
 исключение общей защиты процессор помещает в стек обработчика
 исключений код ошибки. Если исключение вызвано загрузкой
 дескриптора, то код ошибки содержит селектор для данного
 дескриптора; в противном случае код ошибки является пустым.
 Источник для селектора в коде ошибки может представлять собой
 одно из:
 
      1. Операнд команды.
 
      2. Селектор из шлюза, являющегося операндом команды.
 
      3. Селектор из TSS, участвующего в переключении задачи.
 
 9.9.14  Прерывание 14  -  Страничный сбой
 -----------------------------------------------------------------
 
 Страничный сбой происходит, когда подкачка страниц разрешена
 (бит PG регистра CR0 установлен) и процессор обнаруживает одно
 из следующих условий во время трансляции линейного адреса в
 физический:
 
 - Элемент каталога страниц или таблицы страниц, необходимый для
   трансляции адреса, имеет очищенный бит Присутствия, что
   означает, что таблица страниц или страница, содержащая
   операнд, не присутствует в физической памяти.
 
 - Процедура не имеет достаточного уровня привилегированности
   для доступа к указанной странице.
 
 Процессор обеспечивает для обработчика страничного сбоя два
 информационных элемента, помогающих диагностировать исключение и
 восстановить нормальные условия:
 
 - Код ошибки в стеке. Код ошибки для страничного сбоя имеет
   формат, отличный от формата для других особых ситуаций (см.
   Рисунок 9 -7). Код ошибки сообщает обработчику исключения
   следующие три вещи:
 
   1. Произошло ли данное исключение вследствие того, что
      страница не присутствует, или из-за нарушения прав доступа
      к странице.
 
   2. Работал ли процессор в момент исключения в режиме
      пользователя, или в режиме супервизора.
 
   3. Состоял ли доступ к памяти, вызвавший данное исключения, в
      чтении или в записи.
 
 - Содержимое регистра CR2. Процессор загружает в регистр CR2 32-
   разрядный линейный адрес, сгенерировавший исключение.
   Обработчик исключения может использовать данный адрес для
   нахождения соответствующих элементов каталога страниц и
   таблицы страниц. Если во время выполнения обработчика
   страничного сбоя произойдет еще один страничный сбой, то
   обработчик должен поместить содержимое регистра CR2 в стек.
 
 -----------------------------------------------------------------
 | Поле | Значение |                   Описание                  |
 -----------------------------------------------------------------
   U/S        0      Доступ, вызвавший сбой, произошел при работе
                     процессора в режиме супервизора
 
              1      Доступ, вызвавший сбой, произошел при работе
                     процессора в режиме пользователя
 
   W/R        0      Вид досупа, вызвавший сбой, это чтение
 
              1      Вид досупа, вызвавший сбой, это запись
 
    P         0      Сбой был вызван отсутствием страницы
 
              1      Сбой был вызван нарушением защиты на уровне
                     страниц
 -----------------------------------------------------------------
 
      31              15       7      3 2 1 0
      ----------------------------------------
      |                                |U|W| |
      |      Не определены             |/|/|P|
      |                                |S|R| |
      ----------------------------------------
 
            Рисунок 9-7.  Код ошибки страничного сбоя
 
 
 9.9.14.1  Страничный сбой при переключении задачи
 -----------------------------------------------------------------
 
 Следующие операции выполняют доступ к памяти при переключении
 задачи:
 
 1. Запись состояния исходной задачи в TSS для этой задачи.
 
 2. Чтение GDT для нахождения дескриптора TSS новой задачи.
 
 3. Чтение TSS новой задачи для проверки типов дескрипторов
    сегмента из TSS.
 
 4. Может быть выполнено чтение LDT новой задачи для верификации
    сегментных регистров, хранимых в новом TSS.
 
 Страничный сбой может являться результатом обращения к одной из
 этих операций. В двух последних случаях исключение происходит в
 контексте новой задачи. Указатель команд указывает на следующую
 команду новой задачи, а не на команду вызвавшую переключение
 задачи (или на последнюю выполняемую команду в случае
 прерывания). Если устройство операционной системы позволяет
 страничным сбоям происходить вовремя переключения задач, то
 обработчик страничного сбоя должен вызываться через шлюз задачи.
 
 9.9.14.2  Страничный сбой при противоречивом значении указателя
           стека
 -----------------------------------------------------------------
 
 Следует обращать особое внимание на то, чтобы страничный сбой не
 приводил к использованию процессором неверного указателя стека
 (SS:ESP). Программное обеспечение, написанное для 16-битовых
 процессоров Intel, часто использует для переключения на новый
 стек пару команд, например,
 
      MOV SS, AX
      MOV SP, StackTop
 
 В случае процессора i486, поскольку вторая команда обращается к
 памяти, можно получить в данном случае страничный сбой после
 того, как был изменен селектор сегментного регистра SS, но перед
 тем, как соответственно было изменено соджержимое регистра SP. В
 этой точке две части указателя стека SS:SP (разумеетя, для
 32-разрядных программ это SS:ESP) противоречивы друг с другом.
 Новый стековый сегмент используется со старым указателем стека.
 
 Процессор не использует противоречащий указатель стека, если
 обработка страничного сбоя вызывает переключение стека на хорошо
 определенный стек (т.е. обработчик это задача или более
 привилегированная процедура). Однако, если страничный сбой
 происходит на том же уровне привилегированности и в той же
 задаче, что и для обработчика страничного сбоя, то процессор
 попытается использовать стек, на который указывает
 противоречивый указатель стека.
 
 В системах, использующих подкачку страниц и обрабатывающих
 страничные сбои в пределах задач, содержащих сбой (посредством
 шлюзов ловушки или прерывания), программное обеспечение,
 выполняемое на том же уровне привилегированности, что и
 обработчик страничного сбоя, должно инициализировать новый стек
 командой LSS, а не парой команд, показанной выше. Если
 обработчик страничного сбоя работает на уровне
 привилегированности 0 (нормальный случай), проблема
 ограничивается программами, работающими на уровне
 привилегированности 0, т.е. обычно ядром операционной системы.
 
 9.9.15  Прерывание 16  -  Ошибка операции с плавающей точкой
 -----------------------------------------------------------------
 
 Сбой операции с плавающей точкой говорит об ошибке, генерируемой
 командой арифметической операции с плавающей точкой. Прерывание
 16 может произойти только если бит NE регистра CR0 установлен.
 Более подробную информацию о сообщениях об ошибках для операций
 с плавающей точкой см. в Главе 16.
 
 9.9.16  Прерывание 17  -  Проверка выравнивания
 -----------------------------------------------------------------
 
 Сбой проверки выравнивания может генерироваться при доступе к
 невыравненным операндам. Например, слово, записанное по
 нечетному адресу памяти, или двойное слово, записанное по
 адресу, не кратному четырем. В Таблице 9-6 приводятся требования
 к выравниванию по типам данных. Для разрешения контроля
 выравнивания должны выполняться следующие условия:
 
      - Бит AM регистра CR0 должен быть установлен.
      - Флаг AC должен быть установлен.
      - CPL должен быть равен 3 (уровень пользователя).
 
      Таблица 9-6. Требования к выравниванию по типам данных
 
 -----------------------------------------------------------------
 Тип данных                        Адрес должен нацело делиться на
 -----------------------------------------------------------------
 Слово                                           2
 Двойное слово                                   4
 Короткое вещественное                           4
 Длинное вещественное                            8
 Временное вещественное                          8
 Селектор                                        2
 48-разрядный сегментированный указатель         4
 32-разрядный плоский указатель                  4
 32-разрядный сегментированный указатель         2
 48-разрядный "Псевдо-дескриптор"                4
 Область хранения FSTENV/FLDENV          4 или 2, в зависимости от
                                            размера операнда
 Область хранения FSAVE/FRSTOR           4 или 2, в зависимости от
                                            размера операнда
 Битовая строка                                  4
 -----------------------------------------------------------------
 
 Проверку выравнивания полезно использовать в программах, в
 которых два младших бита указателей служат для идентификации
 адресуемой ими структуры данных. Например, подпрограмма в
 библиотеке математических функций может принимать указатели на
 числовые структуры данных. Если типу этой структуры в двух
 младших битах указателей на этот тип назначен код 10 (двоичный),
 математические подпрограммы могут выполнить для этого кода типа
 коррекцию, добавляя смещение -10 (двоичное). Если подпрограмма
 получит неверный тип указателя, то произойдет невыравненная
 ссылка, что приведет к генерации исключения.
 
 Сбои проверки выравнивания генерируются только в режиме
 пользователя (уровень привилегированности 3). Ссылки к памяти с
 уровнем привилегированности по умолчанию 0, такие как загрузка
 дескриптора сегмента, не генерируют сбоев проверки выравнивания,
 даже если они вызваны ссылками к памяти, выполненными в
 пользовательском режиме.
 
 Запись 48-разрядного псевдо-дескриптора (образа памяти для
 содержимого базового регистра таблицы дескрипторов) в режиме
 пользователя может генерировать сбой проверки выравнивания. Хотя
 программы режима пользователя обычно не сохраняют
 псевдо-дескрипторов, такого сбоя можно избежать, выравнивая
 псевдодескриптор по адресу нечетного слова (т.е. адресу,
 являющемуся 2 MOD 4).
 
 Команды FSAVE и FRSTOR генерируют невыравненные ссылки, которые
 могут вызвать сбой проверки выравнивания. Прикладным программам
 эти команды нужны редко.
 
 9.10  Обзор исключений
 -----------------------------------------------------------------
 
 Обзор исключений, распознаваемых процессором i486, приводится в
 Таблице 9-7.
 
 9.11  Обзор кодов ошибки
 -----------------------------------------------------------------
 
 Обзор информации об ошибках, доступных для каждого исключения,
 приводится в Таблице 9-8.
 
                  Таблица 9-7. Обзор исключений
 
 -----------------------------------------------------------------
 Описание        Номер   Адрес возврата    Тип        Источник
                 вектора указывает на     исключения  исключения
                         сбойную команду?
 -----------------------------------------------------------------
 Деление на ноль    0           Да        Сбой        Команды DIV
                                                      и IDIV
 
 Отладочные         1           *1        *1          Любая ссылка
 исключения                                             к коду или
                                                      данным
 
 Контрольная точка  3           Нет       Ловушка     Команда INT 3
 
 Переполнение       4           Нет       Ловушка     Команда INTO
 
 Проверка диапазона 5           Да        Сбой        Команда BOUND
 
 Неверный код       6           Да        Сбой      Резервированные
 операции                                           коды операции
 
 Устройство         7           Да        Сбой        Команды ESC
 недоступно                                           и WAIT
 
 Двойной сбой       8           Да        Аварийное   Любая команда
                                          завершение
                                               2
 Неверный TSS      10           Да        Сбой      Команды JMP,
                                                    CALL, RET,
                                                    прерывания и
                                                    особые ситуации
 
 Сегмент не        11           Да        Сбой        Любая команда,
 присутствует                                         изменяющая
                                                      сегмент
 
 Сбой в стеке      12           Да        Сбой        Стековые
                                                      операции
 
 Общая защита      13           Да        Сбой/  3    Любая ссылка
                                          Ловушка     к коду или
                                                      данным
 
 Страничный сбой   14           Да        Сбой        Любая ссылка
                                                      к коду или
                                                      данным
                                              4
 Ошибка операции   16           Да        Сбой        Команды ESC
 с плавающей                                          и WAIT
 точкой
 
 Проверка          17            Да       Сбой        Любая ссылка
 выравнивания                                         к данным
 
 Программное        от 0           Нет    Ловушка     Команды INT n
 прерывание        до 255
 -----------------------------------------------------------------
 
 1. Отладочные исключения это либо ловушки, либо сбои. Обработчик
    исключений может делать различие между ловушками и сбоями,
    исследовав содержимое регистра DR6.
 
 2. Исключение "неверный TSS" недопускает рестарт, если она
    произошла во время обработки прерывания или исключения.
 
 3. Сбои общей защиты позволяют рестарт. Если сбой произошел при
    попытке вызова обработчика, то прерванная программа позволяет
    рестарт, но прерывание может быть потеряно.
 
 4. Сообщения об ошибках операций с плавающей точкой не выдаютс
    до первой команды ESC или команды WAIT, следующей за командой
    ESC, сгенерировавшей ошибку.
 
 Обзор кодов ошибки                                    Таблица 9-8
 -----------------------------------------------------------------
 Описание                          Номер       Генерируется ли
                                  вектора        код ошибки ?
 -----------------------------------------------------------------
 Ошибка деления                      0              Нет
 Отладочные исключения               1              Нет
 Контрольная точка                   3              Нет
 Переполнение                        4              Нет
 Проверка диапазона                  5              Нет
 Неверный код операции               6              Нет
 Устройство недоступно               7              Нет
 Двойной сбой                        8          Да (всегда ноль)
 Неверный TSS                       10              Да
 Сегмент не присутствует            11              Да
 Сбой сегмента                      12              Да
 Общая защита                       13              Да
 Страничный сбой                    14              Да
 Ошибка операции с плавающей точкой 16              Нет
 Проверка выравнивания              17          Да (всегда ноль)
 Программное прерывание            0-255            Нет
 -----------------------------------------------------------------
 
 
 
 
 Глава 11  Отладка
 -----------------------------------------------------------------
 
 Процессор i486 обеспечивает расширенные отладочные средства,
 которые в частности полезны для разработки сложных программных
 систем, таких как мультизадачные операционные системы. Условия
 сбоя для этих программных систем могут быть очень сложными и
 зависимыми от времени. Отладочные средства процессора i486
 предоставляют системному программисту мощный инструмент
 просмотра динамического состояния процессора.
 
 Отладка поддерживается посредством отладочных регистров. Они
 содержат адреса точек памяти, называемых контрольными точками
 (точками останова), которые запускают отладочное программное
 обеспечение. При выполнении операции с памятью по одному из этих
 адресов генерируется исключение. Контрольная точка задается для
 конкретной формы доступа к памяти, например выборки команды или
 операции записи двойного слова. Отладочные регистры поддерживают
 как контрольные точки команд, так и контрольные точки данных.
 
 Для других процессоров контрольные точки команд устанавливаются
 заменой нормальных команд командами контрольных точек. При
 выполнении команды контрольной точки вызывается отладчик. Однако
 в случае отладочных регистров процессора i486 это не
 обязательно. Исключая необходимость записи в пространство кода,
 процесс отладки упрощается (не требуется установка отображения
 сегментов данных в ту же область памяти, что и кодовый сегмент),
 и контрольные точки могут устанавливаться в ПЗУ -резидентном
 программном обеспечении. Кроме того, контрольные точки могут
 быть установлены для чтения и записи данных, что позволяет
 контролировать состояние данных в режиме реального времени.
 
 11.1  Поддержка отладки
 -----------------------------------------------------------------
 
 В число средств архитектуры, поддерживающих отладку, входят:
 
 - Резервируемый отладочный вектор прерывания - задает процедуру
   или задачу, когда происходит событие, важное для отладчика.
 
 - Отладочные адресные регистры - задают адреса до четырех
   контрольных точек.
 
 - Отладочный управляющий регистр - задает формы доступа к памяти
   для контрольных точек.
 
 - Отладочный регистр состояния - сообщает об условиях, которые
   существовали в момент генерации исключения.
 
 - Бит ловушки в TSS (T-бит) - генерирует отладочное исключение
   при попытке выполнить переключение задачи на задачу, для
   которой этот бит был установлен.
 
 - Флаг возобновления (RF) - подавляет возобновление
   множественных исключений для одной и той же команды.
 
 - Флаг ловушки (TF) - генерирует отладочное исключение после
   каждого выполнения команды.
 
 - Команда контрольной точки - Вызывает отладчик (генерирует
   отладочное исключение. Данная команда является альтернативным
   способом установки контрольных точек в коде. Она особенно
   полезна, когда желательно иметь более четырех контрольных точек,
   либо при помещении контрольных точек в исходный код.
 
 - Резервируемый вектор прерывания для исключения контрольной
   точки - вызывает процедуру или задачу при выполнении команды
   контрольной точки.
 
 Эти средства позволяют вызывать отладчик как отдельную задачу
 или процедуру в контексте текущей задачи. Для вызова отладчика
 могут быть использованы следующие условия:
 
      - Переключение на конкретную задачу.
 
      - Выполнение команды контрольной точки.
 
      - Выполнение любой команды.
 
      - Выполнение команды по заданному адресу.
 
      - Чтение или запись  байта,  слова  или  двойного  слова  по
        конкретному заданному адресу.
 
      - Запись  в  байт,  слово  или  двойное  слово  по заданному
        адресу.
 
      - Попытка изменить содержимое отладочного регистра.
 
 11.2  Отладочные регистры
 -----------------------------------------------------------------
 
 Для управления отладкой используется шесть регистров. Доступ к
 этим регистрам выполняется с помощью разновидностей команды MOV.
 Отладочный регистр может быть исходным операндом или операндом
 назначения этих команд. Отладочные регистры относятся к
 привилегированным ресурсам; команды MOV могут обращаться к ним
 только на уровне привилегированности 0. Попытка чтения или
 записи в отладочные регистры с других уровней
 привилегированности генерирует исключение общей защиты. На
 Рисунке 11-1 показан формат отладочных регистров.
 
 11.2.1  Отладлчные адресные регистры (DR0-DR3)
 -----------------------------------------------------------------
 
 Каждый из этих регистров содержит линейный адрес одной из
 четырех контрольных точек. При разрешенной подкачке страниц эти
 адреса транслируются в физические адреса по алгоритму подкачки
 страниц. Условие каждой контрольной точки определяется
 содержимым регистра DR7.
 
 11.2.2  Отладочный управляющий регистр (DR7)
 -----------------------------------------------------------------
 
 Показанный на Рисунке 11-1 отладочный управляющий регистр задает
 вид доступа к памяти, связанный с каждой контрольной точкой.
 Каждый адрес в регистрах DR0 - DR3 соответствует полю R/W0 -
 R/W3 в регистре DR7. процессор интерпретирует их следующим
 образом:
 
      00 - Прерывание только при выполнении команды
      00 - Прерывание только при записи данных
      10 - не определено
      11 -  прерывание  при  чтении  и  записи  данных,  но не при
            выборке команды
 
                    Отладочные регистры
 
  3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 -----------------------------------------------------------------
 | L | R | L | R | L | R | L | R |           | | | | | | | | | | |
 | E | / | E | / | E | / | E | / |0 0 0 0 0 0|G|L|G|L|G|L|G|L|G|L|DR7
 | N | W | N | W | N | W | N | W |           |E|E|3|3|2|2|1|1|0|0|
 | 3 | 3 | 2 | 2 | 1 | 1 | 0 | 0 |           | | | | | | | | | | |
 |---------------------------------------------------------------|
 |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|B|B|B|0 0 0 0 0 0 0 0 0|B|B|B|B|DR6
 |                               |T|S|D|                 |3|2|1|0|
 |---------------------------------------------------------------|
 |                       Зарезервировано                         |DR5
 |---------------------------------------------------------------|
 |                       Зарезервировано                         |DR5
 |---------------------------------------------------------------|
 |                Физический адрес контрольной точки 3           |
 |---------------------------------------------------------------|
 |                Физический адрес контрольной точки 2           |
 |---------------------------------------------------------------|
 |                Физический адрес контрольной точки 1           |
 |---------------------------------------------------------------|
 |                Физический адрес контрольной точки 0           |
 -----------------------------------------------------------------
 
   Биты, помеченные как 0, зарезервированы. Не используйте их.
 
                Рисунок 11-1. Отладочные регистры
 
 
 Поля LEN0 - LEN3 регистра DR7 задат размер позиции памяти, для
 которой установлены контрольные точки. Может быть задан размер в
 1, 2 или 4 байта. Поля длины интерпретируются следующим образом:
 
      00 - доина один байт
      01 - длина два байта
      10 - не определено
      11 - длина четыре байта
 
 Если RWn равно 00 (выполнение команды), то LENn должно быть
 равно 00. Эффект при использовании любой другой длины
 неопределен.
 
 Младшие восемь битов регистра DR7 (поля от L0 до L3 и G0 до G3)
 по отдельности разрешают условия контрольных точек в четырех
 адресах. Существует два уровня их разрешения: локальный (от L0
 до L3) и глобальный (от G0 до G3). Локальные биты разрешения
 автоматически очищаются процессором при каждом переключении
 задачи, чтобы избежать нежелательных условий контрольных точек в
 новой задаче. Они используются для установки контрольных точек в
 одной отдельной задаче. Глобальные биты разрешения при
 переключении задачи не очищаются. Они используются для
 разрешения условий контрольной точки, применимых ко всем
 задачам.
 
 Процессор i486 всегда использует при отладке точное совпадение
 для контрольных точек данных. То есть, если какие-либо из битов
 Ln/Gn установлены, то процессор замедляет выполнение таким
 образом, что сообщение о контрольной точке данных выдается
 именно для той команды, которая вызвала срабатывание данной
 контрольной точки, а не для следующей выполняемой команды. В
 таком случае одно-тактовые команды, выполняющие доступ к памяти,
 будут занимать два тактовых цикла.
 
 Для процессора 386 DX точное совпадение для контрольных точек
 данных не происходит, если его не разрешить установкой бита LE
 или GE. Процессор i486 эти биты игнорирует.
 
 11.2.3  Отладочный регистр состояния (DR6)
 -----------------------------------------------------------------
 
 Показанный на Рисунке 11-1 отладочный регистр состояния сообщает
 об условиях, выявленных во время генерирования отладочного
 исключения. Среди прочей информации, он сообщает, какая
 контрольная точки вызвала данное исключение.
 
 Когда разрешенная контрольная точка генерирует исключение
 отладки, она загружает младшие четыре бита данного регистра (от
 B0 до B3), прежде чем войти в обработчик отладочных исключений.
 Бит B устанавливается, если условие, описанное битами DR, LEN и
 R/w истинно, даже если эта контрольная точка не разрешена битами
 L и G. Процессор устанавливает биты B для всех контрольных
 точек, для которых выполняются условия, установленные в момент
 генерации отладочного исключения, независимо от того, были ли
 они разрешены.
 
 Бит BT связан с битом Т (отладочным битом ловушки) в TSS (формат
 TSS см. в Главе 6). Процессор устанавливает бит BT перед входом
 в отладочный обработчик исключений, если переключение произошло
 на задачу с установленным битом T в TSS. В регистре DR7 не
 существует бита, позволяющего разрешить или запретить данное
 исключение, бит Т в TSS является единственным разрешающим битом.
 
 Бит BS связан с флагом TF. Бит BS устанавливается, если
 отладочное исключение произошло при пошаговом режиме выполнения
 (при установленном флаге TF). Пошаговый режим выполнения дает
 отладочное исключение с наивысшим приоритетом; когда бит BS
 установлен, любые прочие биты состояния отладки также могут быть
 установлены.
 
 Бит BD установлен, если следующая команда будет читать или
 записывать один из восьми отладочных регистров, в то время как
 они используются встроенным эмулятором.
 
 Отметим, что содержимое регистра DR6 никогда не очищается
 процессором. Чтобы избежать путаницы с идентификацией отладочных
 исключений, отладочный обработчик исключений должен перед
 возвратом очищать этот регистр.
 
 11.2.4  Распознавание поля контрольной точки
 -----------------------------------------------------------------
 
 Адрес и биты LEN для каждого из четырех условий контрольной
 точки определяют диапазон последовательных адресов байтов для
 контрольной точки данных. Биты LEN позволяют задание одно-,
 двухи четырех-байтового диапазона. Двух-байтовые диапазоны
 должны быть выравнены по границе слова (адреса, кратные двум), а
 четырех-байтовые диапазоны должны быть выравнены по границе
 двойного слова (адреса, кратные четырем). Эти требования
 принудительно устанавливаются процессором; он использует биты
 LEN для маскирования младших адресных битов в отладочных
 регистрах. Невыравненные адреса контрольных точек кода или
 данных не дадут ожидаемых результатов.
 
 Контрольная точка данных на чтение или запись срабатывает, когда
 любые из байтов, участвующих в операции доступа к памяти,
 находятся в диапазоне, определенном адресным регистром
 контрольной точки и его битами длины LEN. В Таблице 11-1
 приводится несколько примеров комбинаций адресов и полей со
 ссылками к памяти, вызывающие и не вызывающие срабатывание
 ловушки.
 
 Контрольные точки данных для невыравненного операнда могут быть
 составлены из двух наборов элементов в регистрах контрольной
 точки, где каждый отдельный элемент выравнен по границе байта, а
 два элемента вместе покрывают весь нужный операнд. Такая
 контрольная точка генерирует исключения только для операнда, но
 не для каких-либо соседних байтов.
 
 Адреса контрольных точек для команд должны иметь заданную длину
 в один байт (LEN = 00); поведение таких контрольных точек в
 случае других размеров операнда неопределено. Процессор
 распознает адрес контрольной точки команды только когда он
 указывает на первый байт команды. Если команда имеет какие-либо
 префиксы, адрес контрольной точки должен указывать на первый
 префикс.
 
             Таблица 11-1. Примеры контрольных точек
 
 -----------------------------------------------------------------
             Комментарий    |      Адрес          |    Длина
                            |(шестнадцатиричный)  |  (в байтах)
 -----------------------------------------------------------------
 Содержимое регистра  |  DR0|      A0001          |1 (LEN0 = 00)
 Содержимое регистра  |  DR1|      A0002          |2 (LEN0 = 00)
 Содержимое регистра  |  DR2|      B0002          |2 (LEN0 = 01)
 Содержимое регистра  |  DR3|      C0000          |4 (LEN0 = 11)
 ---------------------------|---------------------|---------------
                            |      A0001          |       1
                            |      A0002          |       1
                            |      A0001          |       2
 Операции с памятью,        |      A0002          |       2
 вызывающие срабатывание    |      B0002          |       2
 ловушки                    |      B0001          |       4
                            |      C0000          |       4
                            |      C0001          |       2
                            |      C0003          |       1
 ---------------------------|---------------------|---------------
 Операции с памятью,        |      A0000          |       1
 не вызывающие срабатывание |      A0003          |       4
 ловушки                    |      B0000          |       2
                            |      C0004          |       4
 -----------------------------------------------------------------
 
 11.3  Отладочные исключения
 -----------------------------------------------------------------
 
 Два вектора прерывания процессора i486 резервируются для
 отладочных исключений. Отладочные исключения являются обычным
 способом запуска отладчиков, разработанных для процессора i486;
 исключение контрольной точки предназначена для передачи
 контрольной точки в отладчик.
 
 11.3.1  Прерывание 1 - отладочные исключения
 -----------------------------------------------------------------
 
 Обработчик данного исключения обычно представляет собой отладчик
 или часть отладочной ситемы. Процессор генерирует отладочное
 исключение для любого из нескольких условий. Отладчик может
 проверять флаги в регистрах DR6 и DR7, чтобы определить, какое
 условие вызвало данное исключение и какие еще условия могут
 также являться ее причиной. В Таблице 11-2 показаны состояния
 этих битов для каждого типа условия контрольной точки.
 
 Контрольные точки команд называются сбоями; прочие отладочные
 исключения называются ловушками. Отладочное исключение
 одновременно может сообщать о каждой из них по отдельности, либо
 сразу об обеих. В следующих разделах каждый класс отладочных
 исключений описан подробно.
 
 11.3.1.1  Сбой в контрольной точке команды
 -----------------------------------------------------------------
 
 Процессор сообщает о контрольной точке команды до выполнения
 самой этой команды (т.е., отладочное исключение, вызванное
 контрольной точкой команды, относится к сбоям).
 
 Флаг RF позволяет обработчику отладочного исключения выполнять
 рестарт команд, вызвавших сбой, за исключением отладочных сбоев.
 В случае любого такого сбоя автор системного программного
 обеспечения должен установить бит RF в копии регистра EFLAGS,
 помещаемого в стек в подпрограмме-обработчике отладочного
 исключения. Этот бит подготавливает возможность возобновления
 выполнения программы с адреса контрольной точки без генерации на
 этой же команде повторного сбоя. (Примечание: бит RF не вызывает
 игнорирование ловушек контрольных точек или других видов сбоев).
 
           Таблица 11-2. Условия отладочного исключения
 
 -----------------------------------------------------------------
 Тестируемые флаги                          Описание
 -----------------------------------------------------------------
 BS = 1                         Ловушка пошагового выполнения
 B0 = 1 и (GE0 = 1 или LE0 = 1) Контрольная точка, определенная для
                                DR0, LEN0 и R/W0
 B1 = 1 и (GE1 = 1 или LE1 = 1) Контрольная точка, определенная для
                                DR1, LEN1 и R/W1
 B2 = 1 и (GE2 = 1 или LE2 = 1) Контрольная точка, определенная для
                                DR2, LEN2 и R/W2
 B3 = 1 и (GE3 = 1 или LE3 = 1) Контрольная точка, определенная для
                                DR3, LEN3 и R/W3
 BD = 1                         Отладочные регистры, используемые
                                для встроенной эмуляции
 BT = 1                         Переключение задачи
 -----------------------------------------------------------------
 
 Процессор очищает флаг RF при успешном завершении каждой
 команды, за исключением завершения команды IRET, команды POPF и
 команд JMP, CALL или INT, вызывающих переключение задачи. Эти
 команды переключают флаг RF в значение, заданное сохраненной
 копией регистра EFLAGS.
 
 Процессор устанавливает флаг RF в копии регистра EFLAGS,
 помещенной в стек перед входом в любой обработчик сбоя. Когда
 вход в обработчик сбоя выполняется для контрольных точек команд,
 например, флаг RF устанавливается в копии регистра EFLAGS,
 помещаемой в стек; следовательно, команда IRET, возвращающая
 управление из обработчика исключения, будет восстанавливать флаг
 RF в регистре EFLAGS, и выполнение возобновится в прерванной
 контрольной точкой команде без генерации для той же самой
 команды другой контрольной точки.
 
 Если после отладочного сбоя флаг RF установлен, и отладочный
 обработчик пытается повторить выполнение сбойной команды,
 возможно, что эта попытка приведет к другим сбоям. Рестарт
 команды после таких сбоев также происходит при установленном
 флаге RF, поэтому продолжается подавление повторных отладочных
 сбоев. Процессор очищает флаг RF только после успешного
 завершения команды.
 
 11.3.1.2  Ловушка контрольной точки данных
 -----------------------------------------------------------------
 
 Исключение контрольной точки данных называется ловушкой; т.е.,
 процессор генерирует исключение для контрольной точки данных
 после выполнения команды, обращающейся к позиции в памяти
 данных, для которой установлена контрольная точка.
 
 При использовании контрольных точек данных рекомендуется, чтобы
 также был установлен либо бит LE, либо GE регистра DR7. При
 установленном бите LE или GE любая ловушка точки останова данных
 срабатывает немедленно после завершения команды, выполнившей
 доступ к позиции в памяти, для которой была установлена
 контрольная точка. Немедленное сообщение выполняется путем
 принудительного ожидания исполнительным модулем процессора
 завершения пересылки операнда данных перед началом выполнения
 следующей команды. Если ни один из указанных битов не
 установлен, контрольные точки данных не могут генерироваться до
 команды, следующей за выполнившей этот доступ к данным, либо не
 могут генерироваться вообще. Это происходит потому, что обычно
 выполнение команд перекрывается по времени с переносом данных в
 памяти. Выполнение следующей команды может начаться до
 завершения операций с памятью предыдущей команды.
 
 Если отладчику требуется сохранить содержимое позиции
 контрольной точки, куда выполняется запись, он должен сохранить
 исходное содержимое до установки контрольной точки. Поскольку
 контрольные точки данных являются ловушками, исходные данные
 затираются до генерации исключения ловушки. Обработчик может
 сообщить сохраненное значение после срабатывания контрольной
 точки. Данные в отладочных регистрах могут быть использованы для
 адресации нового значения, записанного командой, которая привела
 к срабатыванию контрольной точки.
 
 11.3.1.3  Сбой общего обнаружения
 -----------------------------------------------------------------
 
 Сбой общего обнаружения происходит при попытке использования
 отладочных регистров в то время, как они используются встроенной
 эмуляцией. Такая дополнительная защита гарантирует эмулятору
 полное управление над всеми отладочными регистрами, когда ему
 это требуется. Обработчик исключений может обнаруживать это
 условие, проверяя состояние бита BD регистра DR6.
 
 11.3.1.4  Ловушка пошагового выполнения
 -----------------------------------------------------------------
 
 Эта ловушка происходит после выполнения команды, если до
 выполнения команды был установлен флаг TF. Отметим, что данное
 исключение не происходит после выполнения команды,
 устанавливающей флаг TF. Например, если команда POPF
 используется для установки флага TF, то ловушка пошагового
 выполнения не происходит до следующей после POPF команды.
 
 Процессор очищает флаг TF перед вызовом обработчика исключения.
 Если флаг TF был установлен в TSS во время переключения задачи,
 то исключение может произойти после выполнения первой
 команды новой задачи.
 
 Флаг пошагового выполнения не очищается при изменении
 привилегированности внутри задачи. Однако, команды INT очищают
 флаг TF. Следовательно, отладчики программного обеспечения с
 пошаговым выполнением кода должны распознавать и эмулировать
 команды INT n или INTO, а не выполнять их непосредственно.
 
 Для обслуживания средств защиты операционная  система  должна
 проверять текущий   уровень   привилегированности   после   каждой
 пошаговой ловушки,  чтобы  проверить,  что   на   текущем   уровне
 привилегированности пошаговое выполнение может быть продолжено.
 
 Приоритеты прерываний гарантируют, что в случае внешнего
 прерывания пошаговое выполнение остановится. Когда внешнее
 прерывание и ловушка пошагового выполнения происходят
 одновременно, первым обрабатывается прерывание пошагового
 выполнения. Оно очищает флаг TF. После сохранения адреса
 возврата или переключения задачи вход внешнего прерывания
 исследуется до выполнения первой команды обработчика пошаговой
 ловушки. Если внешнее прерывание все еще ожидает обработки, то
 оно обслуживается. Обработчик внешних прерываний в режиме
 пошагового выполнения не работает. Для выполнения его за один
 шаг выполните вызывающую обработчик прерывания команду INT n.
 
 11.3.1.5  Ловушка переключения задачи
 -----------------------------------------------------------------
 
 Отладочное исключение происходит также после переключения задачи
 при установленном бите T в TSS новой задачи. Исключение
 происходит после передачи управления новой задаче, но перед
 выполнением первой команды новой задачи. Обработчик исключения
 может обнаружить это условие, исследуя состояние бита BT
 регистра DR6.
 
 Отметим, что если отладчик отладочного исключения представляет
 собой задачу, то бит T в ее TSS не должен быть установлен.
 Нарушение этого правила может привести к зацикливанию
 процессора.
 
 11.3.2  Прерывание 3 - команда контрольной точки
 -----------------------------------------------------------------
 
 Ловушка контрольной точки вызывается выполнением команды INT 3.
 Обычно отладчик подготавливает контрольную точку, заменяя первый
 байт кода операции команды кодом операции команды контрольной
 точки. Когда выполнение команды INT 3 вызывает обработчик
 исключения, адрес возврата указывает на первый байт команды,
 следующей за командой INT 3.
 
 В более старых процессорах это средство  широко  используется
 для  установки  контрольных точек в командах.  В случае процессора
 i486 это легче реализовать с использованием  отладочных регистров.
 Однако, исключение контрольной точки полезно использовать для
 установки контрольных точек в отладчике, так как исключение
 контрольной точки позволяет ему вызывать обработчик исключения,
 отличный от самого себя. Исключение контрольной точки также
 может быть полезно, когда требуется установить больше
 контрольных точек, чем позволяют отладочные регистры, либо при
 их помещении в исходный код разрабатываемой программы.
 
 
 
 
 Глава 18. Вычисления
 ----------------------------------------------------------------
 
 
 18.1 Средства программирования
 ----------------------------------------------------------------
 
 В этой главе дано описание вычислительных возможностей
 процессора i486(TM) для программистов, работающих с языками
 высокого уровня и на ассемблере ASM386/486.
 
 Уровень детализации этой главы дает программистам понимание
 основных навыков, которые могут быть использованы для
 программирования вычислений, но эта информация не является
 полной документацией по описанию всех возможностей процессора.
 Полная документация поставляется с каждым программным продуктом.
 
 18.2 Языки высокого уровня
 ----------------------------------------------------------------
 
 Большое количество языков высокого уровня, которые по
 необходимости автоматически используют множество вычислительных
 команд, создано для процессоров фирмы Intel(R). Эти
 языки включают C-386/486 и PL/M-386/486. Но многие
 компиляторы языков высокого уровня поставляются независимыми
 организациями, разрабатывающими программное обеспечение.
 
 Каждый из языков высокого уровня имеет специальные числовые
 библиотеки, позволяющие программам воспользоваться возможностями
 модуля обработки операций с плавающей точкой. При
 программировании численных операций в любом из этих языков для
 использования этого модуля не нужны никакие программные
 добавления.
 
 Программисты, работающие на PL/M-386/486 и на ассемблере
 ASM386/486, также могут использовать многие из
 программ, содержащихся в библиотеке поддержки языка. Эти
 библиотеки включают многие функции, поддерживаемые языками
 высокого уровня, включая обработчики исключенций,
 преобразователи кодов ASCII в числа с плавающей точкой, и более
 сложное множество трансцендентных функций, чем то множество
 числовых операций, которое поддерживает процессор i486.
 
 18.1.2 Программы на языке Си
 ----------------------------------------------------------------
 
 Программисты, работающие на языке Си, при использовании типов
 данных double или float автоматически используют для
 генерирования числовых операций i486 процессора компилятор языка
 Си. Тип float соответствует обычному вещественному формату; тип
 double соответствует вещественному формату двойной точности.
 Команда #include  вызывает математические функции, такие
 как sin, cos для получения величин типа double. Рисунок 18
 иллюстрирует пример программы на Си, демонстрирующий
 использование возможностей процессора i486.
 
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?     /********************************************             ?
 ?     *                                           *             ?
 ?     *             Пример программы на Си        *             ?
 ?     *                                           *             ?
 ?     *********************************************/            ?
 ?                                                               ?
 ?   /** по необходимости подключить /usr/include/stdio.h  **/   ?
 ?   /** для трансцендентных функций подключить math **/         ?
 ?                                                               ?
 ?   #include                               ?
 ?   #define Pi 3.1415926535897943                               ?
 ?                                                               ?
 ?   main()                                                      ?
 ?   {                                                           ?
 ?     double       sin_result, cos_result;                      ?
 ?     double       angle_deg = 0.0, angle_rad;                  ?
 ?     int          i, no_of_trail = 4;                          ?
 ?                                                               ?
 ?           for ( i = 1; i <= no_of_trail; i++){                ?
 ?                angle_rad = angle_deg * Pi / 180.0;            ?
 ?                sin_result = sin (angle_rad);                  ?
 ?                cos_result = cos(angle_result);                ?
 ?     printf("синус %f градусов равен %f\n",angle_deg,          ?
 ?             sin_result);                                      ?
 ?     printf("косинус %f градусов равен %f\n",angle_deg,        ?
 ?             cos_result);                                      ?
 ?                angle_deg = angle_deg + 30.0;                  ?
 ?               }                                               ?
 ?      /**  так далее  **/                                      ?
 ?   }                                                           ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
          Рисунок 18-1. Пример программы на языке Си-386/486.
 
 
 18.1.3 PL/M-386/486
 ----------------------------------------------------------------
 
 Программисты, работающие на языке PL/M-386/486, могут получить
 доступ к очень полезному подмножеству возможностей
 процессораi486. Тип данных REAL языка PL/M-386/486 соответствует
 обычному вещественному формату (32 бита). Этот тип данных дает
 диапазон чисел порядка 8.43 x 10**(-37) <= ?X? <= 3.38 x
 10**(38) и имеет около семи значимых десятичных цифр. Такое
 представление чисел отвечает многим применениям
 микрокомпьютеров. Преимущество при использовании типа данных
 REAL в том, что промежуточные результаты при вычисленииях
 представляются компилятором языка PL/M-386/486 в расширенном
 вещественном формате. Это означает, что полный диапазон
 представления чисел и точности процессора используется для
 промежуточных вычислений. Переполнение, отрицательное
 переполнение, ошибки округления более вероятны во время
 промежуточных вычислений, чем при получении конечного
 результата. Представление промежуточных результатов в
 вещественном формате с расширенной точностью уменьшает
 вероятность переполнения, отрицательного переполнения и
 исключает ошибки округления, как серьезные ошибки, до достижения
 конца вычислений.
 
 Компилятор генерирует команды по обработке чисел с плавающей
 точкой для вычисления выражений, содержащих тип данных REAL в
 виде переменных или констант. Это означает, что сложение,
 вычитание, умножение, деление, сравнение и присваивание чисел
 типа REAL осуществляется модулем обработки данных с плавающей
 точкой. С другой стороны, выражения типа INTEGER вычисляются
 модулем обработки целочисленных операций.
 
 Пять встроенных процедур (Таблица 18-1) дают программисту,
 работающему на языке PL/M-386/486 доступ к командам управления
 модулем по обработке данных с плавающей точкой. Перед любой
 арифметической операцией обычная программа на PL/M-386/486 будет
 инициализировать модуль, используя процедуру INIT$REAL$MATH$
 UNIT, а затем для настройки конфигурации установит режим
 SET$REAL$MODE. Процедура SET$REAL$MODE загружает управляющее
 слово модуля обработки данных с плавающей точкой, и его
 16-разрядный параметр имеет формат, указанный для управляющеего
 слова в Главе 14. Рекомендуемая величина этого параметра - 033H
 (округление до ближайшего, точность 64 бита, блокировка
 исключений устраняет ошибочные команды). Другие процедуры могут
 использоваться по усмотрению программиста.
 
 Если любая исключение не заблокировано, то обработчик
 исключений должен иметь процедуру обработки в форме процедуры
 прерывания, которая вызывается через вектор прерывания номер 16.
 Обработчик может использовать процедуру GET$REAL$ERROR для
 получения младшего байта слова состояния модуля обработки
 операций с плавающей точкой и затем очистить флаги маски
 исключения. Байт, возвращаемый процедурой GET $REAL $ERROR
 cодержит флаги маски, которые могут быть проанализированы для
 определения номера исключения.
 
 Процедуры SAVE$REAL$STATUS и RESTORE$REAL$STATUS обеспечивают
 многозадачный режим работы, в котором выполняемая задача,
 использующая модуль обаботки операций с плавающей точкой, может
 быть прервана другой задачей, также использующей модуль
 обработки операций с плавающей точкой. Операционная система
 отвечает за выполнение процедуры SAVE$REAL$STATUS перед
 выполнением любой команды, которая может повлиять на модуль
 обработки операций с плавающей точкой. Это процедуры INIT$REAL$
 MATH$UNIT и SET$REAL$MODE, а также арифметические команды.
 Процедура SAVE$REAL$STATUS сохраняет состояние модуля обработки
 операций с плавающей точкой (регистры, статус, управляюще слово
 и так далее) в стеке памяти. Процедура RESTORE$ REAL$STATUS
 восстанавливает информацию о состоянии; прерванная задача может
 вызвать эти процедуры для восстановления состояния модуля
 обработки операций с плавающей точкой во время выполнения. Это
 дает возможность прерванной задаче начать выполнение с того
 места, когда задача была прервана.
 
     Тавблица 18-1.Встроенные процедуры языка PL/M-386/486
 
 ?????????????????????????????????????????????????????????????????
 ?                     ?  Команда   ?                            ?
 ?      Процедура      ? управления ?          Описание          ?
 ?                     ?    FPU     ?                            ?
 ?????????????????????????????????????????????????????????????????
 ? INIT$REAL$MATH$UNIT ?   FINIT    ? Инициализирует FPU         ?
 ? STE$REAL$MODE       ?   FLDSW    ? Устанавливает маски исклю- ?
 ?                     ?            ? чений,  точность  округле- ?
 ?                     ?            ? ния и управление бесконеч- ?
 ?                     ?            ? ностью                     ?
 ? GET$REAL$ERROR      ?   FNSTSW   ? Сохраняет, а затем очищает ?
 ?                     ?   &FNCLEX  ? значение флагов            ?
 ? SAVE$REAL$STATUS    ?   FNSAVE   ? Сохраняет состояние FPU    ?
 ? RESTORE$REAL$STATUS ?   FRSTOR   ? Восстанавливает состояние  ?
 ?                     ?            ?           FPU              ?
 ?????????????????????????????????????????????????????????????????
 
 18.1.4 Ассемблер ASM386/486
 ----------------------------------------------------------------
 
 Ассемблер ASM386/486 дает программисту полный доступ ко всем
 возможностям процессора.
 
 18.1.4.1 Определение данных
 ----------------------------------------------------------------
 
 Директивы ассемблера ASM386/486, указанные в таблице 18-2,
 выделяют память для числовых переменных и констант. Как и другие
 директивы по распределению памяти, ассемблер связывает тип с
 любой переменной, определенной с помощью этих директив. Величина
 типа измеряется в единицах памяти - байтах(10 для DT, 8 для DQ).
 Ассемблер проверяет соответствие типа переменной, используемой в
 команде, самой команде. Например, команда FIADD ALPHA будет
 ошибочна, если тип переменной ALPHA имеет величину, не равную 2
 или 4 байтам, так как целочисленное сложение определено только для
 данных типа слово или короткое целое (двойное слово). Тип
 операнда также сообщает ассемблеру какую машинную команду
 выполнять: хотя для программиста существует только одна команда
 FIADD, но для операндов различного типа требуются различные
 машинные команды.
 
 Иногда разумно использовать команду с операндом, тип которого не
 объявлен. Например, если регистр BX содержит указатель на
 переменную типа короткое целое, то программист может пожелать
 определить команду FIADD [BX]. Это может быть достигнуто
 информированием процессора о типе операнда в команде, то есть
 FIADD DWORD PTR [BX]. Соответствующие преобразователи для других
 рапределений памяти -  WORD PTR, QWORD PTR и TBYTE PTR.
 
 Однако ассемблер не проверяет типы операндов, используемых в
 командах управления процессором. Команда FRSTOR [BP]
 подразумевает, что программист поместил в регистр BP указатель
 на место (возможно в стеке), в котором заранее была сохранена
 запись о состоянии процессора размером 94 байта.
 
 Начальное значение для числовых констант может быть получено
 несколькими способами. Двоичные целые константы могут быть
 определены как битовые строки, десятичные целые, восьмеричные
 целые или шестнадцатиричные строки. Упакованные десятичные
 величины обычно записываются как десятичные целые, хотя
 ассемблер будет принимать и обрабатывать и другие представления
 целых. Вещественные величины могут записываться как обычные
 вещественные десятичные числа (с десятичной точкой), как
 десятичные числа в научной нотации или как шестнадцатиричные
 строки. Использование шестнадцатиричных строк первоначально было
 предназначено для определения специальных величин, таких как
 бесконечности, NaNs и ненормализованные числа. Большинство
 программистов найдут, что обычные и научные десятичные дают
 простейший способ инициализации числовых констант. На
 рисунке 18-2 дан пример, показывающий несколько способов
 пррисвоения данным различных числовых типов одной и той же
 начальной величины.
 
     Таблица 18-2. Директивы распределения памяти ASM386/486.
 ?????????????????????????????????????????????????????????????????
 ?  Директивы  ?    Интерпретация     ?       Типы данных        ?
 ?????????????????????????????????????????????????????????????????
 ?    DW       ?  Определить слово    ? Целое слово              ?
 ?    DD       ?  Определить двойное  ? Короткое целое, короткое ?
 ?             ?     слово            ? вещественное             ?
 ?    DQ       ?  Определить слово    ? Длинное целое, длинное   ?
 ?             ?   длиной 4 байта     ? вещественное             ?
 ?    DT       ?  Определить 10 байтов? Упакованное десятичное,  ?
 ?             ?                      ? временное вещественное   ?
 ?????????????????????????????????????????????????????????????????
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?  ; ПРИМЕР ОПРЕДЕЛЕНИЯ КОНСТАНТЫ -126                          ?
 ?  ;                                                            ?
 ?  ;EVEN           ; выравнение слов в памяти                   ?
 ?  WORD-INTEGER     DW   111111111000010B ; битовая строка      ?
 ?  SHORT_INTEGER    DD   0FFFFFF82H       ; шестнадцатиричная   ?
 ?                                         ; константа должна    ?
 ?                                         ; начинаться с цифры  ?
 ?  LONG_INTEGER     DQ   -126             ; обычное десятичное  ?
 ?  SINGLE_REAL      DD   -126.0           ; "научное"           ?
 ?  DOUBLE_REAL      DD   -1.26E2          ; представление       ?
 ?  PACKED_DECIMAL   DT   -126             ; обычное десятичное  ?
 ?                                         ; целое               ?
 ?  ;                                                            ?
 ?  ; в следующем определении 'C005' означает знак и порядок,    ?
 ?  ; '7E00..00' - мантисса, 'R' информирует ассемблер, что      ?
 ?  ;   представленная строка вещественного типа                 ?
 ?  ;                                                            ?
 ?  EXTENDED_REAL     DT    0C0057E00000000000000R               ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
        Рисунок 18-2. Пример числовых констант.
 
 Следует заметить, что числовые переменные и константы, следующие
 за директивой EVEN, дают уверенность, что операнды будут
 представлены выравненными словами. Наилучшее представление
 получается, когда данные преобразуются к двойным словам,
 расположенным линейно. Все числовые типы данных занимают целое
 число слов, так что если блоки переменных объявляются вместе и
 перед декларативной частью указано слово EVEN, то память не
 растрачивается попусту.
 
 18.1.4.2 Структуры и записи
 ----------------------------------------------------------------
 
 При программировании вычислений на языке ассемблера ASM386/486
 записи RECORD и структуры STRUC могут быть очень полезны. Записи
 могут использоваться для определения битовых полей
 управляющеющих слов, состояния, признака. На рисунке 18-3
 показано одно определение слова состояния и как можно его
 использовать в программе, которая опрашивает устройство
 обработки операций с плавающей точкой до тех пор, пока не
 завершилось выполнение команды.
 
 Так как структуры объединяют различные, но связанные типы данных,
 они позволяют получать данные, имитирующие  "реальный мир". То
 что структура временно может быть передвинута в памяти,
 добавляет ей гибкости. На Рисунке 18-4 дан пример простой
 структуры, которая должна быть использована для представления
 данных. По необходимости этот пример структуры может быть
 реорганизован в целях безопасности и более эффективного
 выполнения. Если два двойных вещественных поля были определены
 до целочисленных полей, тогда (поддерживая тот факт, что
 структура заменяется только адресами, делящимися на 8) все поля
 будут оптимально выравнены в памяти для обеспечения
 эффективного доступа и кеширования. Структуры также могут
 использоваться для определения информации, сохраняемой и
 получаемой с помощью команд FSTENV и FLDENV.
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?      ; резервирование памяти для слова состояния              ?
 ?      ; STATUS-WORD                                            ?
 ?      ; расположение полей слова состояния                     ?
 ?      STATUS RECORD                                            ?
 ?      &     BUSY :              1,                             ?
 ?      &     COND_CODE3 :        1,                             ?
 ?      &     STACK_TOP :         3,                             ?
 ?      &     COND_CODE2 :        1,                             ?
 ?      &     COND_CODE1 :        1,                             ?
 ?      &     COND_CODE0 :        1,                             ?
 ?      &     INT_REG :           1,                             ?
 ?      &     S_FLAG  :           1,                             ?
 ?      &     P_FLAG  :           1,                             ?
 ?      &     U_FLAG  :           1,                             ?
 ?      &     O_FLAG  :           1,                             ?
 ?      &     Z_FLAG  :           1,                             ?
 ?      &     D_FLAG  :           1,                             ?
 ?      &     I_FLAG  :           1                              ?
 ?      ;                                                        ?
 ?      REDUCE :  FPREM1                                         ?
 ?                FNSTSW   STATUS_WORD                           ?
 ?                TEST     STATUS_WORD, MASK_COND_CODE2          ?
 ?                JNZ      REDUCE                                ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
         Рисунок 18-3.Определение записи слова состояния.
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?       SAMPLE       STRUC                                      ?
 ?           N_OBS     DD    ?     ;                             ?
 ?           MEAN      DQ    ?     ;                             ?
 ?           MODE      DW    ?     ;                             ?
 ?           STD_DEV   DQ    ?     ;                             ?
 ?           ;                                                   ?
 ?           TEST_SCORES    DW   1000  DUP (?)                   ?
 ?        SAMPLE       ENDS                                      ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
               Рисунок 18-4. Определение структуры
 
 
 18.1.4.3 Методы адресации
 ----------------------------------------------------------------
 
 Доступ к числовым данным в памяти может быть получен с помощью
 методов адресации через байты ModR/M и SIB (необязательно). Это
 означает, что числовые типы данных могут быть объединены в
 совокупности данных, изменяющиеся от простых к сложным в
 соответствии с необходимостью применения. Методы адресации и
 нотация ассемблера ASM386/486, используемая для определения
 методов в командах, обеспечивают прямой и последовательный
 доступ к структурам, массивам, массивам структур и другим
 организациям данных. В таблице 18-3 даны несколько примеров
 числовых команд вместе с операндами, иллюстрирующие различные
 методы адресации.
 
             Таблица 18-3. Примеры методов адресации
 
 ??????????????????????????????????????????????????????????????????
 ?         Код                ?         Интерпретация             ?
 ??????????????????????????????????????????????????????????????????
 ?  FIADD ALPHA               ? ALPHA - простой скаляр (прямой    ?
 ?                            ? доступ)                           ?
 ?  FDIVR ALPHA, BETA         ? BETA - поле в структуре, которое  ?
 ?                            ? перекрывается с ALPHA ( прямой    ?
 ?                            ? доступ )                          ?
 ?  FMUL QWORD PTR [BX]       ? BX содержит адреса длинных вещест-?
 ?                            ? венных переменных (косвенная адре-?
 ?                            ? сация по регистру)                ?
 ?  FSUB ALPHA [SI]           ? ALPHA - массив, SI содержит смеще-?
 ?                            ? ние относительно начала массива   ?
 ?                            ? (индексный метод доступа)         ?
 ?  FILD [BP], BETA           ? BP содержит адрес структуры в сте-?
 ?                            ? ке ЦПУ, BETA - поле в структуре   ?
 ?                            ? (базированный метод доступа)      ?
 ?  FBLD TBYTE PTR [BX] [DI]  ? BX содержит адрес упакованного де-?
 ?                            ? сятичного массива, DI - смещение  ?
 ?                            ? элемента массива (индексный метод ?
 ?                            ? доступа)                          ?
 ??????????????????????????????????????????????????????????????????
 
 18.1.5 Пример сравнительного программирования
 ----------------------------------------------------------------
 
 На рисунках 18-5 и 18-6 даны примеры простой числовой программы
 ARRSUM на языках ассемблера ASM386/486 и PL/M386/486. В программе
 рассматривается массив X$ARRAY, содержащий простые вещественные
 величины от 0 до 100; целая переменная N$OF$X указывает
 размерность массива. Вычисляются три суммы:
 
 - SUM$X, сумма элементов массива
 
 - SUM$INDEXES, сумма каждого элемента, умноженного на его
   индекс, где первый элемент массива имеет индекс 1, второй - 2 и
   так далее
 
 - SUM$SQUARES, сумма квадратов элементов массива
 
 (Настоящая программа, конечно, кроме этих шагов должна сохранять
 и использовать результаты вычислений.) Управляющеему слову
 присваивается одна из величин: округление до ближайшего целого,
 64-разрядная точность, запрещение прерываний и блокировка всех
 исключений, кроме недопустимых операций. Предполагается, что
 обработчик исключений был написан с учетом недопустимой
 операции, и в случае их обнаружения они обрабатывается по
 прерыванию 16.
 
 Версия ARRSUM на языке PL/M-386/486 очень последовательна и
 иллюстрирует насколько легко в языке могут быть использованы
 числовые возможности процессора i486. После объявления
 переменных программа вызывает встроенные процедуры для
 инициализации модуля обработки операций с плавающей точкой и
 загрузки управляющего слова. Программа "очищает" пременные суммы
 и затем выполняет шаги цикла DO. Управление циклом принимает в
 расчет, что обычно в языке PL/M-386/486 индекс первого элемента
 массива имеет величину 0. При вычислении SUM$INDEXES встроенная
 процедура FLOAT преобразует величину I+1 от целого типа к
 вещественному, так как язык не поддерживает "смешанного"
 арифметического режима. Один из недостатков модуля обработки
 операций с плавающей точкой процессора i486, что он не
 поддерживает вычисления над смешанными типами данных (все
 величины преобразуются к 80-битовому вещественному формату
 расширенной точности)
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?       /**************************************************     ?
 ?        *                                                *     ?
 ?        *         МОДУЛЬ СУММА_МАССИВА                   *     ?
 ?        *                                                *     ?
 ?        **************************************************/    ?
 ?                                                               ?
 ?        array$sum:       do;                                   ?
 ?                                                               ?
 ?            declare (sum$x, sum$indexes, sum$squares) real;    ?
 ?            declare x$array(100) real;                         ?
 ?            declare (n$of$x, i) integer;                       ?
 ?            declare control $ FPU literally '033eh';           ?
 ?                                                               ?
 ?            /* Инициализация массива x$array и n$of$x */       ?
 ?            call init$real$math$unit;                          ?
 ?            call set$real$mode(control $ FPU);                 ?
 ?                                                               ?
 ?            /* Очистить суммы */                               ?
 ?            sum$x, sum$indexes, sum$squares = 0.0;             ?
 ?                                                               ?
 ?            /* Цикл по массиву с подсчетом сумм */             ?
 ?            do i = 0 to n$of$x - 1;                            ?
 ?                 sum$x = sum$x + x$array(i);                   ?
 ?                 sum$indexes = sum$indexes + (x$array(i)*      ?
 ?                 float(i+1));                                  ?
 ?                 sum$squares = sum$squares + (x$array(i)*      ?
 ?                 x$array(i));                                  ?
 ?            end;                                               ?
 ?                                                               ?
 ?            /* и так далее */                                  ?
 ?                                                               ?
 ?      end array$sum;                                           ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
       Рисунок 18-5. Пример программы на языке PL/M-386/486
 
 Версия программы на ассемблере ASM386/486 (Рисунок 18-6)
 определяет внешнюю процедуру INITFPU, которая производит
 инициализацию процессора и его эмулятора независимо от текста
 исходной программы. После определения данных, настройки
 сегментных регистров и указателя стека программа вызывает
 процедуру INITFPU и загружает управляющее слово. Вычисления
 начинаются со следующих трех команд, которые очищают три
 регистра загрузкой 0 в стек. Как показано на Р1исунке 18-7 эти
 регистры сохраняют значение вершины стека во время вычислений,
 когда временные величины помещаются и удаляются из стека.
 
 Для управления итерацией по массиву XARRAY программа использует
 цикл LOOP; в регистр EСX, содержимое которого LOOP автоматически
 уменьшает, помещается переменная N_OF_X, число суммируемых
 элементов массива. Регистр ESI используется для выборки
 (индексирования) элементов массива. Программа выполняется по
 массиву с конца к началу, так что регистр ESI инициализируется
 указателем на элемент, который должен обрабатываться. Оператор
 TYPE используется для определения числа байтов в каждом элементе
 массива. Такое представление позволяет изменить тип массива на
 вещественный двойной точности простым измененим определения (DD
 на DQ) и еще одним проходом ассемблера.
 
    Рисунок 18-6 Пример программы на языке ассемблер ASM386/486
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?           name         arraysum                               ?
 ?                                                               ?
 ?           ; Определить процедуру инициализации                ?
 ?                                                               ?
 ?           extrn        initFPU:far                            ?
 ?                                                               ?
 ?           ; Выделить память под данные                        ?
 ?                                                               ?
 ?           data         segment  rw  public                    ?
 ?           control_FPU           dw  033eh                     ?
 ?           n_of_x                dd  ?                         ?
 ?           x_array               dd  100 dup (?)               ?
 ?                                                               ?
 ?           sum_squares           dd  ?                         ?
 ?           sum_indexes           dd  ?                         ?
 ?           sum_x                 dd  ?                         ?
 ?           data         ends                                   ?
 ?                                                               ?
 ?           ; Выделить память под стек ЦПУ                      ?
 ?                                                               ?
 ?           stack        stackseg     400                       ?
 ?                                                               ?
 ?           ; Начало тела программы                             ?
 ?                                                               ?
 ?           code         segment  er  public                    ?
 ?                                                               ?
 ?           assume  ds:data, ss:stack                           ?
 ?                                                               ?
 ?           start:                                              ?
 ?               mov      ax, data                               ?
 ?               mov      ds, ax                                 ?
 ?               mov      ax, stack                              ?
 ?               mov      eax, ax                                ?
 ?               mov      esp, stackstart stack                  ?
 ?                                                               ?
 ?           ; Проинициализироавали массив x_array и             ?
 ?           ; переменную n_of_x                                 ?
 ?                                                               ?
 ?           ; Подготовить модуль обработки операций             ?
 ?           ; с плавающей точкой или его эмулятор               ?
 ?                                                               ?
 ?               call     initFPU                                ?
 ?               fldsw    control_FPU                            ?
 ?                                                               ?
 ?           ; Очистить три регистра для хранения                ?
 ?           ; результатов суммирования                          ?
 ?                                                               ?
 ?               fldz                                            ?
 ?               fldz                                            ?
 ?               fldz                                            ?
 ?                                                               ?
 ?                                                               ?
 ?           ; Установить ECX как счетчик цикла и                ?
 ?           ; ES как индекс массива x_array                     ?
 ?                                                               ?
 ?               mov      ecx, n_of_x                            ?
 ?               imul     ecx                                    ?
 ?               mov      esi, eax                               ?
 ?                                                               ?
 ?           ; ESI содержит индекс последнего элемента           ?
 ?           ; массива плюс 1                                    ?
 ?           ; Цикл по массиву с подсчетом суммы                 ?
 ?                                                               ?
 ?           sum_next:                                           ?
 ?           ; возвращение на один элемент назад                 ?
 ?           ; и помещение в стек                                ?
 ?                                                               ?
 ?               sub      esi, type x_array                      ?
 ?               fld      x_array[esi]                           ?
 ?                                                               ?
 ?           ; прибавление к сумме и копирование x               ?
 ?           ; в стек                                            ?
 ?                                                               ?
 ?               fadd     st(3), st                              ?
 ?               fld      st                                     ?
 ?                                                               ?
 ?           ; возведение в квадрат и сложение с суммой          ?
 ?           ; (index+1)                                         ?
 ?                                                               ?
 ?               fmul     st, st                                 ?
 ?               faddp    st(2), st                              ?
 ?                                                               ?
 ?           ; уменьшение индекса для следующей итерации         ?
 ?                                                               ?
 ?               dec      n_of_x                                 ?
 ?               loop     sum_next                               ?
 ?                                                               ?
 ?           ; Перемещение x в память                            ?
 ?                                                               ?
 ?           pop_results:                                        ?
 ?                fstp    sum_squares                            ?
 ?                fstp    sum_indexes                            ?
 ?                fstp    sum_x                                  ?
 ?                fwait                                          ?
 ?                                                               ?
 ?           ;                                                   ?
 ?           ; И так далее.                                      ?
 ?           ;                                                   ?
 ?           code         ends                                   ?
 ?           end    start, ds:data, ss:stack                     ?
 ?                                                               ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?                                                               ?
 ? FLDZ, FLDZ,FLDZ                   FLD X_ARRAY[SI]             ?
 ?       ??????????----------------------??????????             ?
 ? ST(0) ?  0.0   ? SUM_SQUARES     ST(0) ?  2.5   ? X_ARRAY     ?
 ?       ??????????                       ??????????             ?
 ? ST(1) ?  0.0   ? SUM_INDEXES     ST(1) ?        ? SUM_SQUARES ?
 ?       ??????????                       ??????????             ?
 ? ST(2) ?  0.0   ? SUM_X           ST(2) ?  0.0   ? SUM_INDEXES ?
 ?       ??????????                       ??????????             ?
 ?                                  ST(3) ?  0.0   ? SUM_X       ?
 ?                                        ??????????             ?
 ?           _________________________________|                  ?
 ?                                                              ?
 ?  FIADD ST(3), ST                             FLD ST           ?
 ?       ??????????----------------------??????????             ?
 ? ST(0) ?  2.5   ? X_ARRAY(19)     ST(0) ?  2.5   ? X_ARRAY(19) ?
 ?       ??????????                       ??????????             ?
 ? ST(1) ?  0.0   ? SUM_SQUARES     ST(1) ?  2.5   ? X_ARRAY(19) ?
 ?       ??????????                       ??????????             ?
 ? ST(2) ?  0.0   ? SUM_INDEXES     ST(2) ?  0.0   ? SUM_SQUARES ?
 ?       ??????????                       ??????????             ?
 ? ST(3) ?  2.5   ? SUM_X           ST(3) ?  0.0   ? SUM_INDEXES ?
 ?       ??????????                       ??????????             ?
 ?                                  ST(4) ?  2.5   ? SUM_X       ?
 ?                                        ??????????             ?
 ?           _________________________________|                  ?
 ?                                                              ?
 ?      FMUL ST, ST                  FADDP ST(2), ST             ?
 ?       ??????????----------------------??????????             ?
 ? ST(0) ?  6.25  ? X_ARRAY(19)(2)  ST(0) ?  2.5   ? X_ARRAY(19) ?
 ?       ??????????                       ??????????             ?
 ? ST(1) ?  2.5   ? X_ARRAY(19)     ST(1) ?  6.25  ? SUM_SQUARES ?
 ?       ??????????                       ??????????             ?
 ? ST(2) ?  0.0   ? SUM_SQUARES     ST(2) ?  0.0   ? SUM_INDEXES ?
 ?       ??????????                       ??????????             ?
 ? ST(3) ?  0.0   ? SUM_INDEXES     ST(3) ?  2.5   ? SUM_X       ?
 ?       ??????????                       ??????????             ?
 ? ST(4) ?  2.5   ? SUM_X                     |                  ?
 ?       ??????????                           |                  ?
 ?           _________________________________|                  ?
 ?                                                              ?
 ?     FIMUL N_of_X                  FADDP ST(2), ST             ?
 ?       ??????????----------------------??????????             ?
 ? ST(0) ?  50.0  ? X_ARRAY(19)     ST(0) ?  6.25  ? SUM_SQUARES ?
 ?       ??????????                       ??????????             ?
 ? ST(1) ?  6.25  ? SUM_SQUARES     ST(1) ?  50.0  ? SUM_INDEXES ?
 ?       ??????????                       ??????????             ?
 ? ST(2) ?  0.0   ? SUM_INDEXES     ST(2) ?  2.5   ? SUM_X       ?
 ?       ??????????                       ??????????             ?
 ? ST(3) ?  2.5   ? SUM_X                                        ?
 ?       ??????????                                              ?
 ?                                                               ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
             Рисунок 18-7 Команды и регистровый стек
 
 На Рисунке 18-7 показано содержимое регистрового стека
 модуля обработки операций с плавающей точкой во время выполнения
 команд в цикле программы. Предполагается, что программа
 находится в ее первой итерации, величина переменной N_OF_X равна
 20, и 20-й элемент массива XARRAY(19) имеет величину 2.5. По
 окончании цикла суммы извлекаются из вершины стека, и программа
 заканчивается простым перемещением сумм в переменные памяти.
 
 18.2 Параллельная обработка
 ----------------------------------------------------------------
 
 Так как модуль обработки целочисленных операций и модуль
 обработки операций с плавающей точкой являются независимыми
 устройствами, то возможно выполнение математических команд
 модулем обработки операций с плавающей точкой параллельно с
 работой модуля обработки целочисленных операций. Такое
 одновременное выполнение различных команд называется
 параллельностью.
 
 Нет специальных приемов программирования, необходимых для
 параллельного выполнения: команды модулю обработки операций с
 плавающей точкой просто размещаются в той же строке, что и
 команды модулю обработки целочисленных операций. Целочисленные и
 вещественные команды инициализируются в том же порядке, как они
 встречаются в потоке команд. Однако в силу того, что
 вещественные операции, выполняемые модулем обработки операций с
 плавающей точкой, в общем требуют больше времени, чем
 целочисленные операции, то модуль обработки целочисленных
 операций часто может выполнить несколько своих команд до того,
 как модуль обработки операций с плавающей точкой завершит
 начатую вещественную команду.
 
 Параллельность часто предполагает очевидные преимущества во
 время выполнения, однако также налагает определенные правила,
 которые должны быть соблюдены для достижения синхронизации работы
 модуля обработки операций с плавающей точкой и модуля обработки
 целочисленных операций.
 
 Все языки высокого уровня, ориентируемые на процессоры фирмы
 Intel, автоматически имеют и управляют параллельностью модуля
 обработки операций с плавающей точкой. Программисты, работающие
 на ассемблере, однако должны понимать и управлять некоторыми
 областями параллельности для достижение гибкости и эффективности
 программ. Эта глава для программистов, работающих на ассемблере,
 или программистов-профессионалов, пишущих программы на языках
 высокого уровня.
 
 18.2.1 Управление параллельностью
 ----------------------------------------------------------------
 
 Обработка вычислительных программ может быть разбита на две
 части: управление программой и арифметика. Часть по управлению
 программой выполняет такие действия как решение - какие функции
 выполнять, вычисление адресов числовых операндов и управление
 циклом. Арифметическая часть просто выполняет сложение,
 вычитание, умножение и другие операции над числовыми операндами.
 Процессор i486 предназначен для обработки этих частей раздельно
 и эффективно.
 
 Управление параллельностью требует проверки на исключение перед
 разрешением процессору изменить значение, только что
 используемое модулем обработки операций с плавающей точкой.
 Почти все числовые команды могут в случае запрещенной операции
 создать числовое исключение. Для программистов, работающих на
 языках высокого уровня, вся требуемая синхронизация
 автоматически выполняется соответствующим компилятором. Для
 работающих на ассемблере синхронизация исключений остается на
 совести программиста.
 
 Сложность в том, что программист может не ожидать, что его
 вычислительная программа может вызывать исключения, но в
 некоторых системах они могут регулярно случаться. Для лучшего
 понимания таких недоразумений рассмотрим, что может случиться,
 когда модуль обработки операций с плавающей точкой обнаружит
 исключение.
 
 В зависимости от операций, определенных проектировщиком
 программного обеспечения, в случае исключения процессор i486
 может выполнить одну из следующих совокупностей действий:
 
 * Модуль обработки операций с плавающей точкой по умолчанию
   может обрабатывать определенные исключения. Программисты могут
   наложить маску на некоторые типы исключений для указания
   модулю обработки операций с плавающей точкой, что нужно
   делать, чтобы в случае исключительной ситуации получить
   разумный результат. Обработка исключения по умолчанию
   выполняется модулем обработки операций с плавающей точкой как
   часть команды, вызвавшей исключение; никаких внешних указаний
   для исключения не дается. При обнаружении исключительной
   ситуации значение флага заносится в регистр состояния, но
   информация о том, где и когда она произошла, является
   доступной. Если модуль обработки операций с плавающей точкой
   обрабатывает все исключения по умолчанию, тогда необходимость
   синхронизации исключительных ситуации не является явной.
   Однако, как будет показано позднее, это не существенная
   причина, чтобы избегать синхронизации при разработке программ,
   использующих модуль обработки операций с плавающей точкой.
 
 * Альтернативой обработке исключений по умолчанию является
   информирование модуля обработки целочисленных операций о
   случившейся исключительной ситуации. Если имело место
   немаскированное исключение, то модуль обработки операций с
   плавающей точкой приостанавливает дальнейшее выполнение
   числовых команд и сигнализирует о случившемся. При обнаружении
   команды ESC или WAIT управление передается обработчику
   исключений. Обработчик исключений сам выбирает процедуру
   обработки любого исключения, обнаруженного модулем обработки
   операций с плавающей точкой. Некоторые команды ESC не
   осуществляют проверки на исключения. Это FNINIT, FNSTENV,
   FNSAVE, FNSTCW и FNCLEX.
 
 Когда модуль обработки операций с плавающей точкой сигнализирует
 о немаскированном исключении, то это означает, что ему требуется
 помощь. Тот факт, что исключение не было маскировано, указывает,
 что дальнейшее выполнение программы модулем обработки операций с
 плавающей точкой неразумно.
 
 Если разрешается параллельное вычисление, то состояние
 процессора при обнаружении исключения неопределено. Во
 время исключения могли быть изменены некоторые внутренние
 регистры и выполнены совершенно различные программы. Для
 обработки такой ситуации модуль обработки операций с плавающей
 точкой имеет специальные регистры, обновляемые в начале каждой
 числовой команды, которые позволяют определить состояние
 программы, чтобы попытаться повторенить неудачную команду.
 
 При синхронизации исключений надо иметь уверенность, что
 модуль обработки операций с плавающей точкой находится в
 хорошо определенном состоянии после случившегося
 немаскированного исключения. Без такого определенного состояния
 программа обработки исключения не могла бы определить причину
 исключительной ситуации и успешно восстановить работу.
 
 В следующих двух главах иллюстрируется необходимость
 рассмотрения синхронизации исключений при написании числовых
 программ, даже если первоначально предполагалось выполнение без
 маскирования исключений. Если программа будет позднее
 помещена, где исключения не маскированы, то она может работать
 неправильно. Пример, когда несколько команд , написанных без
 синхронизации исключений, будет работать правильно, однако
 провалится при перенесении в другую среду, приведен на Рисунке
 18-8.
 
 
 18.2.1.1 Некорректная синхронизация исключений
 ----------------------------------------------------------------
 
 На Рисунке 18-8 даны три команды загрузки целого, вычисления его
 квадратного корня и уменьшение целого на 1. Синхронная
 работа модуля обработки операций с плавающей точкой разрешит
 этой программе работать правильно до тех пор, пока команда FILD
 не сгенерирует исключения.
 
 ?????????????????????????????????????????????????????????????????
 ?                                                               ?
 ?                 НЕКОРРЕКТНАЯ СИНХРОНИЗАЦИЯ                    ?
 ?                                                               ?
 ?          FIELD     COUNT  ; команда FPU                       ?
 ?          INC       COUNT  ; целочисленная команда изменения   ?
 ?                           ; операнда                          ?
 ?          FSQRT            ; ошибка из предыдущей команды FPU  ?
 ?                           ; обнаружена здесь                  ?
 ?                                                               ?
 ?                 КОРРЕКТНАЯ СИНХРОНИЗАЦИЯ                      ?
 ?                                                               ?
 ?          FIELD     COUNT  ; команда FPU                       ?
 ?          FSQRT            ; ошибка из предыдущей команды FPU  ?
 ?                           ; обнаружена здесь                  ?
 ?          INC       COUNT  ; целочисленная команда изменения   ?
 ?                           ; операнда                          ?
 ?                                                               ?
 ?                                                               ?
 ?????????????????????????????????????????????????????????????????
 
          Рисунок 18-8. Примеры синхронизации исключений.
 
 Ситуация изменяется, если расширить регистровый стек в память. В
 этом случае недопустимое исключение не маскировано. Попытка
 извлечения из пустого стека или помещения в полный вызывет
 недопустимое исключение.
 
 Прграмма обработки исключений должна распознать эту ситуацию,
 исправить значение стека и выполнить первоначальную операцию. В
 примере, показанном на рисунке, программа обработки будет
 работать неверно. Проблема в том, что значение переменной COUNT
 увеличивается до вызова обработчика исключений, поэтому
 программа обработки получит неправильное значение переменной
 COUNT, что приведет к непредсказуемому поведению программы.
 
 18.2.1.2 Корректная синхронизация исключений
 ----------------------------------------------------------------
 
 Команда WAIT отвечает за синхронизацию исключений. В случае
 немаскированного исключения модуль обработки операций с
 плавающей точкой сигнализирует процессору об ошибке. При
 обнаружении команды WAIT (или неуправляющей команды ESC) сигнал
 об ошибке подтверждается и вызывается программный обработчик
 исключений. (Для более детальной информации о различных
 механизмах обнаружения ошибок в операциях с плавающей точкой
 смотри главу 16.) Если команда WAIT или ESC расположена
 правильно, то информация, необходимая процессору для обработки
 исключений, еще не будет нарушена.
 
 
 
 Глава 19. Замечания о системном уровне
 ----------------------------------------------------------------
 
 Системное программирование для процессора i486(TM) требует более
 детального понимания структуры модуля обработки операций с
 плавающей точкой, чем прикладное программирование. За работу
 таких функций, как инициализация, обработка исключений и
 синхронизация данных и ошибок, отвечает системный программист.
 Это и рассматривается подробно в настоящей главе.
 
 19.1 Архитектура
 ----------------------------------------------------------------
 
 На программном уровне модуль обработки операций с плавающей
 точкой является расширением модуля обработки целочисленных
 операций. Однако на уровне аппаратуры механизм взаимодействия
 между этими модулями более сложный. В настоящем разделе описано
 это взаимодействие и свойства, заинтересующие системного
 программиста.
 
 19.1.1 Независимость способа адресации
 ----------------------------------------------------------------
 
 В отличии от процессора 80287 NPX (но подобно 387(TM) NPX)
 модуль обработки операций с плавающей точкой процессора i486
 работает независимо от того, работает процессор в режиме
 реальной адресации, в защищенном режиме или в виртуальном режиме
 процессора 8086.
 
 Числовые команды могут использовать любое место памяти,
 доступное задаче, выполняемой в настоящий момент. При работе в
 защищенном режиме все ссылки на операнды памяти автоматически
 проверяются системой управления памятью и механизмами защиты.
 При нарушениях механизма защиты, связанных с вычислительнымм
 операциями, процессор автоматически вызвает обработчик
 исключений.
 
 Для программирующего вычисления режим работы существенен только
 в том случае, если команды модулю обработки операций с плавающей
 точкой и ссылки на данные представлены в памяти с помощью команд
 FSAVE и FSTENV. Каждая из этих команд имеет один из четырех
 форматов в зависимости от режима работы и типа операнда в
 команде. Для более детальной информации о командах FSAVE и
 FSTENV смотрите главу 20.
 
 19.2 Инициализация и управление процессором
 ----------------------------------------------------------------
 
 Одни из наиболее важных функций системного программного
 обеспечения инициализация и управление аппаратными и
 программными ресурсами системы, включая модуль обработки
 операций с плавающей точкой. В этом разделе дано описание
 инициализации и управления, включая обработку исключений,
 которые могут случиться во время выполнения числовых команд.
 
 19.2.1 Инициализация системы
 ----------------------------------------------------------------
 
 Во время инициализации системы процессора i486 системные
 программы должны инициализировать модуль обработки операций с
 плавающей точкой и для отражения состояния среды вычислений
 установить флаги в регистр CR0. Эти действия могут быть
 выполнены быстро и легко, как часть общей инициализации системы.
 
 19.2.2 Настройка конфигурации среды вычислений
 ----------------------------------------------------------------
 
 Системная программа должна загрузить соответствующие значения в
 биты MP, EM и NE регистра управления CR0.
 
 Бит MP (Управление сопроцессором) определяет: прерывается ли
 выполнение задачи по команде WAIT, если содержимое модуля
 обработки операций с плавающей точкой отлично от выполняемой
 задачи. Если MP=1 и NS=1, то по умолчанию команда WAIT будет
 выдавать сообщение "Устройство Не Доступно" (вектор прерывания 7).
 Бит МР используется командой WAIT микропроцессоров 80286 и
 386(TM) DX для ожидания доступа к устройству, отличному от
 числового сопроцессора. Устройство информирует о своем состоянии
 через контакт BUSY#. Так как процессор i486 не имеет такого
 контакта, бит МР не используется, и для нормальной работы ему
 необходимо присвоить 1.
 
 Бит ЕМ (Эмуляция сопроцессора) определяет выполняется ли команда
 ESC модулем обработки операций с плавающей точкой (ЕМ=0) или
 будет обрабатываться программой через вектор прерывания 7
 (ЕМ=1). Бит ЕМ использовался в микропроцессоре 386 DX, чтобы
 вычислительные операции, написанные для системы 386 DX
 CPU/387DX, могли бы быть выполнены на программном эмуляторе
 сопроцессора 387 DX в отсуствии сопроцессора 387 DX. Для
 нормальной работы процессора i486 биту ЕМ должен быть присвоен
 0.
 
 Бит NE (Численные исключения) показывает, как обрабатываются
 немаскированные исключения при работе с данными с плавающей
 точкой: через вектор прерывания 16 (NE=1) или через внешние
 прерывания (NE=0). В системах, использующих контроллер внешних
 прерываний для вызова обработчика числовых исключений, биту
 NE должен быть присвоен 0. Другие системы могут использовать
 автоматическую обработку ошибок через прерывание 16, и в бит NE
 тогда заносится 1. Для подробной информации об обработке
 численных исключений смотри раздел 19.2.5.
 
 19.2.3 Инициализация модуля обработки операций с плавающей
        точкой
 ----------------------------------------------------------------
 
 Инициализация модуля обработки операций с плавающей точкой
 означает приведение его в определенное состояние, независимо от
 предыдущих действий. Инициализация выполняется с помощью
 единственной команды FNINIT. В результате устанавливаются все
 маски ошибок, во все регистры заносится 0 и устанавливается
 режим управления округлением и точностью по умолчанию. В Таблице
 19-1 показано состояние модуля операций с плавающей точкой после
 выполнения команды FINIT или FNINIT.
 
 Команда FNINIT приводит модуль обработки операций с
 плавающей точкой в такое же состояние, которое получается после
 нажатия клавиши RESET в результате выполнения встроенного теста
 по проверке памяти. Если встроенный тест не запрашивается, то
 нажатие RESET оставляет модуль обработки операций с
 плавающей точкой неизмененным. Команда FNINIT будет выполнена
 после перезагрузки.
 
         Таблица 19-1. Состояние FPU после инициализации
 ?????????????????????????????????????????????????????????????????
 ?        Поле         ? Значение ?    Интерпретация             ?
 ?????????????????????????????????????????????????????????????????
 ?  Слово Управления   ?  037FH   ?                              ?
 ?    (Управление    * ?          ?                              ?
 ?    бесконечностью)  ?  0       ?                              ?
 ?    Управление       ?          ?  Округление до ближайшего    ?
 ?    округлением      ?  00      ?                              ?
 ?    Управление       ?          ?  64 бита                     ?
 ?    точностью        ?  11      ?                              ?
 ? Маски особых        ?          ? Все особые ситуации          ?
 ?    ситуаций         ?  111111  ? заблокированы                ?
 ?????????????????????????????????????????????????????????????????
 ?  Слово Состояния    ?  0000H   ?                              ?
 ?    (Бит занятости)  ?  0       ?                              ?
 ?    Код Условия      ?  0000    ?                              ?
 ?    Вершина Стека    ?  000     ?  Регистр 0 - вершина стека   ?
 ?    Наличие Особой   ?          ?                              ?
 ?    ситуации         ?  0       ?  Особых ситуаций нет         ?
 ?    Стековый флаг    ?  0       ?                              ?
 ?    Флаги Особых     ?          ?                              ?
 ?    ситуаций         ?  000000  ?  Особых ситуаций нет         ?
 ?????????????????????????????????????????????????????????????????
 ?  Слово Признака     ?  FFFFH   ?                              ?
 ?    Признаки         ?  11      ?                              ?
 ?????????????????????????????????????????????????????????????????
 ?  Регистры           ?  N.C.    ?  Не изменялись               ?
 ?????????????????????????????????????????????????????????????????
 ?  Ссылки на Особые   ?          ?                              ?
 ?  ситуации           ?          ?                              ?
 ?    Код Команды      ?          ?                              ?
 ?    Адрес Команды    ?          ?                              ?
 ?    Адрес Операнда   ?          ?                              ?
 ?????????????????????????????????????????????????????????????????
 
 * Процессор i486 не имеет управления бесконечностью. Данная
   величина для программ, написанных для сопроцессора 80287; если
   эти программы зависят от этого бита, то для процессора i486
   они могут работать неверно.
 
 19.2.4 Эмуляция
 ----------------------------------------------------------------
 
 При присвоении 1 биту ЕМ процессор i486 через вектор прерывания
 7 (Устройство Не Доступно) будет вызывать программу обработки
 исключений, которая подсчитывает количество команд ЕSC. Бит EM
 используется для выполнения числовых операций на процессоре 386
 с программным эмулятором сопроцессора 387. Числовые операции,
 предназначенные для выполнения на нестандартном эмуляторе
 сопроцессора 387, в отсуствии эмулятора могут не быть выполнены
 на процессоре i486 . Присвоение 1 биту ЕМ делает возможным
 выполнить эти операции или программы, использующие нестандартную
 арифметику с плавающей точкой, на процессоре i486.
 
 19.2.5 Обработка числовых исключений
 ----------------------------------------------------------------
 
 Как только модуль обработки операций с плавающей точкой был
 проинициализирован, и началось нормальное выполнение, модуль
 обработки операций с плавающей точкой может потребовать
 внимания, чтобы обработать числовые исключения. В этой
 главе рассматривается написание программных обработчиков
 числовых исключений.
 
 Если модуль обработки операций с плавающей точкой встречает
 немоскированное исключение, то сразу перед выполнением следующей
 команды WAIT или неуправляющей команды с плавающей точкой
 вызывается программный обработчик исключений. Вызов происходит
 через вектор прерывания 16 или через внешнее прерывание, в
 зависимости от значения бита NE регистра управления CR0.
 
 Если NE=1, то немаскированное исключение с плавающей точкой
 вызывает прерывание 16, непосредственно перед выполнением
 следующей неуправляющей команды с плавающей точкой или команды
 WAIT. Прерывание 16 есть сигнал операционной системе о
 необходимости вызова обработчика исключений. В главе 9 даны
 общие сведения об исключениях и прерываниях процессора i486.
 
 Если NE=0 (и ввод IGGNE# не активен), немаскированное исключение
 "замораживает" процессор сразу перед выполнением следующей
 неуправляющей команды с плавающей точкой или команды WAIT.
 "Замороженный" процессор ожидает внешнее прерывание, которое
 должно быть поддержано внешней аппаратурой в ответ на вывод
 процессора FERR#. (Независимо от значения NE немаскированное
 исключение заставляет вывод FERR# быть активным.) В этом случае
 внешнее прерывание вызывает программу обработки исключения.
 Усли NE=0, но ввод IGGNE# активен, то процессор не обращает
 внимание на исключение и продолжает работу. Обработка ошибок
 через внешние прерывания поддерживается для DOS, совместимых с
 процессором. В Главе 25 даны некоторые предложения по
 совместимости.
 
 При обработке ошибок вычислений процессор должен:
 
 - Не нарушить числовой контекст.
 
 - Сбросить ошибку и попытаться от нее избавиться.
 
 Хотя способы решения этих проблем меняются от реализации к
 реализации, большинство обработчиков должны выполнять следующие
 основные действия:
 
 - Сохранить среду модуля обработки операций с плавающей точкой
   (слова управления, статуса, признака, операнды и ссылки на
   команды), какой она была время генерации исключения.
 
 - Очистить бит исключения в слове состояния.
 
 - Замаскировать прерывания.
 
 - Распознать исключение, проанализировав слова управления и
   статуса в сохраненной среде.
 
 - Принять системно-зависимые меры по корректировке ситуации.
 
 - Вернуться к прерванной программе и возобновить нормальное
   выполнение.
 
 
 19.2.6 Реакция на одновременные исключения
 ----------------------------------------------------------------
 
 В случае, если несколько исключений возникает одновременно,
 модуль обработки операций с плавающей точкой сигнализирует об
 одном из них в соответствии с приоритетом, указанным в конце
 Главы 16. Это означает, например, что SNaN, деленное на 0, дает
 ошибочную операцию, а не исключение деления на нуль.
 
 19.2.7 Примеры программ обработки исключений
 ----------------------------------------------------------------
 
 Программы обработки исключений могут иметь различные формы.
 Они могут изменять правила программирования и арифметики
 процессора i486. Такие изменения могут переопределить ошибки,
 установленные по умолчанию, изменить видимость модуля обработки
 операций с плавающей точкой для программиста или изменить
 арифметику, определенную для модуля обработки операций с
 плавающей точкой.
 
 Чтобы изменить результат выдачи исключения, необходимо
 сначала выполнить ненормальную арифметику или ненормальную
 загрузку из памяти. Для изменения "видения" модуля обработки
 операций с плавающей точкой стековой регистр должен быть
 расширен до размеров памяти, чтобы предоставить для работы
 "бесконечное" число регистров. Арифметика модуля обработки
 операций с плавающей точкой может быть автоматически изменена
 через переопределение точности и диапазона значений при
 переполнении. Все эти функции процессора i486 могут быть
 реализованы через числовые прерывания и программы обработки в
 соответствии с нуждами программиста.
 
 Некоторые другие возможные программы в зависимости от применения
 могут включать:
 
 - Увеличение счетчика особых ситуаций при последней работе с
   дисплеем или при печати
 
 - Печать или выдача на экран диагностических сообщений
   (например, среда модуля обработки операций с плавающей точкой
   или регистров)
 
 - Прекращение дальнейшего выполнения
 
 - Сохранение величины диагностики (NaN) в результате и
   продолжение вычисления
 
 В зависимости от применения, исключения могут фиксировать, а
 могут и опускать ошибки. Как только обработчик исключения
 скорректирует условие, вызвавшее исключение, то при
 необходимости, команда с плавающей точкой, в которой случилось
 исключение, может быть выполнена еще раз. Это не может произойти
 при использовании команды IRET, так как прерывания случаются в
 команде ESC или в команде WAIT, вызываемой после команды ESC.
 Обработчик исключений должен получить (используя команду FSAVE
 или FSTENV) адрес нарушившей команды в программе, которая
 вызывала команду, сделать копию команды, выполнить ее в
 контексте нарушенной программы и затем через команду IRET
 вернуться к потоку текущих команд.
 
 Чтобы откорректировать условие, вызвавшее числовое исключение,
 обработчик исключений должен распознать состояние модуля
 обработки операций с плавающей точкой в то время, когда был
 вызван обработчик исключений. Для восстановления состояния
 модуля обработки операций с плавающей точкой программисты должны
 понимать когда, в течение выполнения числовой команды, нарушение
 было обнаружено.
 
 Недопустимые операции, деление на нуль, ненормализованные
 исключения обнаруживаются до начала выполнения операции, тогда
 как переполнение, отрицательное переполнение и исключения
 нарушения точности не возникают до тех пор, пока не будет
 вычислен результат. Если исключение обнаружено перед
 выполнением, то регистровый стек и память модуля обработки
 операций с плавающей точкой еще не были изменены, так как
 команда, содержащая нарушение, не выполнялась.
 
 При обнаружении исключения после начала выполнения команды
 регистровый стек и память выглядят так, будто команды была
 выполнена; например, они могут быть обновлены. (Однако в
 командах сохранить и сохранить-извлечь, немаскированное
 переполнение и отрицательное переполнение обрабатываются подобно
 исключению перед 1  0выполнением; память не обновлялась и из стека
 ничего не извлекалось.) Примеры в Главе 20 содержат несколько
 обработчиков исключений для обработки числовых исключительных
 ситуаций.
 
 
 
 Часть IV  Совместимость
 
 Глава 21   Выполнение программ  процессоров
            80286 и 386(ТМ) DX или SX
 ----------------------------------------------------------------
 
 В основном, программы написанные для защищенного режима
 процесора 80286 могут выполняться без изменений на процессоре
 i486. Характерной чертой объектного кода процессора 80286,
 является его совместимость с кодом i486, как его подмножества.
 Бит умолчания в дескрипторах сегментов показывает, когда
 процессор должен обрабатывать сегмент кода, данных или стека как
 сегмент центрального процессора 80286 или 386(ТМ)/i486.
 
 Для программного обеспечения процессоры 386 DX или SX,
 являются практически тождествеными процессору i486.
 Большинство различий приходится на их аппаратную реализацию.
 
 Дескрипторы сегмента используемые процессором 80286
 поддерживаются процессором i486 если Intel(R)-резервное слово
 (старшее слово) дескриптора очищено. В процессоре i486 это
 слово содержит старшие биты базового адреса и границу сегмента.
 
 Дескрипторы сегмента для сегментов данных, сегментов кодов,
 локальные таблицы дескрипторов ( для глобальных таблиц
 дескрипторов дескрипторов нет), и шлюзы задач для процессоров
 80286, 386 и i486 одинаковы. Другие дескрипторы процессора
 80286 (сегмент TSS, шлюз вызова, шлюз прерывания и шлюз
 ловушки) поддерживаются процессором i486. Процессор i486
 также имеет дескрипторы для сегментов TSS, шлюзов вызова,
 шлюзов прерывания и шлюзов ловушки, которые поддерживает
 32-разрядная архитектура процессора i486. Обе разновидности
 дескрипторов могут использоваться в одной системе.
 
 Для дескрипторов сегментов, одинаковых для процессоров 80286
 и i486, очищенные биты резервного слова побуждают процессор
 i486 интерпретировать эти дескрипторы точно так, как это
 делает процессор 80286. Например:
 
 Базовый адрес (Base Address) - Восемь старших бит базового
 32-разрядного адреса очищены, что ограничивает базовые
 адреса 24 битами.
 
 Граница (Limit) - Четыре старших бита поля границы очищены,
 что ограничивает значение поля границы 64 Кбайт.
 
 Бит детализации (Granularity bit) - Бит детализации очищен
 показывая, что значение 16-разрядной границы интерпретируется
 блоками по одному байту.
 
 Большой бит (Big bit) - В дескрипторе сегмента данных бит В
 очищен показывая, что в сегменте содержится не более 64
 Кбайт.
 
 Бит умолчания (Default bit) - В дескрипторе сегмента кода
 бит D очищен показывая, что по умолчанию принимаются
 16-разрядная адресация и операнды. В дескрипторе сегмента
 стека очищенный бит D показывает, что вместо регистра ESP
 будет использоваться регистр SP и 64 Кбайтная максимальная
 граница сегмента.
 
 Форматы этих дескрипторов и документация по их использованию
 содержится в "Справочнике для программиста по процессору
 iAPX 286" (iAPX 286 Programmer's Reference Manual).
 
 
 21.1 Два пути запуска задач центрального процессора 80286
 ----------------------------------------------------------------
 
 Когда программы процессора 80286 переносятся на процессор i486,
 рассматриваются два подхода:
 
 1. Перенос и запуск программных систем процессора 80286 на
    процессор i486 производится вместе со старой операционной
    системой, загрузчиком и компоновщиком.
 
    В этом случае все задачи используют TSS процессора 80286.
    Процессор i486 используется как более быстрая версия
    процессора 80286.
 
 2. Перенос выбранного прикладного программного обеспечения
    процессора 80286 и его запуск в среде процессора i486,
    с операционной системой, загрузчиком и компоновщиком
    центрального процессора i486.
 
    В этом случае TSS, используемые для представления задач
    процессора 80286, должны быть изменены на TSS центрального
    процессора i486. Смешение TSS центрального процессора 80286
    и i486 возможно, но выгода очень мала, а проблемы очень
    велики. Лучше, если все задачи в среде программного
    обеспечения центрального процессора i486 будут использовать
    TSS центрального процессора i486. Нет необходимости изменять
    сами обьектные модули, реализованные на процессоре 80286;
    ТSS обычно создаются операционной системой, загррузчиком или
    компоновщиком. Смотрите Главу 24, в которой более подробно
    обсуждается интерфейс между 16-разрядным и 32-разрядным
    кодом.
 
 
 21.2  Отличия от центрального процессора 80286.
 ----------------------------------------------------------------
 
 Немногочисленные различия между процессорами  80286 и i486
 затрагивают операционную систему в большей степени чем
 прикладные программы.
 
 
 21.2.1  Циклический возврат адреса в 24-разрядном адресном
         пространстве процессора 80286
 ----------------------------------------------------------------
 
 При использовании процессора 80286, комбинация базы и смещения,
 приводящая к адресации за пределы 16 Мбайт, вызывает циклический
 возврат адреса к первому мегабайту адресного пространства.
 Поскольку процессор i486 имеет большее адресное пространство,
 такие адреса попадают на 17-й мегабайт. Если в программе
 используется циклический возврат, реализуемый в процессоре
 80286, то того же эффекта можно добиться с помощью разбиения на
 страницы. Для этого следует отобразить первые 64 Кбайт 17-го
 мегабайта логических адресов на физические адреса в первом
 мегабайте.
 
 
 21.2.2  Резервное слово дескриптора сегмента
 ----------------------------------------------------------------
 
 Так как процессор i486 использует содержащие резервное слово
 дескрипторы сегмента процессора 80286, программы для процессора
 80286, которые помещают в это слово значения, могут некорректно
 выполнятся на процессоре i486.
 
 
 21.2.3  Новые коды типа дескриптора сегмента
 ----------------------------------------------------------------
 
 Фрагмент операционной системы, который управляет памятью с
 помощью таблиц дескрипторов, для определения неиспользуемых
 входов часто помещает запрещенные значения в поля прав-доступа
 элементов таблицы дескрипторов. Значения прав-доступа 80H и 00H
 неверны как для процессора 80286, так и для процессора i486.
 Другие значения, неопределенные для процессора 80286, могут
 быть верны для процессора i486, поскольку для него задано
 определение этих битов.
 
 
 21.2.4   Ограничения семантики префикса LOCK
 ----------------------------------------------------------------
 
 В процессоре 80286 функция блокирования шины реализована иначе,
 чем в процессоре i486. Программы, которые используют
 специфические для процессора 80286 формы блокирования памяти,
 возможно не будут работать на процессоре i486.
 
 Префикс LOCK и соответствующий ему сигнал шины следует
 использовать только для предотвращения прерываний операций
 пересылки данных другими хозяевами шины. Префикс LOCK можно
 использовать только с нижеперечисленными командами процессора
 i486, когда они модифицируют память. Исключение неопределенного
 кода операции будет результатом использования префикса LOCK
 перед любыми другими командами или с командами, перечисляемыми
 ниже, когда они не выполняют операцию записи, изменяющую память,
 (т.е. операндом назначения является регистр ).
 
 - Команды проверки и изменения битов BTS, BTR и BTC.
 - Команды обмена XCHG, XADD, и CMPXCHG (префикс LOCK не нужен
   для команды XCHG )
 - Oднооперандные арифметические и логические команды INC, DEC,
   NOT, NEG.
 - Двухоперандные арифметические и логические команды ADD, ADC,
   SUB, SBB, AND, OR , XOR.
 
 Команды блокирования гарантированно блокируют только области
 памяти, определенные в операнде назначения, но может
 блокироваться и большая область памяти. Например, типичные
 конфигурации процессоров 8086 и 80286 блокируют все физическое
 пространство памяти.
 
 На процессоре 80286 префикс LOCK чувствителен к IOPL; если CPL
 имеет меньший уровень привилегированности, чем IOPL,
 генерируется исключение общей защиты. На процессорах 386 DX и
 i486 нет контроля против выполнения IOPL.
 
 
 21.2.5   Дополнительные исключения
 ----------------------------------------------------------------
 
 Процессоры 386 и i486 имеют новые исключения, которые могут
 присутствовать даже в системах, разработанных для процессора
 80286.
 
 - Исключение #6 - "неопределенный код операции"
 
   Это исключение может явиться результатом неправильного
   использования префикса команды LOCK.
 
 - Исключение #14 - "сбой страницы"
 
   Это исключение может иметь место в программе для процессора
   80286, если операционная система разрешает страничное
   разбиение. Страничное разбиение может быть использовано в
   задачах для систем с процессором 80286, если все задачи
   используют одни и те же каталоги страниц. Поскольку в TSS
   процессора 80286 нет места для хранения PDBR регистра,
   переключение на задачу процессора 80286 не изменяет значение
   PDBR регистра. В задачах, переданных от процессора 80286,
   следует использовать TSS центрального процессора i486,
   поскольку так они смогут целиком использовать страничное
   разбиение.
 
 
 21.3  Отличия от центрального процессора 386 (TM).
 ----------------------------------------------------------------
 
 Между моделями программирования процессоров 386 DX и SX и
 процессора i486 различий очень немного. Процессор i486
 определяет новые биты в регистрах EFLAGS, CR0 и CR3, а также
 новые входы в таблицы страниц первого и второго уровней. В 386
 процессорах эти биты были зарезервированы, поэтому новые
 особенности архитектуры не повлияли на совместимость.
 
 
 21.3.1  Новый флаг
 ----------------------------------------------------------------
 
 Флаг AC (18-ая битовая позиция) совместно с битом AM регистра
 CR0 контролирует проверку выравнивания.
 
 
 21.3.2  Новое исключение
 ----------------------------------------------------------------
 
 Ислючение проверки выравнивания (17-й вектор исключения)
 сообщает ссылку на невыровненную память при проведении проверки
 выравнивания.
 
 
 21.3.3  Новые команды
 ----------------------------------------------------------------
 
 Появились три новые прикладные команды:
 
 - Команда  BSWAP
 - Команда  XADD
 - Команда  CMPXCHG
 
 Появились также три новые системные команды для управления
 кэшем и TLB:
 
 - Команда  INVD
 - Команда  WBINVD
 - Команда  INVLPG
 
 Поменялась форма команды MOV, используемой для доступа к
 тестовым регистрам. Для кэша определены новые тестовые регистры,
 а модель TLB доступна через измененные тестовые регистры.
 
 
 21.3.4   Новые биты регистра управления
 ----------------------------------------------------------------
 
 В регистре CR0 определены пять новых битов:
 
 - NE бит
 - WP бит
 - AM бит
 - NW бит
 - CD бит
 
 В регистре CR3 определены два новых бита:
 
 - PCD бит
 - PWT бит
 
 
 21.3.5   Новые биты входа таблицы страниц
 ----------------------------------------------------------------
 
 Во входах таблицы страниц для контроля буфферизации страниц
 определены два новых бита:
 
 - PCD бит
 - PWT бит
 
 
 21.3.6  Изменение в заполнении дескриптора сегмента
 ----------------------------------------------------------------
 
 На 386 процессорах заполнение дескриптора сегмента всегда
 вызывает блокирование чтения и записи при установке бита
 доступа дескриптора. Для процессора i486 блокировка чтения и
 записи происходит только в случае, когда данный бит еще не
 установлен.
 
 
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье