logo

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

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

RET

Возврат из процедуры

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

OF

DF

IF

TF

SF

ZF

AF

PF

CF

 

 

 

 

 

 

 

 

 

 

Код

Команда

Описание

Проц.

Пример

C3

RET

Ближний возврат из процедуры

8086

retn

CB

RET

Дальний возврат из процедуры

8086

retf

C2 iw

RET imm16

Ближний возврат из процедуры с освобождением imm16 байт в стеке

8086

retn 2

CA iw

RET imm16

Дальний возврат из процедуры с освобождением imm16 байт в стеке

8086

retf 6

Описание:

Команда RET предназначена для возврата из подпрограмм, она передает управление по адресу возврата, выбираемому из стека. Этот адрес обычно помещается в стек командой CALL. Необязательный числовой параметр команды RET указывает количество байт, которые команда дополнительно освобождает в стеке после извлечения адреса возврата (эти байты могли содержать, например, параметры покидаемой подпрограммы, переданные командой CALL-через_шлюз_вызова).

Поддерживается две разновидности команды возврата: ближняя и дальняя. Ближний возврат позволяет передавать управление только внутри одного кодового сегмента, дальний — допускает межсегментные переходы.

Для ближнего возврата восстанавливаемый из стека адрес является абсолютным смещением в сегменте, которое помещается в указатель команд (регистр CS при этом не изменяется). Для дальнего возврата адрес в стеке является дальним указателем, первым извлекается смещение, затем следует селектор.

В реальном режиме регистры CS и IP загружаются сразу без каких-либо проверок.

В защищенном режиме дальний возврат инициализирует проверку селектора и дескриптора адреса возврата. Кроме этого, возврат к меньшему уровню привилегий вызывает перезагрузку стека SS:eSP значением, сохраненным перед блоком параметров стека покидаемой процедуры. Сегментные регистры DS, ES, FS и GS могут быть очищены при выполнении дальнего возврата к меньшему уровню привилегий, если значения селекторов в этих регистрах задают сегменты, которые не могут быть использованы на новом уровне привилегий (определяется путем анализа соответствующих дескрипторов).

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

Операция:

IF (Команда ближний RET) (* RETN *)

THEN

  IF OperandSize = 16

  THEN

     6 байт в вершине стека должны попадать в пределы стекового сегмента, иначе #SS(0);

     tempEIP = Pop();

     tempEIP = tempEIP AND 0000FFFFh;

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

     EIP = tempEIP;

  ELSE (* OperandSize = 32 *)

     12 байт в вершине стека должны попадать в пределы стекового сегмента, иначе #SS(0);

     EIP = Pop();

  FI;

  IF (Команда имеет непосредственный операнд) THEN

     IF StackAddressSize = 32

        THEN

           ESP = ESP + SRC; (* Освобождение места в стеке *)

        ELSE (* StackAddressSize = 16 *)

           SP = SP + SRC; (* Освобождение места в стеке *)

     FI;

  FI;

FI;

IF (PE = 0 OR (PE = 1 AND VM = 1)) AND (Команда дальний RET)(* Реальный или виртуальный-8086 режим, RETF *)

THEN

  IF OperandSize = 16

  THEN

     6 байт в вершине стека должны попадать в пределы стекового сегмента, иначе #SS(0);

     tempEIP = Pop();

     tempEIP = tempEIP AND 0000FFFFh;

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

     EIP = tempEIP;

     CS = Pop(); (* Извлекает из стека 16 бит *)

  ELSE (* OperandSize = 32 *)

     12 байт в вершине стека должны попадать в пределы стекового сегмента, иначе #SS(0);

     EIP = Pop();

     CS = Pop(); (* Извлекает из стека 32 бита, старшие 16 бит очищаются *)

  FI;

  IF (Команда имеет непосредственный операнд) THEN SP = SP + (SRC AND FFFFh); FI;

FI;

IF (PE = 1 AND VM = 0) AND (Команда дальний RET)(* Защищенный режим, не V86 режим, команда RETF *)

THEN

  IF OperandSize = 32

  THEN Два двойных слова в вершине стека должны попадать в пределы стекового сегмента, иначе #SS(0);

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

  FI;

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

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

     RPL селектора должен быть ³ CPL, иначе #GP(Возвращаемый селектор);

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

     Байт AR дескриптора должен задавать кодовый сегмент, иначе #GP(Возвращаемый селектор);

     Для согласованного кодового сегмента RPL селектора должен быть ³ DPL CPL, иначе #GP(Возвращаемый селектор);

     Сегмент должен присутствовать, иначе #NP(Возвращаемый селектор);

  IF (RPL возвращаемого селектора = CPL)

     THEN GOTO RETURN-SAME-LEVEL;

     ELSE GOTO RETURN-OUTER-LEVEL;

  FI;

FI;

SAME-LEVEL:

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

  IF OperandSize = 32

  THEN

     EIP = Pop();

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

  ELSE (* OperandSize = 16 *)

     EIP = Pop();

     EIP = EIP AND 0000FFFFh;

     CS = Pop(); (* Выбирается 16 бит *)

  FI;

  IF (Команда имеет непосредственный операнд) THEN

     IF StackAddressSize = 32

        THEN

           ESP = ESP + SRC; (* Освобождение места в стеке *)

        ELSE (* StackAddressSize = 16 *)

           SP = SP + SRC; (* Освобождение места в стеке *)

     FI;

  FI;

OUTER-PRIVILEGE-LEVEL:

  IF OperandSize = 32

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

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

  FI;

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

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

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

     RPL селектора должен быть равен RPL возвращаемого CS селектора, иначе #GP(SS селектор);

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

     DPL сегмента стека должен быть равен RPL возвращаемого CS селектора, иначе #GP(SS селектор);

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

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

  Установить CPL равным RPL в возвращаемом CS селекторе;

  IF OperandSize = 32

  THEN

     EIP = Pop();

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

     CS.RPL = CPL;

     eSP = eSP + SRC; (* Корректировка стека покидаемой процедуры *)

     tempESP = Pop();

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

     ESP = tempESP;

     SS = tempSS;

  ELSE

     EIP = Pop();

     EIP = EIP AND 0000FFFFh;

     CS = Pop(); (* Выбирается 16 бит *)

     CS.RPL = CPL;

     eSP = eSP + SRC;

     tempESP = Pop();

     tempSS = Pop(); (* Выбирается 16 бит *)

     ESP = tempESP;

     SS = tempSS;

  FI;

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

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

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

  DO

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

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

     FI;

     Быть допустимым для текущего уровня - значит отвечать следующим условиям:

        Индекс селектора должен попадать в пределы таблицы дескрипторов;

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

        Для сегмента данных и несогласованного кодового сегмента DPL должен быть ³ CPL и DPL должен быть ³ RPL;

  OD;

  eSP = eSP + SRC; (* Корректировка стека головной процедуры *)

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

#GP, #NP или #SS, как описано в разделе "Операция". #PF(Код ошибки) при страничной ошибке.

#AC(0) при невыровненной ссылке в память при текущем уровне привилегий равном 3.

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

#GP, если возвращаемый указатель команды находится вне пространства эффективных адресов в сегменте CS.
#SS, если необходимое число байт вершины стека не находится в пространстве эффективных адресов сегмента SS.

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

Такие же, как и в режиме реальной адресации.
#PF(Код ошибки) при страничной ошибке.
#AC(0) при невыровненной ссылке в память.


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




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

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

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