-----------------------------------------------------------------|Код Команда Число Описание ||операции тактовых || циклов || ||CF IRET 15 Возврат из прерывания || (дальний возврат и извлечение || из стека флагов) ||CF IRET 36 Возврат из прерывания || к меньшему уровню || привилегированности ||CF IRET TS+32 Возврат из прерывания, || другая задача (NT = 1) ||CF IRETD 15 Возврат из прерывания || (дальний возврат и извлечение || из стека флагов) ||CF IRETD 36 Возврат из прерывания || к меньшему уровню || привилегированности ||CF IRETD 15 Возврат из прерывания, || к режиму V86 ||CF IRET TS+32 Возврат из прерывания, || другая задача (NT = 1) |----------------------------------------------------------------- Примечание: приближенные значения ts задаются следующейтаблицей: ----------------------------------------------------------------- | Новая задача Старая задача |------------------------------------------- | к TSS i486 | к TSS 80286 | к TSS VM----------------------------------------------------------------- VM/i486/TSS 80286 | 199 | 180 | 177----------------------------------------------------------------- Работа команды IF PE = 0THEN (* Режим реальных адресов *) IF operandSize = 32 (* Команда = IRETD *) THEN EIP <- Pop(); ELSE (* Команда = IRET *) IP <- Pop(); FI; CS <- Pop(); IF OperandSize = 32 (* Команда = IRETD *) THEN EFLAGS <- Pop(); ELSE (* Команда = IRET *) FLAGS <- Pop(); FI;ELSE (* Защищенный режим *) IF VM = 1 THEN #GP(0); ELSE IF NT = 1 THEN GOTO ВОЗВРАТ-ЗАДАЧИ; ELSE IF VM = 1 в образе флагов, находящемся в стеке THEN GOTO ВОЗВРАТ-СТЕКА-К-V86; ELSE GOTO ВОЗВРАТ-СТЕКА; FI; FI; FI;FI; ВОЗВРАТ-СТЕКА-К-V86: (* Прерванная процедура в режиме V86 *) IF верхние 36 байтов стека не в пределах границ THEN #SS(0); FI; IF указатель команд не в границах кодового сегмента THEN #GP(0); FI; EFLAGS <- SS:[ESP + 8]; (* Устанавливает VM прерванной подпрограммы *) EIP <- Pop(); CS <- Pop(); (* CS ведет себя, как в 8086, т.к. VM = 1 *) Потеря <- Pop(); (* извлечение из стека с потерей уже считанного EFLAGS *) ВремESP <- Pop(); ВремSS <- Pop(); ES <- Pop(); (* Извлекаются из стека 2 слова; старшее слово отбрасывается *) DS <- Pop(); (* Извлекаются из стека 2 слова; старшее слово отбрасывается *) FS <- Pop(); (* Извлекаются из стека 2 слова; старшее слово отбрасывается *) GS <- Pop(); (* Извлекаются из стека 2 слова; старшее слово отбрасывается *) SS:ESP <- ВремSS:ВремESP; (* Возобновление выполнения в виртуальном режиме 8086 *) ВОЗВРАТ-ЗАДАЧИ: Рассмотрим селектор обратной компоновки задач в TSS, адресуемом регистром текущей задачи; В бите Локальный/Глобальный должно быть задано значение Глобальный, иначе #TS(селектор нового TSS); Индекс должен быть в границах GDT, иначе #TS(селектор нового TSS); Байт AR должен задавать TSS, иначе #TS(селектор нового TSS); TSS должен присутствовать, иначе #NP(селектор нового TSS); ПЕРЕКЛЮЧЕНИЕ-ЗАДАЧ без вложенности в TSS, заданный селектором обратной компоновки задач; Обозначение прерванной задачи как NOT BUSY (не занято); Указатель команд должен быть в пределах границ кодового сегмента, ELSE #GP(0); ВОЗВРАТ-СТЕКА: IF OperandSize = 32 THEN Третье слово в стеке должно быть в пределах границ стека, иначе #SS(0); ELSE Второе слово в стеке должно быть в пределах границ стека, иначе #SS(0); FI; RPL селектора CS возврата должен быть >= CPL, иначе #GP(селектор возврата); IF RPL селектора возврата = CPL THEN GOTO ВОЗВРАТ-НА-ТОТ-ЖЕ-УРОВЕНЬ; ELSE GOTO ВОЗВРАТ-НА-ВНЕШНИЙ-УРОВЕНЬ; FI; ВОЗВРАТ-НА-ТОТ-ЖЕ-УРОВЕНЬ: IF OperandSize = 32 THEN Верхние 12 байтов в стеке должны быть в пределах границ, иначе #SS(0); Селектор CS возврата (в eSP+4) должен быть не-пустым, иначе # #GP(0); ELSE Верхние 6 байтов в стеке должны быть в пределах границ, иначе #SS(0); Селектор CS возврата (в eSP+2) должен быть не-пустым, иначе # #GP(0); FI; Индекс селектора должен быть в границах его таблицы дескрипторов, иначе #GP(селектор возврата); Байт AR должен задавать кодовый сегмент, иначе #GP(селектор возврата); IF не-конформный THEN DPL кодового сегмента должен быть = CPL; ELSE #GP(селектор возврата); FI; IF конформный THEN DPL кодового сегмента должен быть <= CPL, иначе #GP(селектор возврата); Указатель команд должен быть в пределах границ кодового сегмента, иначе #GP(0); FI; IF OperandSize = 32 THEN Загрузка CS:IP из стека; Загрузка регистра CS дескриптором нового кодового сегмента; Загрузка EFLAGS третьим двойным словом из стека; Инкремент eSP на 12; ELSE Загрузка регистра CS дескриптором нового кодового сегмента; Загрузка EFLAGS третьим словом из стека; Инкремент eSP на 6; FI; ВОЗВРАТ-НА-ВНЕШНИЙ-УРОВЕНЬ: IF OperandSize = 32 THEN Верхние 20 байтов в стеке должны быть в пределах границ, иначе #SS(0); ELSE Верхние 10 байтов в стеке должны быть в пределах границ, иначе #SS(0); FI; Рассмотрим селектор CS возврата и связанный с ним дескриптор: Селектор должен быть не-пустым, иначе #GP(0); Индекс селектора должен быть в границах его таблицы дескрипторов, ELSE #GP(селектор возврата); Байт AR должен задавать кодовый сегмент, иначе #GP(селектор возврата); IF не-конформный THEN DPL кодового сегмента должен быть = RPL селектора CS; ELSE #GP(селектор возврата); FI; IF конформный THEN DPL кодового сегмента должен быть > CPL, ELSE #GP(селектор возврата); FI; Сегмент должен присутствовать, иначе #NP(селектор возврата); Рассмотрим селектор SS возврата и связанный с ним дескриптор: Селектор должен быть не-пустым, иначе #GP(0); Индекс селектора должен быть в границах его таблицы дескрипторов, ELSE #GP(селектор SS); RPL селектора должен быть равен RPL селектора CS возврата ELSE #GP(селектор SS); Байт AR должен задавать сегмент данных, доступный для записи, иначе #GP(селектор SS); DPL сегмента стека должен быть = RPL селектора CS возврата; ELSE #GP(селектор SS); SS должен присутствовать, иначе #NP(селектор SS); Указатель команд должен быть в пределах границ кодового сегмента, иначе #GP(0); IF OperandSize = 32 THEN Загрузка CS:EIP из стека; Загрузка EFLAGS значениями в (eSP+8); ELSE Загрузка CS:IP из стека; Загрузка FLAGS значениями в (eSP+4); FI; Загрузка SS:eSP из стека; Загрузка регистра CS дескриптором CS; Загрузка регистра SS дескриптором SS; FOR каждого из ES, FS, GS и DS DO; IF текущее значение регистра недостоверно для внешнего уровня; THEN обнуление регистра и очистка флага достоверности; FI; Чтобы быть достоверным, установка регистра должна удовлетворять следующим свойствам: Индекс селектора должен быть в границах его таблицы дескрипторов; Байт AR должен задавать сегмент данных, доступный для записи, или кодовый сегмент, доступный для чтения; IF это сегмент данных или не-конформный кодовый сегмент, THEN DPL должен быть > CPL, или DPL должен быть < RPL; OD; ОписаниеВ режиме реальных адресов команда IRET извлекает из стека указателькоманд, регистр CS и флаговый регистр, после чего возобновляет выполнениепрерванной подпрограммы.В защищенном режиме действие команды IRET зависит от установки флагавложенности задачи (NT) в регистре флагов. При извлечении из стека новогообраза флагов биты IOPL флагового регистра изменяются только при CPLравном 0.Если флаг NT очищен, команда IRET возвращается из процедуры прерывания безпереключения задачи. Код, в который происходит возврат, должен быть равнымили менее привилегированным, чем подпрограмма прерывания (как указываютбиты RPL селектора CS, извлекаемого из стека). Если код назначения менеепривилегирован, то команда IRET также извлекает из стека указатель стека иSS.Если флаг NT установлен, то команда IRET выполняется в обратнойпоследовательности относительно команд CALL или INT, вызвавшихпереключение задачи. Обновленное состояние задачи, выполняющей командуIRET, сохраняется в ее сегменте состояния задачи (TSS). При повторномвходе в задачу впоследствии выполняется код, который следует за командойIRET. Изменяемые флагиИзменяются все флаги; регистр флагов извлекается из стека. Исключения защищенного режима#GP, #NP или #SS, как указано выше в разделе "Работа команды". Исключения режима реальных адресовПрерывание 13, если какая-либо часть извлекаемого из стека операнда лежитза адресом 0FFFFH. Исключения виртуального режима 8086Сбой #GP(0), если IOPL меньше 3, что позволяет эмуляцию.