Исключение 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, ссылающаяся на не присутствующий шлюз).
Операционная система обычно использует исключение "сегмент не присутствует" для реализации на сегментном уровне виртуальной памяти. Однако, обозначение не присутствия сегмента в дескрипторе шлюза обычно не означает, что сегмент не присутствует (поскольку шлюзы не обязательно должны соответствовать сегментам). Не присутствующие шлюзы могут использоваться операционной системой для переключения исключений, имеющих специальное значение для операционной системы.
Исключение 12 - Исключение в стеке
Сбой в стеке генерируется в двух следующих случаях:
· В результате нарушения границы операцией, ссылающейся к регистру SS. Сюда входят стеко-ориентированные команды, такие как POP, PUSH, ENTER и LEAVE, а также прочие ссылки к памяти, неявно использующие стек (например, MOV AX,[BP+6]). Команда ENTER генерирует данное исключение, когда не хватает памяти для распределения локальных переменных.
· При попытке загрузить регистр SS дескриптором, отмеченным признаком "сегмент не присутствует", и допустимым во всех прочих отношениях. Это может произойти при переключении задачи, при выполнении команды CALL к другому уровню привилегированности, при возврате к другому уровню привилегированности, команде LSS, либо MOV или POP для регистра SS.
Когда процессор обнаруживает исключение в стеке, он помещает код ошибки в стек обработчика исключений. Если исключение произошло в следствии не присутствующего сегмента стека или переполнения нового стека во время выполнения межуровневой команды CALL, то код ошибки содержит селектор сегмента, вызвавшего исключение (обработчик исключений может проверять бит Присутствия в дескрипторе для того, чтобы определить, какое исключение имело место); в противном случае код ошибки равен 0.
Команда, генерирующая данный сбой, позволяет рестарт во всех случаях. Адрес возврата, помещенный в стек обработчика исключений, указывает на команду, рестарт которой требуется выполнить. Эта команда обычно та, что вызвала исключение; однако, в случае исключительной ситуации в стеке вследствие загрузки дескриптора не присутствующего сегмента стека во время переключения задачи указанная команда представляет собой первую команду новой задачи.
Когда исключение в стеке происходит при переключении задачи, сегментные регистры не могут служить для адресации памяти. Во время переключения задачи значения селекторов загружаются до проверки дескрипторов. При генерации исключения стека остальные сегментные регистры остаются непроверенными, что может привести при их использовании к исключениям. Обработчик сбоев стека должен проверить все сегментные регистры, прежде чем пытаться возобновить выполнение новой задачи; в противном случае могут быть сгенерированы исключения общей защиты в условиях, когда диагностирование более затруднительно.