logo

Главная Система команд x86 Базовая система команд CPU IRETD

Система команд 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

IRETD

Возврат из прерывания при 32-битном размере операнда

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

OF

DF

IF

TF

SF

ZF

AF

PF

CF

*

*

*

*

*

*

*

*

*

 

Код

Команда

Описание

Проц.

Пример

CF

IRET

Возврат из прерывания при 16-битном размере операнда

8086

iret

CF

IRETD

Возврат из прерывания при 32-битном размере операнда

Intel386

iretd

Описание:

Команда IRET/IRETD предназначена для возврата управления из процедуры обработчика прерывания или особой ситуации в прерванную программу. Эта команда также используется для возврата из подпрограмм, которые оформлены как вложенные задачи и вызываются командой CALL через шлюз задачи.

Мнемоники IRET и IRETD имеют один код операции. Конкретная выполняемая команда определяется атрибутом размера операнда. При 16-битном размере операнда исполняется IRET, при 32-битном — IRETD. Некоторые ассемблеры могут автоматически вставлять соответствующий префикс размера операнда перед кодом операции при трансляции мнемоник IRET и IRETD. Другие же ассемблеры воспринимают эти мнемоники одинаково и программируют только код операции. Работа команды в этом случае определяется текущей установкой размера операнда для кодового сегмента (бит D дескриптора сегмента).

В режиме реальной адресации (CR0.PE = 0) команда IRET/IRETD последовательно выбирает из стека указатель команд (E)IP, регистр CS и регистр флагов (E)FLAGS и продолжает выполнение прерванной программы или процедуры.

В защищенном режиме (CR0.PE = 1) действие команды IRET/IRETD зависит от текущего значения флага вложенной задачи (EFLAGS.NT), флага виртуального режима (EFLAGS.VM), текущего и возвращаемого уровней привилегий (CPL), текущего уровня привилегий ввода/вывода (EFLAGS.IOPL), флага активации расширений виртуального режима (CR4.VME), флага отложенного виртуального прерывания (EFLAGS.VIP) и битов VM, IF, TF в образе регистра флагов в стеке. Различают следующие типы возврата из прерывания:

 

Если флаг вложенной задачи установлен (EFLAGS.NT = 1), то команда IRET/IRETD производит действие обратное действиям команды CALL или INT, которая вызвала переключение задачи. Обновленное состояние задачи при выполнении команды IRET/IRETD сохраняется в сегменте состояния задачи. При этом команда IRET/IRETD меняет статус занятости в дескрипторе TSS покидаемой задачи на «свободно» (бит B = 0 в поле TYPE дескриптора), а также сбрасывает бит NT в сохраняемом в соответствующем сегменте TSS образе регистра (E)FLAGS. Состояние занятости в дескрипторе TSS новой задачи, в которую передается управление, командой IRET/IRETD не изменяется, так как оно должно было установиться в «занято» (бит B = 1 в поле TYPE дескриптора) в момент передачи управления во вложенную задачу командой CALL или INT. Программы любого уровня привилегий могут устанавливать флаг EFLAGS.NT = 1. Это однако не позволяет нарушать правила защиты, так как целостность и последовательность обращения к вложенным задачам обеспечивается через поле обратной связи (LINK) сегмента TSS. Команда IRET/IRETD передает управление только в ту задачу, которая (точнее, селектор дескриптора TSS которой) указана в поле LINK сегмента TSS покидаемой задачи.

Если флаг вложенной задачи сброшен (EFLAGS.NT = 0), то команда IRET/IRETD возвращает управление из процедуры прерывания без переключения задачи. Код, которому возвращается управление в защищенном режиме, должен быть равно или менее привилегирован, чем процедура прерывания (что задается битами RPL селектора CS, получаемого из стека).

При возврате из процедуры обработчика прерывания или особой ситуации в защищенном режиме процессор, как и в режиме реальной адресации, автоматически считывает из стека сохраненные ранее значения регистров (E)IP, CS и (E)FLAGS. Если код назначения менее привилегирован, то команда IRET/IRETD также получает из стека указатель стека (E)SP и селектор стекового сегмента SS. Когда из стека загружается новое значение регистра флагов (E)FLAGS, то изменение флага разрешения прерываний IF возможно только при выполнении условия CPL ≤ IOPL (текущие значения до перегрузки). Сами же биты уровня привилегий ввода/вывода (IOPL) изменяются только если текущий уровень привилегий CPL = 0.

