logo

Система команд x86

Программирование - Архитектура и система команд микропроцессоров x86
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

INT01

Вызов процедуры прерывания 1

Влияние команды на флаги и форматы команды:

OF

DF

IF

TF

SF

ZF

AF

PF

CF

 

 

0

0

 

 

 

 

 

 

Код

Команда

Описание

Проц.

Пример

F1

INT01 (ICEBP)

Вызов прерывания 1 (#DB, отладка)

386

(недокументированная мнемоника)

Описание:

Команда INT01 (ее также называют ICEBP) была впервые упомянута в документации на процессор Pentium Pro, но полного описания действия этой команды не было опубликовано никогда. По-видимому, эта команда поддерживается всеми моделями процессоров, начиная c Intel386, и предназначена для генерации прерывания 1. То есть по форме действия команда INT01 идентична команде INT n за исключением того, что номер прерывания задается неявно равным 1 (это в целом похоже на команду INT 3, где номер прерывания неявно равен 3).

Само название ICEBP появилось из словосочетания In-circuit emulation breakpoint (точка останова внутрисхемного эмулятора). Функционал внутрисхемной эмуляции (In-Circuit Emulator – ICE) предназначен для отладки программ на аппаратном уровне на специальных отладочных стендах (ICE-стенд). До появления защищенного режима в процессорах Intel286 аппаратным отладчикам (отладочным стендам) в целом хватало возможности пошагового исполнения с одновременным контролем сигналов на шинах процессора. Но с появлением Intel286 оказалось, что таких возможностей нехватает для эффективной отладки сложного программного обеспечения в защищенном режиме. Как следствие, в процессорах начиная с Intel386 были реализованы специальные расширения архитектуры (отладочные регистры и специальные команды), которые позволяют разработчикам как осуществлять пошаговое исполнение отлаживаемого кода, так и устанавливать точки останова по определенным событиям. Специальный режим внутрисхемной эмуляции (ICE) в этих процессорах также был существенно доработан, что позволило создавать отладочные стенды, в которых аппаратные возможности отладки существенно переплетались с соответствующими программными расширениями системы команд процессора. 

В последующих моделях процессоров функционал режима внутрисхемной эмуляции (ICE) подвергался определенным доработкам. Так что и порядок возможного использования команды ICEBP также трансформировался. Само название ICEBP со временем не прижилось. По факту, производители чипов стали выпускать специальные модификации процессоров с аппаратной поддержкой ICE для использования в составе программно-аппаратных отладочных стендов, исключив эти функции из обычных потребительских продуктов. Но если аппаратный функционал подразумевает наличие специальных выводов, которые можно подключать или не подключать к кристаллу процессора, то программная составляющая, реализуемая на уровне микроархитектуры, присутствует во всех модификациях. Так что более адекватным оказалось название INT01, поскольку именно оно отражает обычное действие данной команды — вызов прерывания 1.

В целом использование команды INT01 (ICEBP) зависит от того, какая архитектура внутрисхемного эмулятора (ICE) поддерживается данным конкретным процессором. Определенные различия имеются между процессорами до Pentium (Intel386, Intel486) и после (Pentium, Pentium Pro ... ), а для процессоров AMD — начиная с K6.

Действие команды INT01 в процессорах младших моделей может давать разный эффект в зависимости от значения специального бита перенаправления прерывания DR7.IR.

Если перенаправление прерывания неактивно (DR7.IR = 0), то INT01 в точности отвечает свой аббревиатуре и срабатывает как простой вызов программного прерывания с вектором 1 (аналогично двухбайтовой команде INT 1). То есть при встрече данной команды происходит переход к обработчику прерываний по заданному вектору. В отличие случая, когда генерируется особая ситуация отладки #DB (которая может возникнуть при установленном флаге трассировки EFLAGS.TF = 1), команда INT01 не устанавливает (и вообще никак не изменяет) значение флага трассировки EFLAGS.TF при записи образа регистра флагов EFLAGS в стек. Таким образом, после обработки прерывания и возврата управления в код прерванной процедуры не происходит последующей генерации особой ситуации отладки #DB как при пошаговом режиме работы.

Если же перенаправление прерывания установлено (DR7.IR = 1), то при поступлении команды INT01 процессор пытается взаимодействовать с оборудованием отладочного стенда для перехода к обработчику эмулятора. Но такое взаимодействие, как правило, возможно только для специальных отладочных версий микропроцессоров. Обычные тиражные (production) модели не имеют соответствующих активных выводов для взаимодействия с оборудованием стенда и могут просто зависать в данной ситуации.

Существует два способа включения перенаправления прерывания. Это можно сделать прямой установкой бита IR при записи нового значения в отладочный регистр DR7. Либо данный бит может быть установлен самим оборудованием отладочного стенда при определенных условиях.

В процессорах старших моделей (начиная с Pentium и AMD K6) эффект команды INT01 совершенно аналогичен, но сама архитектура работы отладчика была изменена и взаимодействие процессора с отладочным стендом стало осуществляться через специальный отладочный порт. В этих процессорах режим перенаправления прерывания включается и выключается через запись в специальный регистр модели Probe Mode Control Register (PMCR). При этом запись и чтение данного регистра возможны только через отладочный порт и нет никакого программного механизма для этого. Такая архитектура добавила гибкости в механизм отладки, так как она позволяет вкллючать перенаправление прерывания и переходить к эмуляции в любой момент исполнения программного кода.

Операция:

Представленный здесь алгоритм описывает не только поведение процессора при выполнении команды INT01, но и при поступлении любого внешнего прерывания или генерации особой ситуации.

 

IF CR0.PE = 0

   THEN GOTO REAL-ADDRESS-MODE;

   ELSE

      IF ( EFLAGS.VM = 1 AND EFLAGS.IOPL < 3 AND

          ( INT n ) AND

          ( CR4.VME = 0 OR CR4.VME = 1 AND IRB[n] = 1 ) 

         ) (* IRB[n] - бит, соответствующий прерыванию n в карте перенаправления прерываний *)

         THEN

            #GP(0); (Программное прерывание INT n в режиме: (1) V86 при EFLAGS.IOPL < 3, (2) EV86 Режим 2 *)

         ELSE (* Защищенный режим или режим V86/EV86 *)

            IF ( EFLAGS.VM = 1 AND CR4.VME = 1 AND

                ( INT n ) AND IRB[n] = 0 )

               THEN GOTO EV86-MODE; (* EV86: Режим 3 или Режим 5 *)

               ELSE GOTO PROTECTED-MODE; (* Аппаратные прерывания, особые ситуации; программные прерывания INT n в режиме: (1) Защищенный режим, (2) V86 при EFLAGS.IOPL = 3, (3) EV86 Режим 1 или Режим 4 *)

            FI;

      FI;

FI;

END;

 

REAL-ADDRES-MODE:

IF ( (Номер прерывания * 4) + 3 выходит за пределы сегмента при обращении к таблице векторов прерываний IVT ) THEN #GP; FI;

IF ( В стеке нет места для 6 байт ) THEN #SS; FI;

Push(FLAGS);

EFLAGS.IF = 0; (* Сброс флага прерываний *)

EFLAGS.TF = 0; (* Сброс флага ловушки *)

EFLAGS.AC = 0; (* Сброс флага режима контроля выравнивания *)

Push(CS);

Push(IP);

(* В стек не заносятся коды ошибок *)

CS = IVT[Номер прерывания * 4].selector;

EIP = IVT[Номер прерывания * 4].offset AND 0x0000FFFFh; (* старшие 16-бит регистра EIP обнуляются *)

(* Продолжение работы в режиме реальной адресации ... *)

END;

 

EV86-MODE: (* CR0.PE = 1, EFLAGS.VM = 1, CR4.VME = 1, Режим EV86 - программное прерывание INT n, при IRB[n] = 0 - Режим 3 или Режим 5 *)

IF (В стеке задачи V86 нет места для 6 байт) THEN #SS(0); FI;

tempFLAGS = FLAGS;

tempFLAGS.IOPL = 0; (* см. Примечание *)

tempFLAGS.NT = 0;

IF EFLAGS.IOPL = 3 (* Режим 3 *)

   THEN EFLAGS.IF = 0; (* Сброс флага разрешения прерываний *)

   ELSE (* EFLAGS.IOPL < 3 - Режим 5 *)

      tempFLAGS.IF = EFLAGS.VIF;

      EFLAGS.VIF = 0; (* Сброс виртуального флага прерываний *)

FI;

EFLAGS.TF = 0; (* Сброс флага ловушки *)

Push(tempFLAGS);

Push(CS);

Push(IP);

(* В стек не заносятся коды ошибок *)

CS = IVT_V86[Номер прерывания * 4].selector; (* Таблица векторов прерываний IVT_V86 располагается в начале адресного пространства задачи V86 *)

EIP = IVT_V86[Номер прерывания * 4].offset AND 0x0000FFFFh; (* старшие 16-бит регистра EIP обнуляются *)

(* Продолжение работы в режиме EV86 ... *)

END;

 

PROTECTED-MODE: (* CR0.PE = 1, Аппаратные прерывания, особые ситуации; программные прерывания INT n в режиме: (1) Защищенный режим, (2) V86 при EFLAGS.IOPL = 3, (3) EV86 Режим 1 или Режим 4 *)

IF ( (Номер прерывания * 8) + 7 не попадает в пределы таблицы IDT ) THEN #GP(номер прерывания * 8 + 2 + EXT); FI;

(* Здесь и далее в параметрах кода ошибки слагаемое +2 означает установку бита IDT кода ошибки, а слагаемое +EXT - означает установку бита EXT кода ошибки в соответствии с тем, было ли вызвавшее ошибку прерывание программным EXT = 0 или внешним EXT = 1 *)

Байт AR дескриптора должен задавать шлюз прерывания, шлюз ловушки или шлюз задачи, иначе #GP(номер прерывания * 8 + 2 + EXT);

IF (Программное прерывание или особая ситуация) (* Т.е. один из случаев INT n, INT 3, INT01, BOUND или INTO *)

   THEN

      IF ( CPL > DPL шлюза )

         THEN

            #GP(номер прерывания * 8 + 2); (* CR0.PE = 1, DPL шлюза < CPL, программное прерывание *)

      FI;

FI;

Шлюз должен присутствовать, иначе #NP(номер прерывания * 8 + 2 + EXT);

IF (Шлюз задачи)

   THEN GOTO TASK-GATE;

   ELSE

      GOTO TRAP-OR-INT-GATE; (* CR0.PE = 1, шлюз прерывания или ловушки *)

FI;

END;

 

TRAP-OR-INT-GATE: (* Защищенный режим или режим V86/EV86, шлюз ловушки или прерывания *)

Проверка нового селектора CS, заданного в дескрипторе шлюза, и соответствующего ему дескриптора из LDT или GDT:

   Селектор должен быть не нулевым, иначе #GP(EXT);

   Индекс селектора должен попадать в пределы таблицы дескрипторов, иначе #GP(селектор + EXT);

   Выбранный дескриптор должен быть дескриптором сегмента кода, иначе #GP(селектор + EXT);

   Сегмент должен присутствовать (P = 1), иначе #NP(селектор + EXT);

IF (Кодовый сегмент несогласованный) AND (DPL сегмента кода < CPL) 

   THEN

      IF EFLAGS.VM = 0

         THEN GOTO INT-TO-INTER-PRIV; (* CR0.PE = 1, EFLAGS.VM = 0, шлюз прерывания или ловушки, несогласованный кодовый сегмент, DPL сегмента кода < CPL *)

         ELSE (* EFLAGS.VM = 1 *)

            IF ( DPL нового сегмента кода ≠ 0 ) THEN #GP(Селектор кодового сегмента + EXT); FI;

            GOTO INT-FROM-V86-MODE;(* CR0.PE = 1, EFLAGS.VM = 1, шлюз прерывания или ловушки, DPL сегмента кода = 0, CPL = 3 *)

      FI;

   ELSE (* CR0.PE = 1, шлюз прерывания или ловушки, согласованный кодовый сегмент или несогласованный кодовый сегмент с DPL = CPL *)

      IF EFLAGS.VM = 1 THEN #GP(Селектор кодового сегмента + EXT); FI;

      IF ( (Кодовый сегмент согласованный) OR (DPL сегмента кода = CPL) )

         THEN GOTO INT-TO-INTRA-PRIV; (* CR0.PE = 1, шлюз прерывания или ловушки, DPL сегмента кода ≤ CPL для согласованного сегмента, DPL сегмента кода = CPL для несогласованного сегмента *)

         ELSE #GP(Селектор кодового сегмента + EXT); (* DPL > CPL для согласованного сегмента или DPL ≠ CPL для несогласованного сегмента *)

      FI;

FI;

END;

 

INT-TO-INTER-PRIV: (* Защищенный режим, шлюз прерывания или ловушки, несогласованный кодовый сегмент, DPL сегмента кода < CPL *)

IF ( Текущий TSS 32-битный )

   THEN

      TSSstackAddress = (new code segment DPL * 8) + 4

      IF ( (TSSstackAddress + 5) > Предел TSS ) (* (TSSstackAddress + 7) > Предел TSS - для некоторых моделей процессоров *)

         THEN #TS(Селектор текущего TSS + EXT);

      FI;

      NewSS = [База TSS + TSSstackAddress + 4]; (* загружается 2 байта *)

      NewESP = [База TSS + TSSstackAddress]; (* загружается 4 байта *)

   ELSE (* Текущий TSS 16-битный *)

      TSSstackAddress = (new code segment DPL * 4) + 2

      IF ( (TSSstackAddress + 3) > Предел TSS ) (* (TSSstackAddress + 4) > Предел TSS - для некоторых моделей процессоров *)

         THEN #TS(Селектор текущего TSS + EXT);

      FI;

      NewESP = [База TSS + TSSstackAddress]; (* загружается 2 байта *)

      NewSS = [База TSS + TSSstackAddress + 2]; (* загружается 2 байта *)

FI;

Проверка селектора нового стекового сегмента NewSS и соответствующего ему дескриптора из LDT или GDT:

   Селектор должен быть не нулевым, иначе #TS(EXT);

   Индекс селектора должен попадать в пределы таблицы дескрипторов, иначе #TS(SS селектор + EXT);

   RPL селектора должен быть равен DPL нового кодового сегмента, иначе #TS(SS селектор + EXT);

   DPL стекового сегмента должен быть равен DPL нового кодового сегмента, иначе #TS(SS селектор + EXT);

   Дескриптор должен иметь формат дескриптора сегмента данных, разрешенного для записи (W = 1), иначе #TS(SS селектор + EXT);

   Сегмент должен присутствовать (P = 1), иначе #SS(SS селектор + EXT);

IF (32-битный шлюз)

   THEN Новый стек должен иметь место для 20 байт (24 байт, если есть код ошибки), иначе #SS(EXT)

   ELSE Новый стек должен иметь место для 10 байт (12 байт, если есть код ошибки), иначе #SS(EXT)

FI;

Новый указатель инструкции должен попадать в пределы нового кодового сегмента, иначе #GP(EXT); (* указатель инструкции определяется значением поля OFFSET из дескриптора шлюза *)

SS:ESP = TSS(NewSS:NewESP); (* Загрузить новые значения SS и eSP из TSS *)

IF (32-битный шлюз)

   THEN CS:EIP = Gate(SELECTOR:OFFSET); (* Загрузить селектор:смещение из дескриптора 32-битного шлюза *)

   ELSE CS:IP = Gate(SELECTOR:OFFSET); (* Загрузить селектор:смещение из дескриптора 16-битного шлюза *)

FI;

Загрузить дескриптор CS в скрытую часть регистра CS;

Загрузить дескриптор SS в скрытую часть регистра SS;

IF (32-битный шлюз)

   THEN

      Push(Длинный указатель на старый стек - SS:ESP); (* 3 слова дополняются до 4 *)

      Push(EFLAGS);

      Push(Длинный указатель на точку возврата - CS:EIP); (* 3 слова дополняются до 4 *)

      Push(Код ошибки); (* Если присутствует, 4 байта *)

   ELSE

      Push(Длинный указатель на старый стек - SS:SP); (* 2 слова *)

      Push(FLAGS);

      Push(Длинный указатель на точку возврата - CS:IP); (* 2 слова *)

      Push(Код ошибки); (* Если присутствует, 2 байта *)

FI;

CPL = DPL нового кодового сегмента;

CS.RPL = CPL;

IF (Шлюз прерывания) THEN EFLAGS.IF = 0 FI; (* Сбросить флаг прерывания *)

EFLAGS.TF = 0;

EFLAGS.NT = 0;

EFLAGS.RF = 0;

(* Продолжение работы в защищенном режиме на уровне с большими привилегиями ... *)

END;

 

INT-FROM-V86-MODE: (* Режим V86/EV86, шлюз прерывания или ловушки, DPL = 0, CPL = 3 *)

(* Текущий TSS всегда 32-битный в режиме V86 *)

IF ( Предел TSS < 9 ) (* Предел TSS < 11 - для некоторых моделей процессоров *)

   THEN #TS(Селектор текущего TSS + EXT);

FI;

NewSS = [База TSS + 8]; (* загружается 2 байта *)

NewESP = [База TSS + 4]; (* загружается 4 байта *)

 

Проверка селектора нового стекового сегмента NewSS и соответствующего ему дескриптора из LDT или GDT:

   Селектор должен быть не нулевым, иначе #TS(EXT);

   Индекс селектора должен попадать в пределы таблицы дескрипторов, иначе #TS(SS селектор + EXT);

   RPL селектора должен быть равен нулю, иначе #TS(SS селектор + EXT);

   DPL стекового сегмента должен быть равен нулю, иначе #TS(SS селектор + EXT);

   Дескриптор должен иметь формат дескриптора сегмента данных, разрешенного для записи (W = 1), иначе #TS(SS селектор + EXT);

   Сегмент должен присутствовать (P = 1), иначе #SS(SS селектор + EXT);

IF (32-битный шлюз)

   THEN

      Новый стек должен иметь место для 36 байт (40 байт, если есть код ошибки), иначе #SS(EXT)   

      Новый указатель инструкции должен попадать в пределы нового кодового сегмента, иначе #GP(EXT); (* указатель инструкции определяется значением поля OFFSET из дескриптора шлюза *)

      TempEflags = EFLAGS;

      EFLAGS.VM = 0; (* Процессор выходит из режима V86 для обработки прерывания в защищенном режиме *)

      EFLAGS.NT = 0;

      EFLAGS.TF = 0;

      EFLAGS.RF = 0;

      IF (Шлюз прерывания)

         THEN EFLAGS.IF = 0;

      FI;

      TempSS = SS;

      TempESP = ESP;

      CPL = 0; (* Переключение на нулевой уровень привилегий *)

      SS:ESP = TSS(NewSS:NewESP); (* Загрузить значения SS0 и ESP0 из TSS *)

      Push(GS); (* расширяется до двух слов *)

      Push(FS); (* расширяется до двух слов *)

      Push(DS); (* расширяется до двух слов *)

      Push(ES); (* расширяется до двух слов *)

      GS = 0; (* Сегментные регистры обнуляются. Недопустимо последующее использование нулевых селекторов в защищенном режиме *)

      FS = 0;

      DS = 0;

      ES = 0;

      Push(TempSS); (* расширяется до двух слов *)

      Push(TempESP);

      Push(TempEflags);

      Push(CS); (* расширяется до двух слов *)

      Push(EIP);

      Push(Код ошибки); (* Если присутствует, 4 байта *)

      CS:EIP = Gate(SELECTOR:OFFSET); (* Загрузить селектор:смещение из дескриптора 32-битного шлюза *)

 

   ELSE (* 16-битный шлюз *)

      Новый стек должен иметь место для 18 байт (20 байт, если есть код ошибки), иначе #SS(EXT)

      (* сохранение в стеке 16-битных значений регистров происходит аналогично 32-битному шлюзу *)

      (* Возврат из прерывания командой IRET обратно в режим V86 из 16-битного сегмента будет невозможен, так как флаг VM не сохранится в стеке и не восстановится из образа EFLAGS при возврате *)

FI;

(* Продолжение работы в защищенном режиме на нулевом уровне привилегий ... *)

END;

 

INT-TO-INTRA-PRIV: (* CR0.PE = 1, DPL = CPL или согласованный сегмент с DPL ≤ CPL *)

IF (32-битный шлюз)

   THEN Новый стек должен иметь место для 12 байт (16 байт, если есть код ошибки), иначе #SS(EXT)

   ELSE Новый стек должен иметь место для 6 байт (8 байт, если есть код ошибки), иначе #SS(EXT)

FI;

Новый указатель инструкции должен попадать в пределы нового кодового сегмента, иначе #GP(EXT);

IF (32-битный шлюз)

   THEN

      Push(EFLAGS);

      Push(Длинный указатель на точку возврата); (* 3 слова дополняются до 4 *)

      CS:EIP = Gate(SELECTOR:OFFSET); (* Загрузить селектор:смещение из дескриптора 32-битного шлюза *)

      Push(Код ошибки); (* Если присутствует, 4 байта *)

   ELSE

      Push(FLAGS);

      Push(Длинный указатель на точку возврата); (* 2 слова *)

      CS:IP = Gate(SELECTOR:OFFSET); (* Загрузить селектор:смещение из дескриптора 16-битного шлюза *)

      Push(Код ошибки); (* Если присутствует, 2 байта *)

FI;

Загрузить дескриптор CS в скрытую часть регистра CS;

CS.RPL = CPL;

IF (Шлюз прерывания) THEN EFLAGS.IF = 0; FI;

EFLAGS.TF = 0;

EFLAGS.NT = 0;

EFLAGS.RF = 0;

(* Продолжение работы в защищенном режиме без изменения уровня привилегий ... *)

END;

 

TASK-GATE: (* CR0.PE = 1, шлюз задачи *)

Проверка селектора TSS из дескриптора шлюза задачи:

   Селектор должен задавать GDT (бит TI = 0), иначе #GP(TSS селектор + EXT);

   Индекс селектора должен попадать в пределы таблицы GDT, иначе #GP(TSS селектор + EXT);

Проверка соответствующего выбранному селектору дескриптора TSS:

   Дескриптор TSS должен иметь тип свободного TSS (TYPE.B = 0), иначе #GP(TSS селектор + EXT);

   TSS должен присутствовать (P = 1), иначе #NP(TSS селектор + EXT);

SWITCH-TASKS(С вложением) в TSS; (* здесь "С вложением" означает тот факт, что при инициализации контекста новой задачи будет установлен флаг EFLAGS.NT = 1, а в поле LINK ее сегмента TSS будет скопирован селектор TSS прерываемой (старой) задачи – см. Адресация и многозадачность: Средства поддержки мультизадачности *)

IF (Прерывание представляет собой особую ситуацию с кодом ошибки)

   THEN

      В стеке должно быть место для кода ошибки, иначе #SS(EXT);

      Push(код ошибки);

FI;

Указатель инструкции EIP должен попадать в пределы сегмента CS, иначе #GP(EXT);

(* Загрузка контекста новой задачи сопровождается дополнительными проверками как это описано в разделе Адресация и многозадачность: Средства поддержки мультизадачности *)

(* Продолжение работы в контексте новой задачи ... *)

END;

 

Особые ситуации защищенного режима:

Представленный здесь перечень особых ситуаций характеризует поведение процессора не только при выполнении команды INT01, но и при поступлении любого внешнего прерывания или генерации особой ситуации. Бит EXT в коде ошибки используется для индикации внешнего по отношению к прерванной программе события (внешнего прерывания).

#GP(индекс прерывания * 8 + 2 + EXT), если:

#GP(0 + EXT), если указатель команды (OFFSET) в дескрипторе шлюза из таблицы IDT не попадает в пределы кодового сегмента.

#GP(код ошибки), если:

#TS(код ошибки), если:

#NP(код ошибки), если:

#SS(0 + EXT), если:

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

#BP, если исполняется команда INT 3.
#OF, если исполняется команда INTO и флаг EFLAGS.OF = 1.

Intel386 … :
#PF(Код ошибки) при страничной ошибке.
#UD при использовании префикса LOCK.
#DB, если исполняется команда INT01.

Intel486 … :
#AC(EXT) при невыровненной ссылке в память, если активирован контроль выравнивания (CR0.AM = 1, EFLAGS.AC = 1, CPL = 3).

 

Особые ситуации режима реальной адресации:

Представленный здесь перечень особых ситуаций характеризует поведение процессора не только при выполнении команды INT01, но и при поступлении любого внешнего прерывания или генерации особой ситуации.

#GP, если вектор прерывания превышает предел таблицы векторов прерываний (IVT) (предел таблицы векторов прерываний может быть задан при программировании регистра IDTR).
#SS, при нарушении границ стекового сегмента во время сохранения данных в стеке.
#BP, если исполняется команда INT 3.
#OF, если исполняется команда INTO и флаг EFLAGS.OF = 1.

Intel386 … :
#UD при использовании префикса LOCK.
#DB, если исполняется команда INT01.

 

Особые ситуации режима V86:

Представленный здесь перечень особых ситуаций характеризует поведение процессора не только при выполнении команды INT01, но и при поступлении любого внешнего прерывания или генерации особой ситуации. Бит EXT в коде ошибки используется для индикации внешнего по отношению к прерванной программе события (внешнего прерывания).

#GP(индекс прерывания * 8 + 2 + EXT), если:

#GP(0), если исполняется команда INT n когда текущий уровень привилегий ввода/вывода EFLAGS.IOPL < 3 (кроме режима EV86).

#GP(0 + EXT), если указатель команды (OFFSET) в дескрипторе шлюза из таблицы IDT не попадает в пределы кодового сегмента.

#GP(код ошибки), если:

#TS(код ошибки), если:

#NP(код ошибки), если:

#SS(0 + EXT), если:

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

#BP, если исполняется команда INT 3.
#OF, если исполняется команда INTO и флаг EFLAGS.OF = 1.

Intel386 … :
#PF(Код ошибки) при страничной ошибке.
#UD при использовании префикса LOCK.
#DB, если исполняется команда INT01.

Intel486 … :
#AC(EXT) при невыровненной ссылке в память, если активирован контроль выравнивания (CR0.AM = 1, EFLAGS.AC = 1, CPL = 3).

Pentium (в режиме EV86):
#GP(0), если исполняется команда INT n когда текущий уровень привилегий ввода/вывода EFLAGS.IOPL < 3, а соответствующий прерыванию бит карты перенаправления прерываний IRB равен 1.

 

Замечание:

Команды INT 1 и INT01 (ICEBP) вызывают генерацию особой ситуации типа ошибки трассировки (Fault) (не ловушкиTrap). При этом, в отличие от пошагового исполнения через установку флага EFLAGS.TF, не происходит записи в отладочный регистр DR6 служебной информации о точке останова.


Входит в группу команд: Базовая система команд CPU

Все права защищены © Алексей Ровдо, 1994-2023. Перепечатка возможна только по согласованию с владельцем авторских прав. admin@club155.ru

Top.Mail.Ru       Сервер радиолюбителей России - схемы, документация,

 соревнования, дипломы, программы, форумы и многое другое!   схемы новости электроники