Прерывания и особые ситуации: Условия возникновения и особенности обработки |
Программирование - Архитектура и система команд микропроцессоров x86 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Прерывание 0 — Деление на нуль (#DE)Возникает, если в командах DIV или IDIV делитель равен нулю или результат операции не может быть представлен в том количестве бит, которыми располагает операнд-назначение. А также, если в команде AAM ее непосредственный операнд задан равным нулю.
Прерывание 1 — Прерывание отладки (#DB)Генерируется при ряде условий. Может быть как ошибкой, так и ловушкой в зависимости от причины:
Процессор не сохраняет код ошибки для этого прерывания. Обработчик должен проверять отладочные регистры для выяснения причины прерывания.
Прерывание 2 — Немаскируемое прерывание (NMI)Немаскируеамое прерывание генерируется извне путем подачи сигнала на вывод NMI# процессора, либо через внутреннюю шину встроенного APIC-контроллера. При поступлении немаскируемого прерывания процессор заканчивает выполнение текущей команды, сохраняет в стеке значения некоторых регистров (зависит от режима работы), в т.ч. указатель CS:(E)IP на следующую команду, и передает управление обработчику прерывания. Таким образом, позднее прерванная программа может быть продолжена без каких-либо дополнительных действий. Во время обработки немаскируемого прерывания процессор во избежание зацикливания перестает реагировать на запросы на немаскируемое прерывание до поступления команды IRET. Рекомендуется использовать шлюз прерывания для обработчика немаскируемых прерываний с тем чтобы обеспечить автоматическое отключение маскируемых прерываний на время работы обработчика.
Прерывание 3 — Точка останова (#BP)Генерируется командой INT 3. Данное прерывание предназначено для использования отладчиком, который размещает специальную однобайтовую команду INT 3 (код CCh) вместо первого байта команд или вместо однобайтовых команд. Сохраненные значения CS:EIP указывают на байт, следующий за INT 3. Существует второй способ вызова данного прерывания с помощью двухбайтового кода INT 3 (код CD03h). Однако данный метод на практике не применяется, все ассемблеры x86 по умолчанию интерпретируют мнемонику INT 3 как однобайтовую команду с кодом CCh (но это не исключает возможность ручного программирования двухбайтового кода). Помимо размера кода, отличается и процесс обработки одно- и двухбайтовых команд INT 3. Прерывание, сгенерированное однобайтовой командой при CR4.VME = 1 не подвергается перенаправлению по карте перенаправления прерывания и всегда обрабатывается обработчиком защищенного режима, а в режиме V86 для данного прерывания не осуществляется проверок поля IOPL и, соответственно, не может быть сгенерирована ошибка общей защиты (#GP). Команда INT 3 ни коим образом не влияет на состояние и содержимое регистров процессора. Прерванная программа может быть продолжена, если обработчик прерывания восстановит команду, измененную записью точки останова INT 3, и, уменьшив на единицу сохраненные значения CS:EIP, передаст управление на эту команду. В процессорах Intel386 и старше для отладки программ и установки точек останова рекомендуется использовать регистры отладки, а команду INT 3 применять только в случаях, когда требуемое количество точек останова превышает возможности этих регистров.
Прерывание 4 — Переполнение (#OF)Генерируется при выполнении команды INTO, если установлен флаг OF.
Прерывание 5 — Нарушение границ (#BR): Intel186 …Генерируется, если при выполнении команды BOUND процессор обнаруживает, что операнд выходит за заданные границы.
Прерывание 6 — Неопределенный код операции (#UD): Intel186 …Возникает, когда в управляющем блоке процессора обнаруживается некорректный код, включая коды MMX, 3DNow! и SIMD-команд в процессорах, которые не поддерживают такие расширения системы команд. Сохраненное значение CS:EIP указывает на недопустимый код или на его префикс. Ошибка может быть обработана в текущей задаче. Это прерывание также возникает при любом появлении неправильного операнда (например, межсегментный переход, использующий регистровый операнд), при попытке выполнения специальных команд защищенного режима (LLDT, SLDT, LTR, STR, LSL, LAR, VERR, VERW, ARPL) в режиме реальной адресации или в режиме V86 и при попытке выполнить команду RSM, когда процессор не находится в системном режиме SMM (System Management Mode). В процессорах Intel386 и старше прерывание #UD вызываетcя также использованием префикса LOCK с командами не допускающими блокировки или с командами в которых операнд-назначение не располагается в памяти. В процессорах, которые поддерживают системы команд MMX, SIMD и 3DNow!, прерывание #UD генерируется при встрече таких команд, если установлен флаг CR0.EM, а для SIMD-команд и в случае, если CR4.OSFXSR = 0. Кроме этого, когда специальный бит CR4.OSXMMEXCPT = 0, то все незамаскированные исключения SIMD вызывают генерацию особой ситуации #UD, а обработчик особой ситуации должен затем определять причину ее генерации, обращаясь к SIMD-регистрам. (Если CR4.OSXMMEXCPT = 1, то все незамаскированные исключения SIMD вызывают генерацию особой ситуации #XM). В процессорах Pentium Pro … введена новая команда UD2, выполнение которой вызывает генерацию особой ситуации #UD. Во всех типах процессоров, которые осуществляют предварительную выборку и спекулятивное (предварительное) исполнение команд прерывание UD# генерируется не на стадии декодирования или исполнения команды, а только тогда, когда процессор попытается установить или воспользоваться результатом исполнения некорректной команды. Специальные коды D6h и F1h зарезервированы Intel и не вызывают ошибки.
Прерывание 7 — Сопроцессор отсутствует (#NM): Intel286 …Генерируется в следующих ситуациях:
Т.е. прерывание генерируется, если поступает команда FPU, а сопроцессор отсутствует или поступают команды FPU, MMX, 3DNow!, SIMD или WAIT/FWAIT, а состояние сопроцессора не отвечает необходимому для данной задачи (произошло переключение задач). Флаг CR0.MP был первоначально введен в процессорах Intel286 и Intel386 и используется совместно с битом CR0.TS для определения, должна ли команда WAIT/FWAIT генерировать особую ситуацию #NM. Для программ, запускаемых на процессорах Intel486 и старше (при наличии встроенного или внешнего сопроцессора), должно быть CR0.MP = 1. Для Intel486SX (когда сопроцессор Intel487SX отсутствует) — CR0.MP = 0.
Прерывание 8 — Двойная ошибка (#DF): Intel286 …Во время выполнения перехода к обработчику прерываний и особых ситуаций может возникнуть еще одна особая ситуация или прерывание. Обычно в этом случае они просто обрабатываются последовательно одна за другой, но бывают случаи, когда это невозможно. Примером такой ситуации может служить исключение общей защиты на уровне 3, сопровождаемое исключением 11 из-за отсутствия требуемого сегмента. Прерывание #DF генерируется для индикации таких двойных ошибок, когда это возможно. Существует три класса прерываний и особых ситуаций: безопасные, способствующие и страничные. В зависимости от этого класса и порядка возникновения прерываний и особых ситуаций может генерироваться двойная ошибка.
Таблица 3.3. Условия, при которых генерируется двойная ошибка
Код ошибки помещается в стек обработчика двойной ошибки; поэтому этот код всегда нулевой. Вызвавшая ошибку команда не перезапускаема. Если во время перехода на обработчик двойной ошибки возникает еще какая-либо особая ситуация, то процессор переходит в режим останова, откуда может быть выведен только сигналами аппаратных прерываний NMI, SMI или сбросом. Если это происходит в обработчике немаскируемого прерывания NMI, то процессор может быть запущен в работу только сбросом. (На практике оказывается, что даже не все процессоры фирмы Intel ведут себя именно так, некоторые просто сбрасываются, некоторые могут, как ни в чем не бывало, продолжить работу.)
Прерывание 9 — Превышение сегмента сопроцессором : Intel286, Intel386Это прерывание поддерживается только процессорами Intel286 и Intel386. В Intel486 ... прерывание 9 считается зарезервированным и не должно использоваться. Прерывание генерируется при проверке границ сегмента, производящейся при каждом обращении сопроцессора к памяти, в случае, если произошел выход за пределы сегмента при попытке чтения/записи второго или следующих слов операнда. Прерывание может обрабатываться в той же задаче, но команда, вызвавшая эту ошибку, не перезапускаема. Процессор не сохраняет никакой информации о вызвавшей прерывание команде. Для выяснения причины прерывания необходимо обратиться к специальным регистрам сопроцессора, содержащим последнюю выполненную команду и адрес запрошенного операнда. После возникновения этого прерывания не могут быть выполнены никакие команды типа WAIT или команды FPU (кроме FINIT/FNINIT) до тех пор, пока не будет устранена причина сбоя, или сопроцессор не будет инициализирован. В тех случаях, когда Intel287 и Intel387 генерируют прерывание 9 процессоры Intel486 … генерируют ошибку общей защиты (#GP). Некоторые случаи, однако, требуют осторожности. Ошибки памяти (особенно страничные ошибки) могут потеряться, если они происходят в FLDENV или FRSTOR в то время, как процессор осуществляет переключение задач. Рекомендуется, чтобы область сохранения состояния сопроцессора находилась в той же странице, что и TSS.
Прерывание 10 — Неправильный TSS (#TS): Intel286 …Генерируется при переключении задач, если новый TSS, на который указывает шлюз задачи, является недопустимым. Недопустимыми считаются случаи, когда не только сам TSS задан не корректоно, но и когда он содержит некорректные описания сегментов кода, стека и данных для новой задачи. Код ошибки, передаваемый обработчику содержит индекс селектора ошибочного сегмента.
Таблица 3.4. Ошибки, вызывающие генерацию особой ситуации #TS
Бит EXT кода ошибки показывает, была ли особая ситуация вызвана событием внешним по отношению к программе (т.е., если внешнее прерывание осуществляет переключение задач через шлюз, задающий некорректный TSS). Это прерывание может быть вызвано, как в контексте старой задачи, так и уже в новой (т.е. регистр TR уже будет загружен новым селектором TSS). Первый случай возникает при проверке присутствия нового TSS. Если переключения задач еще не произошло, то сохраненные CS:EIP указывают на команду старой задачи, которая инициировала переключение задач, если же ошибка возникла после переключения задач, то сохраненные CS:EIP указывают на первую команду новой задачи. Обрабока данной ошибки в текущей задаче затруднена. Intel рекомендует использовать шлюз задачи для обработчика этой ошибки.
Прерывание 11 — Сегмент не присутствует (#NP): Intel286 …Генерируется, если процессор обнаруживает, что бит присутствия в дескрипторе сегмента сброшен. Это может произойти в следующих случаях:
Эта ошибка рестартируема и может обслуживаться в рамках породившей ее задачи. Код ошибки помещается в стек. Бит EXT кода ошибки устанавливается, если прерывание вызвано внешним событием. Бит IDT кода ошибки устанавливается, если код ошибки ссылается на элемент IDT (т.е. команда INT ссылается на неприсутствующий шлюз). Сохраняемые значения CS:EIP в большинстве случаев указывают на команду, приведшую к генерации ошибки. В случае, когда ошибка происходит при переключении задач, сохраняемые CS:EIP указывают на первую команду новой задачи, а если ошибка генерируется при обращении к дескриптору шлюза, то CS:EIP будут указывать на команду, осуществившую такое обращение (например, команда CALL).
Прерывание 12 — Ошибка стека (#SS): Intel286 …Генерируется в следующих случаях:
При возникновении стековой ошибки, процессор помещает код ошибки в стек обработчика. Если прерывание произошло во время переключения задач посредством межуровнего CALL из-за того, что произошло переполнение стека, или сегмент стека не присутствует, то код ошибки содержит селектор сегмента, ставшего причиной ошибки; в других случаях код ошибки всегда нулевой. Сохраняемые значения CS:EIP указывают на команду, вызвавшую ошибку. Поскольку сама эта команда не выполнена, а состояние процессора при генерации стековой ошибки остается неизменным, обработчику легко устранить причины, вызвавшие ошибку и перезапустить команду. На практике оказывается, что различные модели процессоров различных производителей могут вести себя неадекватно в реальном режиме работы. При превышении границ стекового сегмента в этом неважном на взгляд некоторых разработчиков режиме, разные процессоры могут сброситься, зависнуть, перейти в режим останова и пр.
Прерывание 13 — Общая защита (#GP): Intel286 …Все нарушения защиты, которые не учитываются в других особых ситуациях, генерируют ошибку общей защиты (#GP). Такими нарушениями могут быть:
При возникновении ошибки общей защиты процессор помещает код ошибки в стек обработчика. Если ошибка произошла при загрузке неправильного дескриптора, то код ошибки — это селектор этого дескриптора, либо его индекс в таблице IDT, во всех остальных случаях код ошибки нулевой. Сохраняемые значения CS:EIP указывают на команду, вызвавшую ошибку. Если ошибка происходит во время переключения задач, то ее генерация может произойти как до, так и после момента переключения задачи. Во втором случае процессор сначала закончит загрузку всех значений в регистры CS, SS, DS, ES, FS, GS без проверки их корректности, а затем передаст управление обработчику ошибки. Обработчик ошибки общей защиты может произвести перезапуск прерванной программы практически при всех случаях. Однако при этом возможна потеря внешних прерываний, которые явились причиной генерации ошибки общей защиты. В реальном режиме прерывание 13 генерируется при нарушении границы 0FFFFh в сегментах CS, DS, ES, FS, GS.
Прерывание 14 — Страничная ошибка (#PF): Intel386 …Генерируется, если страничный механизм активизирован (CR0.PG = 1) и при трансляции линейного адреса в физический возникает одна из следующих ситуаций:
Обработчик страничной ошибки получает информацию о ее причине из двух источников: кода ошибки, помещаемого в стек, и содержимого регистра CR2, который содержит линейный адрес, вызвавший ошибку. Код страничной ошибки имеет специальный формат (рис. 3.7.).
Рис. 3.7. Формат кода страничной ошибки
Прерванная программа после устранения причин, вызвавших страничную ошибку (например, загризки страницы в физическую память), может быть продолжена без каких-либо дополнительных корректировок. Если страничная ошибка была вызвана в связи с нарушением привилегий страничной защиты, то бит доступа (A) в соответствующем элементе каталога страниц устанавливается. Поведение бита доступа в соответствующем элементе таблиц страниц для этого случая не регламентируется в процессорах Intel и может быть разным в различных моделях.
Прерывание 16 — Ошибка сопроцессора (#MF): Intel286 …Это прерывание сигнализирует об ошибке, возникшей во время выполнения команды FPU. Т.е. в результате выполнения команды имело место незамаскированное исключение FPU (с помощью регистра управления FPU можно замаскировать все исключения) . В Intel286 и Intel386 это прерывание генерируется при подаче сигнала на специальный вывод микропроцессора ERROR#, который должен подключаться к соответствующему выходу сопроцессора. В более поздних моделях (Intel486 …), где сопроцессор встроенный, генерация ошибки #MF происходит без использования внешних сигналов. Специальный флаг CR0.NE управляет режимом реакции таких процессоров на исключения FPU. Ошибка генерируется только, если CR0.NE = 1 во время выполнения команды FPU/MMX/3DNow!, следующей за командой, вызвавшей ошибку. Когда CR0.NE = 0 реакция на исключения FPU происходит в т.н. стиле MS-DOS. В этом случае (если сигнал на входе IGNNE# неактивен), то незамаскированные ошибки сопроцессора приводят к остановке процессора перед выполнением следующей за вызвавшей ошибку команды плавающей арифметики (если это не управляющая команда) или команды WAIT. При этом, процессор ждет освобождения сопроцессора, а сопроцессор в свою очередь ожидает обслуживания исключения. Вывести процессор из этого режима возможно только внешним прерыванием, которое обычно формируется аппаратурой по появлению сигнала на выходе FERR# (Intel486 …) или ERROR# (Intel387, Intel287). Сигнал на этом выводе появляется независимо от значения бита NE при возникновении исключения в сопроцессоре. Если NE = 0, но сигнал на входе IGNNE# активен, то процессор игнорирует ошибку и продолжает выполнение программы. Поскольку сохраняемый при вызове обработчика указатель CS:EIP не всегда определяет команду, ставшую причиной генерации исключения, обработчик должен анализировать содержимое специального регистра сопроцессора FIP, который и содержит точный указатель. Важной является синхронизация потока команд FPU с другими командами процессора. Например, если команда процессора использует результат предшевствовавшей ей команды FPU, возможна потеря исключения и использование некорректного результата. Для предотвращения этого необходимо вставить команду WAIT/FWAIT после команды FPU. Обратитесь к специальной литературе для подробного изучения специфики программирования смешанных кодов. Протокол реакции на исключения FPU имеет некоторые отличия в различных моделях процессоров и сопроцессоров. Отличия эти касаются в первую очередь режима реакции в стиле MS-DOS и момента генерации ошибки сопроцессора (сразу по возникновении или при поступлении следующей команды FPU/MMX/3DNow!). В современных микропроцессорах наиболее универсальным и жестко регламентированным является режим внутренней генерации ошибки сопроцессора (CR0.NE = 1), который является основным, режим реакции в стиле MS-DOS поддерживается для совместимости. Подробное описание механизма реакции на исключения сопроцессора приведено в Intel® 64 and IA-32 Architectures Software Developer’s Manual. Volume 1: Basic Architecture.
Прерывание 17 — Контроль выравнивания (#AC): Intel486 …Генерируется при попытке доступа к невыровненным операндам. Выравнивание необходимо для следующих типов данных.
Таблица 3.5. Условия контроля выравнивания
Для активизации проверки выравнивания должны выполняться следующие условия: Сохраняемое значение CS:EIP указывает на команду доступа к невыровненным данным, вызвавшую ошибку.
Прерывание 18 — Контроль машины (#MC): Pentium …Данное прерывание впервые было введено в процессоре Pentium и поддерживается также в Pentium Pro, Pentium II, Pentium III. Оно считается зависимым от модели, т.е. в дальнейших модификациях процессоров может быть исключено. Это прерывание предназначено для выявления ошибок паритета и других неисправностей аппаратуры. Обработчик определяет причину прерывания по содержимому особых регистров процессорно зависимой архитектуры проверки машины (Mashine Check Architecture). За дополнительной информацией обратитесь к техническому описанию Intel.
Прерывание 19 — Исключение SIMD (#XM): Pentium III …Особая ситуация генерируется при возникновении незамаскированных SIMD-исключений, когда CR4.OSXMMEXCPT = 1. Бит CR4.OSXMMEXCPT управляет режимом реакции процессора на SIMD-исключения. Когда CR4.OSXMMEXCPT = 0 вместо особой ситуации XM# генерируется особая ситуация недействительный код операции (#UD), а прерывание 19 считается зарезервированным. Особая ситуация #XM генерируется сразу после команды, вызвавшей SIMD-исключение, поэтому для SIMD-команд не приходится применять специальные меры по синхронизации с другими командами, как это приходится делать с командами FPU (для которых генерация особой ситуации #MF может происходить не сразу, а на следующей команде FPU/MMX/3DNow!).
Прерывания 32…255 — Прерывания пользователяПрерывания пользователя могут генерироваться в двух случаях:
Сохраняемое значение CS:EIP при вызове внешнего прерывания указывает на команду, следующую за командой, во время выполнения которой был получен запрос на прерывание. А при программном прерывании командой INT n — на следующую команду.
|
Все права защищены © Алексей Ровдо, 1994-2023. Перепечатка возможна только по согласованию с владельцем авторских прав. admin@club155.ru