Если происходит возврат в программу режима V86, то из стека также загружаются значения сегментных регистров ES, DS, FS, GS.

В режиме V86 доступен только возврат без выхода из этого режима. То есть флаг виртуального режима EFLAGS.VM, если он был установлен, уже нельзя сбросить командой IRETD, загрузив новое значение из образа в стеке. Это, однако, возможно, если речь идет о возврате из вложенной задачи, которая была ранее вызвана командами CALL или INT с использованием шлюза задачи. Также при использовании команды IRET/IRETD в режиме V86 (когда виртуальные прерывания не активированы – CR4.VME = 0) невозможно модифицировать биты RF, IOPL, VIP и VIF регистра EFLAGS. Если при вызове команды IRET/IRETD в режиме V86 текущий уровень привилегий ввода/вывода EFLAGS.IOPL меньше текущего уровня привилегий задачи (то есть EFLAGS.IOPL < 3), то генерируется ошибка общей защиты (#GP) и управление передается в обработчик этой ошибки. Такое поведение называется IOPL-чувствительностью и в режиме V86 характерно также для команд CLI, STI, POPF/POPFD, PUSHF/PUSHFDINT n.

В режиме EV86 (при активированных виртуальных прерываниях – CR4.VME = 1) возможно использование команды IRET (16-битный размер операнда), когда соблюдается требование EFLAGS.IOPL < 3. В таком случае команда не позволяет изменять флаг IF или устанавливать флаг TF регистра FLAGS, но вместо загрузки флага прерываний IF его образ копируется во флаг виртуальных прерываний VIF в старшем слове регистра EFLAGS, а при попытке установки флага трассировки TF генерируется ошибка общей защиты #GP(0). Для обеспечения обработки отложенных виртуальных прерываний ошибка общей защиты #GP(0) генерируется также тогда, когда команда IRET пытается загрузить из стека образ с установленным значением бита IF при уже установленном флаге отложенного виртуального прерывания EFLAGS.VIP.

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

Немаскируемые прерывания (NMI) не блокируются флагом EFLAGS.IF, но такая блокировка возникает сразу после генерации немаскируемого прерывания. Блокировка действует вплоть до первого исполнения команды IRET/IRETD, которая ее и снимает.

Операция:

IF CR0.PE = 0

   THEN GOTO REAL_ADDRESS_MODE;

   ELSE GOTO PROTECTED_MODE;

FI;

 

REAL_ADDRESS_MODE:

IF OperandSize = 32 (* Команда IRETD *)

   THEN

      IF ( 12 байт из вершины стека выходят за его пределы )

         THEN #SS;

      FI;

      tempDWORD = SS:[ESP] (* 4 байта из вершины стека *)

      IF ( tempDWORD[31:16] ≠ 0 ) THEN #GP; FI;

      EIP = Pop(); (* 32-битная выборка *)

      CS = Pop(); (* 32-битная выборка, старшие 16 бит отбрасываются *)

      tempEFLAGS = Pop();

      EFLAGS = (tempEFLAGS AND 0x257FD5h) OR (EFLAGS AND 0x1A0000h); (* флаги VIP, VIF, VM регистра EFLAGS не изменяются *)

   ELSE (* OperandSize = 16 - команда IRET *)

      IF ( 6 байт из вершины стека выходят за его пределы )

         THEN #SS;

      FI;

      EIP = Pop() AND 0x0000FFFFh; (* 32-битная выборка, старшие 16 бит сбрасываются *)

      CS = Pop(); (* 16-битная выборка *)

      FLAGS = Pop(); (* 16-битная выборка, флаги в старшем слове регистра EFLAGS не изменяются *)

FI;

END;

 

PROTECTED_MODE:

IF EFLAGS.VM = 1 (* Виртуальный режим: CR0.PE = 1, EFLAGS.VM = 1 *)

   THEN GOTO RETURN_FROM_V86; (* CR0.PE = 1, EFLAGS.VM = 1 *)

   ELSE (* EFLAGS.VM = 0 *)

      IF EFLAGS.NT = 1

         THEN GOTO TASK_RETURN; (* CR0.PE = 1, EFLAGS.VM = 0, EFLAGS.NT = 1 *)

         ELSE (* EFLAGS.NT = 0 *)

            IF OperandSize = 32

               THEN

                  IF ( 12 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

                  tempEIP = Pop();

                  tempCS = Pop();

                  tempEFLAGS = Pop();

               ELSE (* OperandSize = 16 *)

                  IF ( 6 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

                  tempEIP = Pop() AND 0x0000FFFFh; (* 16-битная выборка, старшее слово сбрасывается *)

                  tempCS = Pop(); (* 16-битная выборка *)

                  tempEFLAGS[15:0] = Pop(); (* 16-битная выборка *)

            FI;

            IF tempEFLAGS.VM = 1 AND CPL = 0

               THEN GOTO RETURN_TO_V86(* VM = 1 в образе флагов в стеке *)

               ELSE GOTO PROTECTED_MODE_RETURN; (* VM = 0 в образе флагов в стеке *)

            FI;

      FI;

FI;

END;

 

RETURN_FROM_V86:

IF EFLAGS.IOPL = 3 (* Виртуальный режим: CR0.PE = 1, EFLAGS.VM = 1, EFLAGS.IOPL = 3 *)

   THEN

      IF OperandSize = 16

         THEN

            IF ( 6 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

            IF ( Указатель команды из вершины стека не попадает в пределы кодового сегмента ) THEN #GP(0); FI;

            EIP = Pop() AND 0x0000FFFFh; (* 16-битная выборка, старшее слово сбрасывается *)

            CS = Pop(); (* 16-битная выборка *)

            tempFLAGS = Pop() AND NOT 0xB02Ah; (* 16-битная выборка, поле IOPL маскируется при выборке нового значения FLAGS из стека *)

            FLAGS = ( FLAGS AND 0x3002h ) OR tempFLAGS; (* Поле IOPL регистра FLAGS не модифицируется *)

         ELSE (* OperandSize = 32 *)

            IF ( 12 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

            IF ( Указатель команды из вершины стека не попадает в пределы кодового сегмента ) THEN #GP(0); FI;

            EIP = Pop();

            CS = Pop(); (* 32-битная выборка, старшие 16 бит отбрасываются *)

            tempEFLAGS = Pop() AND NOT 0x1BB02Ah; (* 32-битная выборка, биты RF, VM, IOPL, VIP и VIF маскируются при выборке нового значения EFLAGS из стека *)

            EFLAGS = ( EFLAGS AND 0x1B3002h ) OR tempEFLAGS; (* Биты RF, VM, IOPL, VIP и VIF регистра EFLAGS не модифицируются *)

      FI;

   ELSE (* EFLAGS.IOPL < 3 *)

      IF ( (CR4.VME = 0) or (OperandSize = 32) )

         THEN #GP(0); (* Ловушка монитора V86 *)

         ELSE (* CR4.VME = 1 и OperandSize = 16 *)

            IF ( 6 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

            IF ( Указатель команды из вершины стека не попадает в пределы кодового сегмента ) THEN #GP(0); FI;

            IF ( [SP+4].TF = 1 ) (* Образ регистра FLAGS в стеке содержит флаг TF = 1 *)

               THEN #GP(0); (* Ловушка монитора V86 *)

               ELSE 

                  IF ( EFLAGS.VIP = 1 and [SP+4].IF = 1 ) (* Попытка установки флага IF когда уже установлен флаг VIP *)

                     THEN #GP(0); (* Ловушка монитора V86 *)

                     ELSE

                        EIP = Pop() AND 0x0000FFFFh; (* 16-битная выборка, старшее слово сбрасывается *)

                        CS = Pop(); (* 16-битная выборка *)

                        tempFLAGS = Pop(); (* 16-битная выборка *)

                        EFLAGS.VIF = tempFLAGS.IF;

                        tempFLAGS = tempFLAGS AND NOT 0xB22Ah; (* биты IOPL и IF регистра FLAGS маскируются *)

                        FLAGS = ( FLAGS AND 0x3302h ) OR tempFLAGS; (* Биты IOPL, IF, TF регистра FLAGS не модифицируются *)

                  FI;

            FI;

      FI;

FI;

(* Продолжение работы в виртуальном-8086 режиме ... *)

END;

 

RETURN_TO_V86: (* Прерывание было обработано в защищенном режиме: CR0.PE = 1, VM = 0 *)

(* В образе флагов в стеке VM = 1 - производится возврат из защищенного режима в режим V86 *)

IF ( 24 байт из вершины стека выходят за его пределы ) THEN #SS(0); FI;

IF (Указатель команды из вершины стека не попадает в пределы кодового сегмента) THEN #GP(0); FI;

CS = tempCS;

EIP = tempEIP;

EFLAGS = tempEFLAGS;

TempESP = Pop();

TempSS = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

ES = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

DS = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

FS = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

GS = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

SS:ESP = TempSS:TempESP;

CPL = 3;

(* Продолжение работы в виртуальном-8086 режиме ... *)

END;

 

TASK_RETURN: (* CR0.PE = 1, EFLAGS.VM = 0, EFLAGS.NT = 1 *)

Проверка селектора обратной связи LINK в TSS текущей задачи:

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

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

Проверка дескриптора TSS новой задачи в таблице GDT, на который указывает селектор обратной связи LINK в TSS текущей задачи:

   Дескриптор должен иметь тип "дескриптор TSS" и признак занятого (TYPE.B = 1), иначе #TS(новый TSS селектор);

   Предел в поле Limit дескриптора TSS должен быть больше 107 (для 32-битного TSS) или 43 (для 16-битного TSS), иначе #TS(новый TSS селектор);

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

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

Пометить покинутую задачу, как не занятую (TYPE.B = 0);

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

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

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

END;

 

PROTECTED_MODE_RETURN: (* Прерывание было обработано в защищенном режиме: CR0.PE = 1, VM = 0 *)

(* tempEFLAGS.VM = 0 - возврат в защищенный режим *)

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

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

   Селектор должен задавать индекс дескриптора попадающий в пределы соответствующей таблицы дескрипторов, иначе #GP(tempCS);

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

   tempCS.RPL ≥ CPL, иначе #GP(tempCS);

   Если задаваемый селектором дескриптор описывает согласованный кодовый сегмент, то DPL дескриптора ≤ tempCS.RPL, иначе #GP(tempCS);

IF (tempCS.RPL > CPL)

   THEN GOTO RETURN-OUTER-PRIV-LEVEL;

   ELSE GOTO RETURN-SAME-PRIV-LEVEL;

FI;

END;

 

RETURN-SAME-PRIV-LEVEL: (* возврат в защищенный режим: tempEFLAGS.VM = 0, tempCS.RPL = CPL *)

IF tempEIP не попадает в пределы кодового сегмента THEN #GP(0); FI;

EIP = tempEIP;

CS = tempCS;

EFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT) = tempEFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT);

IF OperandSize = 32

   THEN EFLAGS(RF, AC, ID) = tempEFLAGS(RF, AC, ID);

FI;

IF CPL ≤ EFLAGS.IOPL

   THEN EFLAGS.IF = tempEFLAGS.IF;

FI;

IF CPL = 0 (* tempEFLAGS.VM = 0 *)

   THEN

      EFLAGS.IOPL = tempEFLAGS.IOPL;

      IF OperandSize = 32

         THEN EFLAGS(VM, VIF, VIP) = tempEFLAGS(VM, VIF, VIP);

      FI;

FI;

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

END;

 

RETURN-OUTER-PRIV-LEVEL: (* возврат в защищенный режим: tempEFLAGS.VM = 0, tempCS.RPL > CPL *)

IF OperandSize = 32

   THEN

      В пределы стека должны попадать верхние 8 байт, иначе #SS(0);

      tempESP = Pop();

      tempSS = Pop(); (* Выбирается 2 слова, старшее слово отбрасывается *)

   ELSE

      В пределы стека должны попадать верхние 4 байт, иначе #SS(0);

      tempESP = Pop() AND 0x0000FFFFh; (* 16-битная выборка, старшее слово сбрасывается *)

      tempSS = Pop(); (* 16-битная выборка *)

FI;

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

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

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

   tempSS.RPL = tempCS.RPL, иначе #GP(tempSS);

   AR байт дескриптора должен задавать разрешенный для записи сегмент данных, иначе #GP(tempSS);

   tempSS.DPL = tempCS.RPL, иначе #GP(tempSS);

   Сегмент должен присутствовать, иначе #SS(tempSS);

tempEIP должен попадать в пределы кодового сегмента, иначе #GP(0);

EIP = tempEIP;

CS = tempCS;

EFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT) = tempEFLAGS(CF, PF, AF, ZF, SF, TF, DF, OF, NT);

IF OperandSize = 32

   THEN

      EFLAGS(RF, AC, ID) = tempEFLAGS(RF, AC, ID);

FI;

SS:ESP = TempSS:TempESP;

IF CPL ≤ IOPL THEN EFLAGS.IF = tempEFLAGS.IF; FI;

IF CPL = 0

   THEN

      EFLAGS.IOPL = tempEFLAGS.IOPL;

      IF OperandSize = 32

         THEN EFLAGS(VM, VIF, VIP) = tempEFLAGS(VM, VIF, VIP);

      FI;

FI;

CPL = tempCS.RPL;

 

DO (Для каждого из регистров ES, FS, GS и DS)

   IF (Селектор в регистре задает сегмент данных или несогласованный кодовый сегмент, при этом CPL > DPL дескриптора сегмента)

      THEN (* Значение регистра недопустимо для текущего уровня привилегий *)

         Селектор = 0; (* Обнулить регистр *)

   FI;

OD;

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

END;

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

#GP(0), если возвращается нулевой селектор кодового или стекового сегмента.
#GP(0), если возвращаемый указатель команды EIP не попадает в пределы кодового сегмента.

#GP(селектор), если:

#TS(селектор нового TSS), если:

#SS(0) если при извлечении данных из стека просходит выход за допустимую верхнюю границу стекового сегмента.
#NP(селектор) если возвращаемый кодовый или стековый сегмент, либо дескриптор TSS возвращаемой задачи, отмечен как неприсутствующий (бит P соответствующего дескриптора сегмента сброшен).

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

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

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

#GP, если возвращаемый указатель команды не попадает в допустимые для реального режима пределы кодового сегмента;
#SS, если при извлечении данных из стека просходит выход за допустимую для реального режима верхнюю границу стекового сегмента.

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

#GP(0), если возвращаемый указатель команды EIP не попадает в пределы кодового сегмента.
#GP(0), если уровень привилегий ввода/вывода не равен 3 (EFLAGS.IOPL ≠ 3) (кроме режима EV86).
#SS(0), если при извлечении данных из стека просходит выход за допустимую верхнюю границу стекового сегмента.
#UD при использовании префикса LOCK.
#PF(Код ошибки) при страничной ошибке.

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

Pentium … (в режиме EV86):
#GP(0), если атрибут размера операнда не равен 16.
#GP(0), если загружаемый образ регистра FLAGS в стеке содержит установленный флаг трассировки TF = 1.
#GP(0) при попытке загрузки из образа в стеке установленного флага разрешения прерываний EFLAGS.IF когда уже установлен флаг отложенного виртуального прерывания  EFLAGS.VIP = 1.

Замечание:

Команды IRET/IRETD относятся к так называемым сериализующим командам (Serializing instructions), которые не могут исполняться различными оптимизирующими механизмами вне порядка их следования (out-of-order). Более того, процессор ультимативно очищает все свои буферы параллельного и опережающего исполнения команд в тот момент, когда заканчивается исполнение сериализующей команды. По факту это может оказывать заметное негативное влияние на скорость исполнения кода в целом (особенно, если сериализующих команд в нем много). Поэтому использование сериализующих команд в критических к скорости исполнения блоках кода рекомендуется минимизировать.

Программа-монитор режима V86 предусматривает, что привилегированные команды, нарушающие модель защиты при текущем уровне привилегий ввода/вывода EFLAGS.IOPL < 3, обрабатываются через вызов особой ситуации общей защиты (#GP). Но если флаг TF будет установлен командой IRET в режиме EV86, то вслед за ней по логике должна будет генерироваться особая ситуация отладки (#DB). Чтобы предотвратить несанкционированный монитором V86 переход к обработчику особой ситуации отладки (#DB), процессор проверяет образ, извлекаемый из стека, и при попытке установки флага TFрежиме EV86 когда EFLAGS.IOPL < 3) генерирует особую ситуации общей защиты (#GP). По всей видимости, эта «фича» существует с самого момента появления режима виртуальных прерываний в процессоре Pentium, хотя о ней и не было информации в официальной документации. Вместе с тем, замечено, что описанное изменение флага TF командой IRET в некоторых моделях процессоров может отрабатываться иначе и не приводить к генерации особой ситуации общей защиты (#GP) (это, похоже, является ошибкой или еще одной «фичей», которая также никогда официально не описывалась). Аналогичное ограничение (и ошибка) существует и для команды POPF.

В некоторых моделях процессоров возможна ошибочная генерация особой ситуации #GP вместо #SS, когда команда IRET/IRETD нарушает границу стекового сегмента.


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




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

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

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