Шлюз прерывания содержит адрес входа в обработчик прерывания в виде «селектор сегмента» и «смещение»
Шлюзы вызова (Call Gates) используются для вызовов процедур со сменой уровня привилегий, шлюзы задач (Task Gates) используются для переключения задач, шлюзы прерываний (Interrupt Gates) и ловушек (Trap Gates) определяют процедуры обслуживания прерываний. Шлюзы вызова позволяют автоматически копировать заданное число слов из старого стека в новый. Шлюзы прерываний отличаются от шлюзов ловушек только тем, что они запрещают прерывания (сбрасывают IF), а шлюзы ловушек — нет.
Аналогично тому, как команда CALL вызывает процедуру или задачу, так и исключение или прерывание может "вызвать" обработчик прерывания, представленный в виде процедуры или задачи. Реагируя на исключение или прерывание, процессор использует вектор особого прерывания или прерывания в качестве индекса дескриптора в IDT. Если процессор индексирует шлюз прерывания или шлюз ловушки, то вызов обработчика происходит аналогично вызову при помощи CALL шлюза вызова. Если процессор индексирует шлюз задачи, это приводит к переключению задачи аналогично вызову при помощи CALL шлюза задачи.
Прерывания, использующие либо шлюзы прерывания, либо шлюзы ловушки, вызывают очистку флага TF после того, как его текущее значение сохранено в стеке как часть сохраняемого содержимого регистра EFLAGS. Поступая таким образом, процессор предотвращает воздействие трассировки команды на реакцию прерывания. Последующая команда IRET восстанавливает флаг TF в значение, сохраненное в регистре EFLAGS в стеке.
Различие между шлюзом прерывания и шлюзом ловушки состоит в их воздействии на флаг IF. Прерывание, использующее шлюз прерывания, очищает флаг IF, предотвращая тем самым влияние на текущий обработчик прерывания прочих возможных прерываний. Последующая команда IF восстанавливает флаг IF в состояние, которое он имел в сохраненном в стеке регистре EFLAGS. Прерывание, проходящее через шлюз ловушки, не изменяет флага IF.
Защита в процедурах прерываний.
Правило привилегированности, управляющее процедурами прерывания, аналогично правилу, действующему при вызове процедуры: процессор не разрешает прерыванию передавать управление процедуре в менее привилегированный сегмент (с численно большим номером уровня привилегированности). Попытка нарушить это правило ведет к генерации исключения защиты.
Поскольку прерывания, как правило, происходят не в заранее запланированное время, данное правило фактически накладывает ограничения на уровни привилегированности, с которыми могут выполняться процедуры обработки исключений и прерываний. Для защиты от нарушения правила привилегированности можно использовать один из следующих способов:
· Обработчик исключения или прерывания должен быть помещен в конформный кодовый сегмент. Этот способ может использоваться для обработчиков некоторых конкретных исключений (например, деления на ноль). Такие обработчики должны использовать только данные, доступные через стек. Если обработчику требуются данные из сегмента данных, этот сегмент данных должен иметь уровень привилегированности 3, то есть он должен быть незащищенным.
· Обработчик может быть помещен в кодовый сегмент с уровнем привилегированности 0. Такой обработчик будет выполняться всегда, независимо от CPL программы.
Код ошибки.
При отработке исключения в защищенном режиме процессор сохраняет в стеке слово кода ошибки (Error Code). Если оно отлично от нуля, то в нем содержится селектор дескриптора, с которым связана ошибка.
Код ошибки имеет формат, показанный на Рисунке 4.3 .
Рис. 4.3 Формат кода ошибки
Код ошибки похож на селектор сегмента, однако вместо поля RPL код ошибки содержит два однобитовых поля:
1. Процессор устанавливает бит EXT, если исключение вызвано событием, внешним по отношению к программе.
2. Процессор устанавливает бит IDT, если индексная часть кода ошибки ссылается к дескриптору шлюза в IDT.
Если бит IDT не установлен, то бит TI указывает на то, ссылается ли код ошибки к GDT (бит TI очищен), или же к LDT (бит TI установлен). Остальные 13 битов - это старшие биты селектора сегмента. В некоторых случаях код ошибки является пустым (т.е. все биты его младшего слова очищены.) Код ошибки помещается в стек в виде двойного слова. Это делается для выравнивания стека по адресам, кратным четырем. Старшая половина двойного слова резервируется.