§ Исключения
Исключениями называются прерывания, которые генерирует процессор в ответ на нарушения условий защиты. Повлиять на исключения прикладные программы (работающие на уровне привилегий, выше 0) не могут, замаскировать - тоже. Аппаратный контроль защиты - самый надёжный и 32-разрядные процессоры предоставляют этот сервис в полном объёме.Исключения делятся на три типа, в зависимости от условий их возникновения:
- Ошибка (fault)
- Ловушка (trap)
- Авария (abort)
Ловушка – это исключение, возникающее сразу после выполнения "отлавливаемой" команды. Это исключение позволяет продолжить выполнение программы со следующей команды (без рестарта "виноватой"). На ловушках строится механизм отладки программ.
Авария – это исключение, которое не позволяет продолжить выполнение прерванной программы и сигнализирует о серьёзных нарушениях целостности системы. Примером аварии служит исключение двойного нарушения (прерывание 8), когда сама попытка обработки одного исключения вызывает другое исключение.
Для некоторых исключений процессор помещает с стек обработчика двухбайтовый код ошибки, позволяющий конкретно определить ошибку.
Далее приводится полный список исключений и прерываний. В этой таблице применяются следующие обозначения:
- Номер вектора – номер вектора прерывания, на которое отображено исключение.
- Название – используется в документации Intel и состоит из заглавных букв английского названия исключения, например, #DE - Divide Error.
- Error code – наличие dw-кода ошибки, который процессор добавляет в стек обработчика перед передачей ему управления.
Номер вектора | Название | Описание | Тип | Error Code | Источник исключения |
0 | #DE | Ошибка деления | Fault | Нет | Команды DIV и IDIV |
1 | #DB | Отладка | Fault/Trap | Нет | Любая команда или команда INT 1 |
2 | - | Прерывание NMI | Прерывание | Нет | Немаскируемое внешнее прерывание |
3 | #BP | Breakpoint | Trap | Нет | Команда INT 3 |
4 | #OF | Переполнение | Trap | Нет | Команда INTO |
5 | #BR | Превышение предела | Fault | Нет | Команда BOUND |
6 | #UD | Недопустимая команда (Invalid Opcode) | Fault | Нет | Недопустимая команда или команда UD21 |
7 | #NM | Устройство не доступно (No Math Coprocessor) | Fault | Нет | Команды плавающей точки или команда WAIT/FWAIT |
8 | #DF | Двойная ошибка | Abort | Да (Нуль) | Любая команда |
9 | - | Превышение сегмента сопроцессора (зарезервировано) | Fault | Нет | Команды плавающей точки2 |
0Ah | #TS | Недопустимый TSS | Fault | Да | Переключение задач или доступ к TSS |
0Bh | #NP | Сегмент не присутствует | Fault | Fault | Загрузка сегментных регистров или доступ к сегментам |
0Ch | #SS | Ошибка сегмента стека | Fault | Да | Операции над стеком и загрузка в SS |
0Dh | #GP | Общая защита | Fault | Да | Любой доступ к памяти и прочие проверки защиты |
0Eh | #PF | Страничное нарушение | Fault | Да | Доступ к памяти |
0Fh | - | Зарезервировано Intel-ом. Не использовать. | Нет | ||
10h | #MF | Ошибка плавающей точки в x87 FPU (Ошибка математики) | Fault | Нет | Команда x87 FPU или команда WAIT/FWAIT |
11h | #AC | Проверка выравнивания | Fault | Да | (Нуль) Обращение к пямяти3 |
12h | #MC | Проверка оборудования | Abort | Нет | Наличие кодов и их содержимое зависит от модели4 |
13h | #XF | Исключение плавающей точки в SIMD | Fault | Нет | Команды SSE и SSE25 |
14h-1Fh | - | Заререзвировано Intel-ом. Не использовать | |||
20h-FFh | - | Прерывания определяются пользователем | Прерывание | Внешнее прерывание или команда INT n |
§ Примечания:
- Команда UD2 появилась в процессоре Pentium Pro.
- Процессоры IA-32 после Intel386 не генерируют это исключение.
- Это исключение появилось в процессоре Intel486.
- Это исключение появилось в процессоре Pentium и развивается в процессорах семейства P6.
- Это исключение появилось в процессоре Pentium III.
Операционная система должна определить дескрипторы для всех исключений. Если процессор при генерации исключения не обнаружит в IDT соответствующего дескриптора, это приведёт к генерации ещё одного исключения. Процессор может обработать два исключения последовательно, но в некоторых случаях, когда это ему не удаётся, он генерирует исключение двойной ошибки.
Если в IDT не будет дескриптора и для исключения двойной ошибки, либо не сможет корректно его обработать, то процессор переходит в режим отключения, похожий на режим, в который его переводит команда HLT (т.е. попросту, зависает) и будет реагировать только на сигналы типа аппаратного сброса.
Сами обработчики исключений не обязательно должны выполнять свои функции. На этапе создания операционной системы достаточно сделать "заглушки", которые будут выводить на экран номер исключения и параметры, переданные в стеке. Т.к. действия обработчиков сильно отличаются в зависимости от предназначения ОС, то здесь, в этом разделе, будут приведены лишь примеры "заглушек", а примеры обработчиков исключений и аппаратных прерываний вы сможете найти в соответствующих разделах.