Исключения в защищённом режиме
Для обработки особых ситуаций - исключений - разработчики процессора i80286 зарезервировали 31 номер прерывания. В таблице 3 приведён полный список зарезервированных прерываний защищённого режима.
Таблица 4. Зарезервированные прерывания защищённого режима.
00h | Ошибка при выполнении команды деления. |
01h | Прерывание для пошаговой работы, используется отладчиками. |
02h | Немаскируемое прерывание. |
03h | Прерывание по точке останова для отладчиков. |
04h | Переполнение, генерируется командой INTO, если установлен флаг OF. |
05h | Генерируется при выполнении машинной команды BOUND, если проверяемое значение вышло за пределы заданного диапазона. |
06h | Недействительный код операции, или длина команды больше 10 байт. |
07h | Отсутствие арифметического сопроцессора. |
08h | Двойная ошибка, вырабатывается в том случае, если при обработке исключения возникло ещё одно исключение. Если во время обработки этого прерывания возникает третье исключение, процессор переходит в состояние отключения, что приводит к перезапуску процессора. |
09h | Превышение сегмента арифметическим сопроцессором. |
0Ah | Недействительный сегмент состояния задачи TSS. |
0Bh | Отсутствие сегмента. Вырабатывается при попытке использовать для адресации дескриптор, у которого бит присуствия сегмента в памяти P сброшен в 0. Это прерывание используется для реализации механизма виртуальной памяти. В этом случае по прерыванию 0Bh операционная система может выполнить подкачку отсутствующего сегмента в память. |
0Ch | Исключение при работе со стеком. Может возникать в случае отсутствия сегмента стека в памяти или в случае переполнения (антипереполнения) стека. |
0Dh | Исключение по защите памяти. Возникает при любых попытках получения доступа к сегментам памяти, если программа обладает недостаточным уровнем привилегий. |
0Eh | Отказ страницы для процессоров i80386 или i80486, зарезервировано для i80286. |
0Fh | Зарезервировано. |
10h | Исключение сопроцессора. |
11h - 1Ah | Зарезервированы. |
Перед тем, как передать управление обработчику исключения, для многих зарезервированных прерываний процессор помещает в стек 16-битовый код ошибки.
Этот код ошибки программа может проанализировать и тем самым получить некоторую дополнительную информацию об ошибке.
Формат кода ошибки приведён на рис. 13.
Рис. 13. Формат кода ошибки процессора i80286.
Поле индекса содержит индекс дескриптора, при обращении к которому произошла ошибка. Поле I, равное 1, означает, что этот индекс относится к таблице IDT. В этом случае произошла ошибка при обработке прерывания или исключения.
Если бит I равен 0, поле TI выбирает таблицу дескрипторов (GDT или LDT) по аналогии с соответствующим полем селектора.
Бит EXT устанавливается в том случае, когда ошибка произошла не в результате выполнения текущей команды, а по внешним относительно выполняемой программы причинам. Например, при обработке аппаратного прерывания от устройства ввода/вывода произошло обращение к отсутствующему в памяти сегменту (у которого в дескрипторе сброшен бит присутствия P).
Как мы только что говорили, коды ошибок включаются в стек не для всех исключений. Программа сможет проанализировать этот код только для следующих исключений:
- 08h - двойная ошибка;
- 0Ah - недействительный TSS;
- 0Bh - отсутствие сегмента в памяти;
- 0Ch - исключение при работе со стеком;
- 0Dh - исключение по защите памяти.
Кроме того, новым при обработке прерываний в защищённом режиме является свойство повторной запускаемости исключений. Свойством повторной запускаемости обладают не все исключения.
Что такое повторная запускаемость?
Поясним это на конкретном примере. Пусть в нашей системе реализована виртуальная память. Программа в некоторый момент времени обратилась к отсутствующему в оперативной памяти сегменту, выдав какую-либо команду, например MOV или ADD.
Возникло исключение 0Bh - отсутствие сегмента в памяти. Обработчик этого исключения, входящий в состав операционной системы выполнил свопинг соответствующего сегмента в оперативную память. Что дальше? А дальше было бы неплохо повторить выполнение прерванной команды!
Это можно сделать, так как для всех повторно запускаемых исключений (кроме 03h - прерывание по точке останова и 04h - переполнение) в стек включается адрес не следующей за прерванной командой, а адрес первого байта команды, которая вызвала исключение. Выполнив команду IRET, программа обработки исключения вновь передаст управление прерванной команде.
Свойством повторной запускаемости обладает большинство зарезервированных прерываний, кроме следующих:
- 01h - прерывание для пошаговой работы;
- 08h - двойная ошибка;
- 09h - превышение сегмента сопроцессором;
- 0Dh - исключение по защите памяти;
- 10h - исключение сопроцессора.