Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
мпс с 1 по 294.doc
Скачиваний:
13
Добавлен:
16.04.2019
Размер:
6.2 Mб
Скачать

2.8.2. Причины возникновения исключений

В предыдущих главах рассмотрены основные случаи, при которых реализуются раз­личные виды исключений (табл. 2.60). Поэтому в данном разделе ограничимся кратким обзором причин их возникновения.

Исключение 0 -деление на нуль (#DE). Возникает при выполнении команд DIV, IDIV, если делитель равен нулю или если результат не может разместиться в операнд-приемник (превышает разрядность приемника).

Исключение 1 - исключение для отладки (#DB). Возникает в пошаговом режиме (при значении признака TF = 1 в регистре EFLAGS) после выполнения каждой команды; при переключении на задачу, в сегменте TSS которой установлен, бит Т=1; при достижении аппаратных точек останова, устанавливаемых с помощью регистров DRO-DR3. В зависи­мости от типа аппаратной точки останова исключение #DB может обслуживаться как ошибка или как ловушка.

Прерывание 2 - немаскируемое прерывание. Возникает при поступлении внешнего сиг­нала NMI=1 на вход NMI процессора или приеме соответствующего сообщения по шине APIC. Это прерывание может быть вызвано как программное с помощью команды INT п, где п = 2.

Исключение 3 - исключение программной точки останова (#ВР). Имеет место при вы­полнении однобайтной команды INT3. Команда INT3 обычно вводится в текст отлаживае­мой программы для ее останова и контроля текущих результатов выполнения.

Исключение 4 - переполнение (#OF). Это исключение вызывается с помощью команды INTO. Команда INTO проверяет признак OF в регистре EFLAGS и реализует исключение #OF, если значение этого признака OF = 1.

Исключение 5 - превышение границы массива (#BR). Имеет место при выполнении коман­ды BOUND, если содержимое проверяемого регистра выходит за указанные пределы.

Исключение 6 - недействительный код операции (#UD). Возникает при попытке выполнить команду, в коде которой обнаружено какое-либо из следующих нарушений:

  • указан неиспользуемый (резервированный) код операции;

  • используется неправильный способ адресации операнда;

  • указан код ММХ- или SSE-команд при установленном в регистре CRO значении бита ЕМ = 1;

  • выбраны коды команд LLDT, SLOT, LTR, SIR, LSL, ARPL, VERR, VERW при работе про­цессора в реальном режиме или режиме виртуального 8086;

  • префикс LOCK используется с командой, при выполнении которой не должен произво­диться захват шины;

  • выбран код команды UD2, которая служит для вызова подпрограммы обслуживания дан­ного исключения.

Исключение 7- процессор FPU недоступен (#NM). Реализуется в следующих случаях:

  • при попытке выполнить команду FPU, когда в регистре CRO установлено значение бита ЕМ = 1;

  • при попытке выполнить FPU-, ММХ- или SSE-команду, когда в регистре CRO установлено значение бита TS = 1;

  • попытка выполнить команду WAIT или FWAIT, когда в регистре CRO установлено значе­ние битов МР = TS = 1.

Исключение 8 - двойная ошибка (#DF). Реализуется в случае, когда при вызове подпрограммы обслуживания одного исключения выявляется другое. Если процессор не может обработать такие исключения последовательно, то генерируется исключение #DF. При этом в стек заносится код ошибки с нулевым значением всех битов. Чтобы опреде­лить исключения, которые могут обрабатываться последовательно, они разбиты на три класса: А, В и С (см. табл. 2.60). В табл. 2.62 указано, какие классы исключений могут обрабатываться последовательно, а какие вызовут исключение #DF. Если при вызове исключения #DF обнаруживается другое исключение, то процессор переходит в отклю­ченное состояние (shutdown).

Исключение 10 - недействительный сегмент TSS (#TS). Это исключение может иметь место при переключении задач. В табл. 2.63 указаны случаи, когда сегмент TSS считается недостоверным. При вызове исключения #TS процессор включает в стек код ошибки. Если в коде ошибки установлен, бит ЕХТ = 1, то это означает, что переключение на неверную задачу произошло не программным путем, а от внешнего прерывания через шлюз задачи. Исключение #TS должно обрабатываться только через шлюз задачи!

Исключение 11 -отсутствие сегмента (#NP). Реализуется при обращении к дескрип­тору, который имеет значение бита присутствия Р. = 0. Такая ситуация возникает в следую­щих случаях:

  • попытка загрузить сегментные регистры CS, DS, ES, GS или FS селекторами дескрипто­ров, у которых бит Р = 0 (загрузка регистра SS приводит к исключению #SS); этот случай может иметь место при переключении задач;

  • попытка загрузить регистр LDTR с помощью команды LLDT селектором дескриптора, у которого бит Р = 0;

  • попытка загрузить регистр TR с помощь команды LTR селектором дескриптора TSS, у которого бит Р = 0;

  • попытка использовать дескриптор шлюза или дескриптор TSS, для которых бит присут­ствия Р. = 0

  • Код ошибки содержит индекс селектора, приведшего к возникновению #NP. Если в коде ошибки установлен, бит ЕХТ = 1, то это означает, что в результате внешнего прерывания произошло обращение к отсутствующему объекту (например, шлюз прерывания ссылается на отсутствующий сегмент). Если в коде ошибки значение бита IDT = 1, то это означает, что индекс кода ошибки ссылается на дескрипторную таблицу ЮТ (например, команда INT n выбирает шлюз, у которого бит присутствия Р = 0).

Исключение 12 - ошибка при обращении к стеку (#SS). Возникает при неправиль­ном обращении к стеку, которое имеет место в следующих ситуациях:

  • нарушение границы сегмента стека, на который ссылается регистр SS; команды, кото­рые могут вызвать нарушение границы стека: POP, PUSH, CALL, RET, IRET, ENTER и LEAVE, а также команды, у которых один из операндов находится в сегменте стека (например, MOVCX, [ВР+8] или MOV EDX, SS:[EAX+6]);

  • попытка загрузить сегментный регистр S3 селектором дескриптора, у которого бит при­сутствия Р = 0; это нарушение может возникнуть: при переключении задач, при переходе с одного уровня привилегий на другой с помощью команды CALL, при возврате с другого уровня привилегий, при выполнении команды LSS, при загрузке регистра SS с помощью ко­манд MOV или POP.

Исключение 13 - нарушение общей защиты (#GP). Возникает во всех случаях нару­шения защиты, которые не вызывают исключений #NP, #SS, #PF или #TS. К таким случаям относятся:

  • нарушение границы сегмента при обращении к сегментам, на которые ссылаются регис­тры CS, DS, ES, GS и FS;

  • нарушение границы дескрипторной таблицы (кроме случаев переключения задач и пере­ключения стека);

  • передача управления невыполняемому сегменту; л "• - ->• •*•»" "• t ->c

  • запись в сегмент кода или в сегмент данных, для которого разрешено только чтение;

  • чтение из сегмента кода, для которого разрешено только выполнение;

  • попытка загрузить сегментный регистр SS селектором сегмента, для которого разрешено только чтение (кроме случая переключения задач);

  • загрузка сегментных регистров SS, DS, ES, FS или GS селекторами системных дескрипторов;

  • загрузка сегментных регистров DS, ES, FS или GS селекторами сегментов кода, допус­кающих только выполнение;

  • загрузка сегментного регистра SS нуль-селектором или селектором сегмента кода;

  • загрузка сегментного регистра CS нуль-селектором или селектором сегмента данных;

  • обращение к памяти с использованием сегментных регистров DS, ES, FS или GS, когда они содержат нуль-селекторы;

  • переключение на занятую задачу;

  • переключение на незанятую задачу при выполнении команды IRET;

  • использование селектора, который ссылается на дескриптор TSS в LDT (дескрипторы TSS могут находиться только в GDT);

  • нарушение правил защиты сегментов;

  • превышение длины команды в 15 байт (такая ситуация может возникнуть при использова­нии излишних префиксов);

  • загрузка в регистр управления CRO содержимого, в котором бит PG = 1 (страничное преобразование разрешено) при значении бита РЕ = 0 (защищенный режим запрещен).

  • загрузка в регистр управления CRO содержимого, в котором бит NW = 1 и бит CD - 0;

  • использование элемента таблицы ЮТ, который не является шлюзом прерывания, шлюзом ловушки или шлюзом задачи;

  • попытка в режиме виртуального 8086 передать управление обработчику прерывания через шлюз ловушки или шлюз прерывания, когда сегмент кода программы-обработчика имеет DPL > 0;

  • попытка записать «1» в зарезервированные биты регистры управления CR4;

  • попытка выполнить привилегированную команду, когда CPL № 0;

  • попытка записать «1» в зарезервированные биты MSR регистров;

  • использование шлюза, который содержит нуль-селектор;

  • выполнение команды /Л/Гп, когда CPL > gDPL выбираемого шлюза;

  • использование в дескрипторе шлюза селектора, который не ссылается на сегмент команд;

  • использование в команде LLDT операнда, который не является селектором LDT или имеет значение бита TI = 1;

  • использование в команде LTR операнда, который является локальным селектором или ссылается на занятую задачу;

  • попытка использовать нуль-селектор для межсегментных переходов;

  • выборка процессором, работающим в режиме расширенной адресации (установлено зна­чение бита РАЕ = 1 в регистре CR4), указателя каталога страниц, в зарезервированных полях которого имеются «1».

Исключение 14- ошибка обращения к странице (#PF). Имеет место при страничном преобразовании адресов в следующих случаях:

  • бит присутствия Р = 0 в указателе таблицы или страницы;

  • нарушение правил защиты страниц.

Формат кода ошибки для этого исключения (рис. 2.62) содержит биты, которые имеют следующее назначение:

Р = 0, если исключение вызвано отсутствием страницы, Р - 1, если исключение вызва­но нарушением правил защиты для страниц;

W/R = 0, если исключение произошло при чтении страницы, W/R = 1, если - при записи на страницу;

U/S = 0, если исключение произошло при работе процессора в режиме супервизора, U/S = 1, если исключение произошло при работе в режиме пользователя;

RSVD = 0, если исключение #PF произошло из-за того, что процессор обнаружил «1» в зарезервированных полях указателя таблицы или указателя страницы; RSVD = 1 при дру­гих причинах исключения.

В регистр CR2 процессор заносит линейный адрес, приведший к исключению #PF.

Исключение 16 - исключение FPU (#MF). Реализуется при различных видах ошибок при обработке чисел с плавающей точкой.

Исключение 17 - ошибка выравнивания (#АС). Возникает при нарушении правил выравнивания операндов, которые процессор проверяет, если в регистре EFLAGS уста­новлено значение признака АС = 1, и в регистре CRO бит AM = 1. Исключение реализуется в случае нарушения следующих правил формирования адреса операнда:

  • адрес должен быть кратным 2 при выборке слова, селектора или 32-разрядного дальне­го (far) указателя;

  • адрес должен быть кратным 4 при выборке двойного слова, числа с плавающей точкой одинарной точности, 48-разрядного дальнего (far) указателя, 32-разрядного ближнего (near) указателя или битовой строки;

  • адрес должен быть кратным 8 при выборке числа с плавающей точкой двойной точности или числа с плавающей точкой расширенной точности.

Процессор всегда заносит в стек нулевой код ошибки при вызове исключения #АС. д Исключение 18 - машинный контроль (#МС). Обеспечивает контроль работы про­цессора с помощью специализированных (модельно-специфических) регистров MSR.

Исключение 19 - исключение SSE (#ХМ). Реализуется при различных видах ошибок, возникающих при выполнении SSE-команд.