Защищенный режим работы процессора

Исключения и прерывания


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

Существует  два   источника прерываний и два источника исключений:
- Маскируемые  прерывания,  получаемые  на  входе  INTR  процессора  i486.
Маскируемые прерывания не происходят до  тех пор, пока не будет  установлен
флаг разрешения прерываний (IF).
- Немаскируемые прерывания, получаемые  на
вход NMI (Не-Маскируемое Прерывание) процессора. Процессор не  обеспечивает
механизма отключения немаскируемых прерываний.
- Исключения,  обнаруживаемые процессором.  Далее они  классифицируются как
сбой, ловушка или аварийное завершение.
- Программируемые исключения. Команды INTO, INT  3, INT  n  и  BOUND  могут
служить   программными переключателями  исключений.  Эти  команды  часто
называют   "программными прерываниями", но  они обрабатываюся  процессором
как  исключения.

Векторы исключений и прерываний
Процессор ассоциирует с каждым  отдельным типом прерывания или  исключением
идентифицирующий  его  номер,  называемый  вектором.  Немаскируемым   (NMI)
прерываниям и исключениям присвоены векторы в диапазоне от 0 до 31. Не  все
из этих векторов используются процессором в настоящее время;  неназначенные
векторы из  этого диапазона  резервируются для  возможного использования  в
будущем.   Использовать   неназначенные   векторы   не   следует.   Векторы
маскируемых   прерываний   определяются   аппаратно.   Контроллеры  внешних
прерываний (например,  Intel 8259,  программируемый Контроллер  Прерываний)
передают  вектор  на  шину  процессора  i486  во  время  цикла квитирования
прерывания. Использоваться могут любые  векторы в диапазоне значений  от 32
до  255.
------------------T---------------------------------------------¬
¦ Номер вектора   ¦                    Описание                 ¦
+-----------------+---------------------------------------------+
¦    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          ¦     Маскируемые прерывания                  ¦
L-----------------+----------------------------------------------

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

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

Рестарт команды

Для  большей  части   исключений  и  прерываний   передача  управления   не
происходит до конца текущей команды. Тем самым регистр EIP  устанавливается
таким образом, чтобы указывать  на команду, следующую за  командой, которая
выполнялась в момент генерации исключения или прерывания. Если эта  команда
имеет  префикс  повторения,  то  передача  управления  происходит  в  конце
текущей итерации,  причем все  регистры будут  находиться в  состоячнии для
выполнения следующей  итерации. Однако,  если данная  ситуация относится по
типу  к  сбоям,  то  регистры  процессора  восстанавливаются  в  состояние,
предшествующее  выполнению  вызвавшей  сбой  команды. Тем самым допускается
рестарт команды.  Рестарт  команды используется  для  обработки исключений,
блокирующих  доступ  к  операндам.   Например,  прикладная  программа могла
обратиться к   данным в  сегменте,   не   присутствующем    в   памяти.   В
случае   такого    исключения обработчик   исключения   должен    загрузить
отсутствующий   нужный      сегмент   (возможно,  с   жесткого  диска)    и
возобновить выполнение, начиная   с команды, вызвавшей данное   исключение.
Во   время  исключения   команда  могла   изменить  содержимое    некоторых
регистров  процессора.    При   считывании    командой значения   из  стека
необходимо  восстановить   прежнее  значение   указателя стека.  Все    эти
восстановительные      операции   выполняются       процессором   способом,
совершенно прозрачным  для прикладной программы.    В случае  сбоя  регистр
EIP   восстанавливается  таким   образом,  чтобы   указывать  на   каманду,
вызвавшую    исключение.    При    возврате    из  обработчика   исключений
выполнение программы продолжается с этой же команды.

Разрешение и запрещение прерываний

Некоторые  условия  и  установки  флагов  приводят  к  тому,  что процессор
запрещает определенные виды прерываний и исключений.

Немаскируемые прерывания, маскирующие последующие NMI
При   выполнении   обработчика    прерываний   NMI   процессор    запрещает
дополнительные вызовы процедуры  или задачи, обрабатывающей  прерывание, до
выполнения  следующей  команды  IRET.  Это  предотвращает  помещение в стек
вызовов   обработчиков   прерываний.    Рекомендуется   использовать    для
немаскируемых  прерываний  шлюзов   прерываний,  что  позволяет   запретить
вложенные  маскируемые  прерывания,  поскольку  команда IRET из обработчика
маскируемого прерывания снова разрешит NMI.

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, что запрещает  прерывания. (Шлюзы прерывания рассматриваются  ниже
в данной главе).

Флаг RF в регистре EFLAGS может использоваться для запрещения  обслуживания
отладочных сбоев. Если  он очищен, то  отладочные сбои обслуживаются;  если
же  он  установлен,  то  они  игнорируются.  Это  средство используется для
подавления  множественных  вызовов  обработчика  отладочных  исключений   в
контрольных точках. Например, могла быть установлена контрольная точка  для
команды, ссылающейся  к данным  в сегменте,  не присутствующем  в настоящий
момент в памяти.  Когда эта команда  выполняется в первый  раз, контрольная
точка  генерирует  отладочную  ситуацию.  Прежде  чем произойдет возврат из
обработчика  исключения,  обработчик  должен  установить  флаг  RF  в копии
регистра EFLAGS, сохраненной  в стеке. Это  позволяет сообщить о  сбое типа
"сегмент  не   присутствует"  после   того,  как   обработчик   отладочного
исключения  передаст  управление  назад  на  эту  команду.  Если  флаг   не
установлен,  то  после  возврата  из  обработчика  отладочного   исключения
произойдет другое отладочное исключение.  Процессор устанавливает бит RF  в
сохраненном  содержимом  регистра  EFLAG,  когда  происходят  другие  сбои,
поэтому   при   рестарте   команды   вследствие   сбоя   типа  "сегмент  не
присутствует"   множественные   отладочные   исключения   не  генерируются.
Процессор  очищает  флаг  RF  при  завершении  выполнения приводящих к сбою
команд.



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 Нет -----------------------------------------------------------------
Оглавление


© Колесников Дмитрий Геннадьевич Rambler's Top100 Учебник по СайтоСтроению
доставка навоза актуальная информация . продвижение нового сайта
Комбинезоны оптом