RET

从程序返回

stableVMJITAOTinstruction

编码

操作码指令Op/En64 位兼容/传统说明
C3RETZO有效有效即将恢复呼叫程序。
CBRETZO有效有效继续呼叫程序
C2 iwRET imm16I有效有效接近返回调用程序, 从堆栈中 pop imm16 字节 。
CA iwRET imm16I有效有效远回调用程序,并从堆栈中弹出 imm16 字节 。

操作数编码

每个模式对应上表 Op/En 列的一个取值,说明各操作数按书写顺序分别编码在指令的哪个字段,以及指令对它是读、是写还是两者兼有。

I

  1. imm16

实测开销

未实测:不在 64 位处理器上运行。

说明

将程序控制转到堆栈顶部的返回地址。 地址通常由CALL指令放在堆栈上,返回到遵循CALL指令的指令.

可选的 源操作数 指定返回地址弹出后要释放的堆栈字节数;默认为无. 这个操作数可以用来从堆栈中释放被传递到所谓的程序并且不再需要的参数. 当用于切换到新程序的CALL指令使用非零字数的呼叫门访问新程序时,必须使用它. 在此,用于RET指令的源操作数必须指定与调用闸门的单词计数字段中指定的相同字节数.

RET 指令可用于执行三种不同类型的返回:

),有时称为区内返回。

有时也称为间断返回.

执行程序。

跨特权级返回类型只能在保护模式执行. 见英特尔(R)64和IA-32架构软件开发者手册第1卷第6章中题为"使用呼叫和RET的呼叫程序"的章节,以了解关于近、远和省际级回报的详细资料。

当执行一个接近返回时,处理器从堆栈顶部将返回的指令指针(offset)弹出到EIP寄存器中,并在新的指令指针开始程序执行. CS登记表不变.

当执行远返回时,处理器从堆栈顶部将返回的指令指针弹出到EIP寄存器中,然后从堆栈顶部将段选择子弹出到CS寄存器中. 然后处理器在新的指令指针开始在新的代码段执行程序.

跨特权级远返回的力学类似于间距返回,只是处理器检查了返回的代码和堆栈段的特权级和访问权,以确定是否允许进行控制转移. DS、ES、FS和GS区段登记册,如果是指不允许在新的特权级别进入的区段,则在跨特权级别返回期间,由RET指令批准。 由于堆栈开关也发生于跨特权级别返回上,ESP和党卫军登记器从堆栈中加载.

如果参数在中间优先级调用时被传递到所谓的程序,则必须使用可选的源操作数与RET指令一起在返回时释放参数. 这里,参数从所谓的程序堆栈和调用程序堆栈(即返回的堆栈)中释放出来.

在64位模式中,本指令的默认操作大小是堆栈地址大小,即64位. 这适用于近返回,不远返回;远返回的默认操作大小为32位.

参见第6章"程序调用,中断,和例外",第18章"控制流执行技术(CET)",见Intel(R)64和IA-32架构软件开发者手册,第一卷,CET细节.

启用 FRED 过渡时,执行远 RET 将改变 CPL 导致一般保护例外,执行远 RET 当 CPL 0.

指令令. 远返回后的指示可能会在早先的指示完成执行之前从内存中获取,但是在远返回前的所有指示完成执行之前不会执行(甚至推测)(后来的指示可能在先前的指示存储的数据变得全球可见之前执行).

与接近间接的CALL和接近间接的JMP不同,处理器不会在接近RET后推测执行下一个顺序指令,除非该指令也是跳跃的目标或分支预测器中的目标.

行动

(* Near return *)
IF instruction = near return

    THEN;
          IF OperandSize = 32
                THEN
                      IF top 4 bytes of stack not within stack limits
                            THEN #SS(0); FI;
                      EIP := Pop();
                      IF ShadowStackEnabled(CPL)
                            tempSsEIP = ShadowStackPop4B();
                            IF EIP != TempSsEIP
                                  THEN #CP(NEAR_RET); FI;
                      FI;
                ELSE
                      IF OperandSize = 64
                            THEN
                                  IF top 8 bytes of stack not within stack limits
                                        THEN #SS(0); FI;
                                  RIP := Pop();
                                  IF ShadowStackEnabled(CPL)
                                        tempSsEIP = ShadowStackPop8B();
                                        IF RIP != tempSsEIP
                                              THEN #CP(NEAR_RET); FI;
                                  FI;
                            ELSE (* OperandSize = 16 *)
                                  IF top 2 bytes of stack not within stack limits
                                        THEN #SS(0); FI;
                                  tempEIP := Pop();
                                  tempEIP := tempEIP AND 0000FFFFH;
                                  IF tempEIP not within code segment limits
                                        THEN #GP(0); FI;
                                  EIP := tempEIP;
                                  IF ShadowStackEnabled(CPL)
                                        tempSsEip = ShadowStackPop4B();
                                        IF EIP != tempSsEIP
                                              THEN #CP(NEAR_RET); FI;
                                  FI;
                      FI;
          FI;

          IF instruction has immediate operand


                THEN (* Release parameters from stack *)
                    IF StackAddressSize = 32
                             THEN
                                   ESP := ESP + SRC;
                             ELSE
                               IF StackAddressSize = 64
                                         THEN
                                               RSP := RSP + SRC;
                                     ELSE (* StackAddressSize = 16 *)
                                               SP := SP + SRC;
                                   FI;
                       FI;

          FI;
FI;

(* Real-address mode or virtual-8086 mode *)
IF ((PE = 0) or (PE = 1 AND VM = 1)) and instruction = far return

    THEN
          IF OperandSize = 32
                THEN
                       IF top 8 bytes of stack not within stack limits
                             THEN #SS(0); FI;
                       EIP := Pop();
                       CS := Pop(); (* 32-bit pop, high-order 16 bits discarded *)
                ELSE (* OperandSize = 16 *)
                       IF top 4 bytes of stack not within stack limits
                             THEN #SS(0); FI;
                       tempEIP := Pop();
                       tempEIP := tempEIP AND 0000FFFFH;
                       IF tempEIP not within code segment limits
                             THEN #GP(0); FI;
                       EIP := tempEIP;
                       CS := Pop(); (* 16-bit pop *)
          FI;

    IF instruction has immediate operand
          THEN (* Release parameters from stack *)
                SP := SP + (SRC AND FFFFH);

    FI;
FI;

(* Protected mode, not virtual-8086 mode *)
IF (PE = 1 and VM = 0 and IA32_EFER.LMA = 0) and instruction = far return

    THEN
          IF OperandSize = 32
                THEN
                       IF second doubleword on stack is not within stack limits
                             THEN #SS(0); FI;
                ELSE (* OperandSize = 16 *)
                       IF second word on stack is not within stack limits
                             THEN #SS(0); FI;
          FI;
          IF return code segment selector is NULL
                THEN #GP(0); FI;
          IF return code segment selector addresses descriptor beyond descriptor table limit


                THEN #GP(selector); FI;
          Obtain descriptor to which return code segment selector points from descriptor table;
          IF return code segment descriptor is not a code segment

                THEN #GP(selector); FI;
          IF return code segment selector RPL < CPL

                THEN #GP(selector); FI;
          IF return code segment descriptor is conforming and return code segment DPL > return code segment selector RPL

                THEN #GP(selector); FI;

        IF return code segment descriptor is non-conforming and return code segment DPL  return code segment selector RPL

                THEN #GP(selector); FI;
          IF return code segment descriptor is not present

                THEN #NP(selector); FI:
          IF return code segment selector RPL > CPL

                THEN GOTO RETURN-TO-OUTER-PRIVILEGE-LEVEL;
                ELSE GOTO RETURN-TO-SAME-PRIVILEGE-LEVEL;
          FI;
FI;

RETURN-TO-SAME-PRIVILEGE-LEVEL:
    IF the return instruction pointer is not within the return code segment limit
          THEN #GP(0); FI;
    IF OperandSize = 32
          THEN
                EIP := Pop();
                CS := Pop(); (* 32-bit pop, high-order 16 bits discarded *)
         ELSE (* OperandSize = 16 *)
                EIP := Pop();
                EIP := EIP AND 0000FFFFH;
                CS := Pop(); (* 16-bit pop *)
    FI;
    IF instruction has immediate operand
          THEN (* Release parameters from stack *)
               IF StackAddressSize = 32
                      THEN
                            ESP := ESP + SRC;
                    ELSE (* StackAddressSize = 16 *)
                            SP := SP + SRC;
                FI;
    FI;
    IF ShadowStackEnabled(CPL)
          (* SSP must be 8 byte aligned *)
          IF SSP AND 0x7 != 0
                THEN #CP(FAR-RET/IRET); FI;
          tempSsCS = shadow_stack_load 8 bytes from SSP+16;
          tempSsLIP = shadow_stack_load 8 bytes from SSP+8;
          prevSSP = shadow_stack_load 8 bytes from SSP;
          SSP = SSP + 24;
          (* do a 64 bit-compare to check if any bits beyond bit 15 are set *)
          tempCS = CS; (* zero pad to 64 bit *)
          IF tempCS != tempSsCS
                THEN #CP(FAR-RET/IRET); FI;
          (* do a 64 bit-compare; pad CSBASE+RIP with 0 for 32 bit LIP*)
          IF CSBASE + RIP != tempSsLIP
                THEN #CP(FAR-RET/IRET); FI;


          (* prevSSP must be 4 byte aligned *)
          IF prevSSP AND 0x3 != 0

                THEN #CP(FAR-RET/IRET); FI;
          (* In legacy mode SSP must be in low 4GB *)
          IF prevSSP[63:32] != 0

                THEN #GP(0); FI;
          SSP := prevSSP
    FI;

RETURN-TO-OUTER-PRIVILEGE-LEVEL:
    IF top (16 + SRC) bytes of stack are not within stack limits (OperandSize = 32)
    or top (8 + SRC) bytes of stack are not within stack limits (OperandSize = 16)
                THEN #SS(0); FI;
    Read return segment selector;
    IF stack segment selector is NULL
          THEN #GP(0); FI;
    IF return stack segment selector index is not within its descriptor table limits
          THEN #GP(selector); FI;
    Read segment descriptor pointed to by return segment selector;
    IF stack segment selector RPL  RPL of the return code segment selector
    or stack segment is not a writable data segment
    or stack segment descriptor DPL  RPL of the return code segment selector
                THEN #GP(selector); FI;
    IF stack segment not present
          THEN #SS(StackSegmentSelector); FI;
    IF the return instruction pointer is not within the return code segment limit
          THEN #GP(0); FI;
    IF OperandSize = 32
          THEN
                EIP := Pop();
                CS := Pop(); (* 32-bit pop, high-order 16 bits discarded; segment descriptor loaded *)
                CS(RPL) := ReturnCodeSegmentSelector(RPL);
                IF instruction has immediate operand
                       THEN (* Release parameters from called procedure's stack *)
                          IF StackAddressSize = 32
                                   THEN
                                         ESP := ESP + SRC;
                               ELSE (* StackAddressSize = 16 *)
                                         SP := SP + SRC;
                             FI;
                FI;
                tempESP := Pop();
                tempSS := Pop(); (* 32-bit pop, high-order 16 bits discarded; seg. descriptor loaded *)
         ELSE (* OperandSize = 16 *)
                EIP := Pop();
                EIP := EIP AND 0000FFFFH;
                CS := Pop(); (* 16-bit pop; segment descriptor loaded *)
                CS(RPL) := ReturnCodeSegmentSelector(RPL);
                IF instruction has immediate operand
                       THEN (* Release parameters from called procedure's stack *)
                          IF StackAddressSize = 32
                                   THEN
                                         ESP := ESP + SRC;
                               ELSE (* StackAddressSize = 16 *)


                                    SP := SP + SRC;
                        FI;
            FI;
            tempESP := Pop();
            tempSS := Pop(); (* 16-bit pop; segment descriptor loaded *)
      FI;
IF ShadowStackEnabled(CPL)
      (* check if 8 byte aligned *)
      IF SSP AND 0x7 != 0
            THEN #CP(FAR-RET/IRET); FI;
      IF ReturnCodeSegmentSelector(RPL) !=3
            THEN
                  tempSsCS = shadow_stack_load 8 bytes from SSP+16;
                  tempSsLIP = shadow_stack_load 8 bytes from SSP+8;
                  tempSSP = shadow_stack_load 8 bytes from SSP;
                  SSP = SSP + 24;
                  (* Do 64 bit compare to detect bits beyond 15 being set *)
                  tempCS = CS; (* zero extended to 64 bit *)
                  IF tempCS != tempSsCS
                        THEN #CP(FAR-RET/IRET); FI;
                  (* Do 64 bit compare; pad CSBASE+RIP with 0 for 32 bit LA *)
                  IF CSBASE + RIP != tempSsLIP
                        THEN #CP(FAR-RET/IRET); FI;
                  (* check if 4 byte aligned *)
                  IF tempSSP AND 0x3 != 0
                        THEN #CP(FAR-RET/IRET); FI;
      FI;
FI;
      tempOldCPL = CPL;

     CPL := ReturnCodeSegmentSelector(RPL);

     ESP := tempESP;

     SS := tempSS;

     tempOldSSP = SSP;

     IF ShadowStackEnabled(CPL)

          IF CPL = 3

          THEN tempSSP := IA32_PL3_SSP; FI;

          IF tempSSP[63:32] != 0

          THEN #GP(0); FI;

          SSP := tempSSP

     FI;

     (* Now past all faulting points; safe to free the token. The token free is done using the old SSP

     * and using a supervisor override as old CPL was a supervisor privilege level *)

     IF ShadowStackEnabled(tempOldCPL)

          expected_token_value = tempOldSSP | BUSY_BIT (* busy bit - bit position 0 - must be set *)

          new_token_value = tempOldSSP       (* clear the busy bit *)

          shadow_stack_lock_cmpxchg8b(tempOldSSP, new_token_value, expected_token_value)

     FI;

FI;

FOR each SegReg in (ES, FS, GS, and DS)
      DO
            tempDesc := descriptor cache for SegReg (* hidden part of segment register *)
            IF (SegmentSelector == NULL) OR (tempDesc(DPL) < CPL AND tempDesc(Type) is (data or non-conforming code)))


           THEN (* Segment register invalid *)
                 SegmentSelector := 0; (*Segment selector becomes null*)

      FI;
OD;

IF instruction has immediate operand

      THEN (* Release parameters from calling procedure's stack *)

          IF StackAddressSize = 32
                  THEN

                        ESP := ESP + SRC;
                ELSE (* StackAddressSize = 16 *)

                        SP := SP + SRC;
            FI;

FI;

(* IA-32e Mode *)
    IF (PE = 1 and VM = 0 and IA32_EFER.LMA = 1) and instruction = far return
          THEN
                IF OperandSize = 32
                      THEN
                            IF second doubleword on stack is not within stack limits
                                  THEN #SS(0); FI;
                            IF first or second doubleword on stack is not in canonical space
                                  THEN #SS(0); FI;
                      ELSE
                            IF OperandSize = 16
                                  THEN
                                        IF second word on stack is not within stack limits
                                              THEN #SS(0); FI;
                                        IF first or second word on stack is not in canonical space
                                              THEN #SS(0); FI;
                                  ELSE (* OperandSize = 64 *)
                                        IF first or second quadword on stack is not in canonical space
                                              THEN #SS(0); FI;
                            FI
                FI;
          IF return code segment selector is NULL
                THEN GP(0); FI;
          IF return code segment selector addresses descriptor beyond descriptor table limit
                THEN GP(selector); FI;
          IF return code segment selector addresses descriptor in non-canonical space
                THEN GP(selector); FI;
          Obtain descriptor to which return code segment selector points from descriptor table;
          IF return code segment descriptor is not a code segment
                THEN #GP(selector); FI;
          IF return code segment descriptor has L-bit = 1 and D-bit = 1
                THEN #GP(selector); FI;
          IF return code segment selector RPL < CPL or (CR4.FRED = 1 and return code segment selector RPL > CPL)
                THEN #GP(selector); FI;
          IF return code segment descriptor is conforming and return code segment DPL > return code segment selector RPL
                THEN #GP(selector); FI;

        IF return code segment descriptor is non-conforming and return code segment DPL  return code segment selector RPL

                THEN #GP(selector); FI;
          IF CR4.FRED = 1 and CPL = 0 and L-bit is 0 in return code segment descriptor


                THEN #GP(selector); FI;
          IF return code segment descriptor is not present

                THEN #NP(selector); FI:
          IF return code segment selector RPL > CPL

                THEN GOTO IA-32E-MODE-RETURN-TO-OUTER-PRIVILEGE-LEVEL;
                ELSE GOTO IA-32E-MODE-RETURN-TO-SAME-PRIVILEGE-LEVEL;
          FI;
    FI;

IA-32E-MODE-RETURN-TO-SAME-PRIVILEGE-LEVEL:
IF the return instruction pointer is not within the return code segment limit

    THEN #GP(0); FI;
IF the return instruction pointer is not within canonical address space

    THEN #GP(0); FI;
IF OperandSize = 32

    THEN
          EIP := Pop();
          CS := Pop(); (* 32-bit pop, high-order 16 bits discarded *)

    ELSE
          IF OperandSize = 16
                THEN
                       EIP := Pop();
                       EIP := EIP AND 0000FFFFH;
                       CS := Pop(); (* 16-bit pop *)
               ELSE (* OperandSize = 64 *)
                       RIP := Pop();
                       CS := Pop(); (* 64-bit pop, high-order 48 bits discarded *)
          FI;

FI;
IF instruction has immediate operand

    THEN (* Release parameters from stack *)
         IF StackAddressSize = 32
                THEN
                       ESP := ESP + SRC;
                ELSE
                       IF StackAddressSize = 16
                             THEN
                                   SP := SP + SRC;
                          ELSE (* StackAddressSize = 64 *)
                                   RSP := RSP + SRC;
                       FI;
          FI;

FI;
IF ShadowStackEnabled(CPL)

    IF SSP AND 0x7 != 0 (* check if aligned to 8 bytes *)
          THEN #CP(FAR-RET/IRET); FI;

    tempSsCS = shadow_stack_load 8 bytes from SSP+16;
    tempSsLIP = shadow_stack_load 8 bytes from SSP+8;
    tempSSP = shadow_stack_load 8 bytes from SSP;
    SSP = SSP + 24;
    tempCS = CS; (* zero padded to 64 bit *)
    IF tempCS != tempSsCS (* 64 bit compare; CS zero padded to 64 bits *)

          THEN #CP(FAR-RET/IRET); FI;
    IF CSBASE + RIP != tempSsLIP (* 64 bit compare *)


          THEN #CP(FAR-RET/IRET); FI;
    IF tempSSP AND 0x3 != 0 (* check if aligned to 4 bytes *)

          THEN #CP(FAR-RET/IRET); FI;
    IF (CS.L = 0 AND tempSSP[63:32] != 0) OR

        (CS.L = 1 AND tempSSP is not canonical relative to the current paging mode)
          THEN #GP(0); FI;

    SSP := tempSSP
FI;

IA-32E-MODE-RETURN-TO-OUTER-PRIVILEGE-LEVEL:
IF top (16 + SRC) bytes of stack are not within stack limits (OperandSize = 32)
or top (8 + SRC) bytes of stack are not within stack limits (OperandSize = 16)

    THEN #SS(0); FI;
IF top (16 + SRC) bytes of stack are not in canonical address space (OperandSize =32)
or top (8 + SRC) bytes of stack are not in canonical address space (OperandSize = 16)
or top (32 + SRC) bytes of stack are not in canonical address space (OperandSize = 64)

    THEN #SS(0); FI;
Read return stack segment selector;
IF stack segment selector is NULL

    THEN
          IF new CS descriptor L-bit = 0
                THEN #GP(selector);
          IF stack segment selector RPL = 3
                THEN #GP(selector);

FI;
IF return stack segment descriptor is not within descriptor table limits

          THEN #GP(selector); FI;
IF return stack segment descriptor is in non-canonical address space

          THEN #GP(selector); FI;
Read segment descriptor pointed to by return segment selector;
IF stack segment selector RPL  RPL of the return code segment selector
or stack segment is not a writable data segment
or stack segment descriptor DPL  RPL of the return code segment selector

    THEN #GP(selector); FI;
IF stack segment not present

    THEN #SS(StackSegmentSelector); FI;
IF the return instruction pointer is not within the return code segment limit

    THEN #GP(0); FI:
IF the return instruction pointer is not within canonical address space

    THEN #GP(0); FI;
IF OperandSize = 32

    THEN
          EIP := Pop();
          CS := Pop(); (* 32-bit pop, high-order 16 bits discarded, segment descriptor loaded *)
          CS(RPL) := ReturnCodeSegmentSelector(RPL);
          IF instruction has immediate operand
                THEN (* Release parameters from called procedure's stack *)
                    IF StackAddressSize = 32
                             THEN
                                   ESP := ESP + SRC;
                             ELSE
                                   IF StackAddressSize = 16
                                         THEN
                                               SP := SP + SRC;


                                     ELSE (* StackAddressSize = 64 *)
                                               RSP := RSP + SRC;

                                   FI;
                       FI;
          FI;
          tempESP := Pop();
          tempSS := Pop(); (* 32-bit pop, high-order 16 bits discarded, segment descriptor loaded *)
    ELSE
          IF OperandSize = 16
                THEN
                       EIP := Pop();
                       EIP := EIP AND 0000FFFFH;
                       CS := Pop(); (* 16-bit pop; segment descriptor loaded *)
                       CS(RPL) := ReturnCodeSegmentSelector(RPL);
                       IF instruction has immediate operand

                             THEN (* Release parameters from called procedure's stack *)
                               IF StackAddressSize = 32
                                         THEN
                                               ESP := ESP + SRC;
                                         ELSE
                                               IF StackAddressSize = 16
                                                     THEN
                                                           SP := SP + SRC;
                                                ELSE (* StackAddressSize = 64 *)
                                                           RSP := RSP + SRC;
                                               FI;
                                   FI;

                       FI;
                       tempESP := Pop();
                       tempSS := Pop(); (* 16-bit pop; segment descriptor loaded *)
               ELSE (* OperandSize = 64 *)
                       RIP := Pop();
                       CS := Pop(); (* 64-bit pop; high-order 48 bits discarded; seg. descriptor loaded *)
                       CS(RPL) := ReturnCodeSegmentSelector(RPL);
                       IF instruction has immediate operand

                             THEN (* Release parameters from called procedure's stack *)
                                   RSP := RSP + SRC;

                       FI;
                       tempESP := Pop();
                       tempSS := Pop(); (* 64-bit pop; high-order 48 bits discarded; seg. desc. loaded *)
          FI;
FI;

IF ShadowStackEnabled(CPL)
    (* check if 8 byte aligned *)
    IF SSP AND 0x7 != 0
          THEN #CP(FAR-RET/IRET); FI;
    IF ReturnCodeSegmentSelector(RPL) !=3
          THEN
                tempSsCS = shadow_stack_load 8 bytes from SSP+16;
                tempSsLIP = shadow_stack_load 8 bytes from SSP+8;
                tempSSP = shadow_stack_load 8 bytes from SSP;
                SSP = SSP + 24;
                (* Do 64 bit compare to detect bits beyond 15 being set *)


          tempCS = CS; (* zero padded to 64 bit *)

          IF tempCS != tempSsCS

                 THEN #CP(FAR-RET/IRET); FI;

          (* Do 64 bit compare; pad CSBASE+RIP with 0 for 32 bit LIP *)

          IF CSBASE + RIP != tempSsLIP

                 THEN #CP(FAR-RET/IRET); FI;

          (* check if 4 byte aligned *)

          IF tempSSP AND 0x3 != 0

                 THEN #CP(FAR-RET/IRET); FI;

     FI;

FI;

tempOldCPL = CPL;

CPL := ReturnCodeSegmentSelector(RPL);

ESP := tempESP;

SS := tempSS;

tempOldSSP = SSP;

IF ShadowStackEnabled(CPL)

     IF CPL = 3

          THEN tempSSP := IA32_PL3_SSP; FI;

     IF (CS.L = 0 AND tempSSP[63:32] != 0) OR

          (CS.L = 1 AND tempSSP is not canonical relative to the current paging mode)

          THEN #GP(0); FI;

     SSP := tempSSP

FI;

(* Now past all faulting points; safe to free the token. The token free is done using the old SSP

* and using a supervisor override as old CPL was a supervisor privilege level *)

IF ShadowStackEnabled(tempOldCPL)

     expected_token_value = tempOldSSP | BUSY_BIT   (* busy bit - bit position 0 - must be set *)

     new_token_value = tempOldSSP                   (* clear the busy bit *)

     shadow_stack_lock_cmpxchg8b(tempOldSSP, new_token_value, expected_token_value)

FI;

FOR each of segment register (ES, FS, GS, and DS)
    DO
          IF segment register points to data or non-conforming code segment
          and CPL > segment descriptor DPL; (* DPL in hidden part of segment register *)
                THEN SegmentSelector := 0; (* SegmentSelector invalid *)
          FI;
    OD;

IF instruction has immediate operand
    THEN (* Release parameters from calling procedure's stack *)
         IF StackAddressSize = 32
                THEN
                      ESP := ESP + SRC;
                ELSE
                      IF StackAddressSize = 16
                            THEN
                                  SP := SP + SRC;
                          ELSE (* StackAddressSize = 64 *)
                                  RSP := RSP + SRC;
                      FI;
          FI;

FI;

受影响的旗帜

None.

说明

以 imm8 指定的计数值旋转 源操作数 的位数,而不影响算术旗帜。 结果写给目标操作数. 此指令不支持真实模式和 虚拟 8086 模式 。 操作数大小如果不是64位模式,总是32位. 在64位模式操作数大小 64中需要VEX.W1. VEX.W1在非64位模式中被忽略. 试图用不等于0的 VEX.L 执行此指令将导致 #UD.

行动

IF (OperandSize = 32)

    y := imm8 AND 1FH;
    DEST := (SRC >> y) | (SRC << (32-y));
ELSEIF (OperandSize = 64)
    y := imm8 AND 3FH;
    DEST := (SRC >> y) | (SRC << (64-y));
FI;

受影响的旗帜

None.

SIMD 浮点 例外

None.

其他例外

参见表2-29"十三类例外条件".

RORX - 旋转右逻辑而不影响旗帜

异常

保护模式
#GP(0)如果返回代码或堆栈 段选择子 是 NULL. 如果返回 指令指针 不在返回代码区段限制之内。 如果返回到32位或兼容模式以及以前的 SSP 从阴影堆栈(返回到 CPL <3) 或从 IA32 PL3 SSP(返回到 CPL 3) 返回到 4GB 以上 。
#GP(selector)如果RPL返回代码段选择子比较少CPL如果返回代码或堆栈段选择子索引不在其描述式表格限制之内。如果返回代码段描述式没有表示代码段。如果返回代码段不符合要求,则段选择子's DPL与RPL代码段的段选择子如果返回代码段符合,则段选择子's DPL大于RPL代码段的段选择子如果堆栈段不是可写数据段。如果堆栈段选择子 RPL与RPL返回代码段选择子。如果堆栈段描述符DPL与RPL返回代码段选择子.
#SS(0)如果堆栈的顶端字节不在堆栈限制之内。如果返回堆栈段不存在。
#NP(selector)如果返回代码段不存在。 #PF(fault-code) 如果发生 页面错误 。
#AC(0)如果在 CPL 3 时出现不匹配的内存访问, 并启用对齐检查 。 #CP(Far-RET/IRET) 如果以前的 SSP 从阴影堆栈( 当返回到 CPL < 3) 或 IA32 PL3 SSP( 返回到 CPL 3) 时, 则不匹配 4 字节 。 如果返回 指令指针 从堆栈和阴影堆栈不匹配 。
实地址模式
#GP如果返回 指令指针 不在返回代码段限制内
#SS如果堆栈的顶端字节不在堆栈限制之内.
虚拟 8086 模式
#GP(0)如果返回 指令指针 不在返回代码段限制内
#SS(0)如果堆栈的顶端字节不在堆栈限制之内. #PF(fault-code) 如果发生 页面错误 ,则会发生.
#AC(0)如果启用对齐检查时发生了不匹配的内存访问.
兼容模式
与64位模式例外相同.
64 位模式
#GP(0)如果回来指令指针如果返回, 则不带定义 。指令指针不在返回代码段限制内。如果堆栈段选择子为NULL返回兼容模式。如果堆栈段选择子为NULL继续CPL364位模式。如果是NULL堆栈段选择子 RPL不等于CPL回到无 -CPL364 位模式。 如果返回代码段选择子为NULL。如果返回到32位或兼容模式以及上一个SSP从阴影堆栈( 当返回时)CPL <3) 或从 IA32 PL3 SP(返回CPL3)超过4GB.
#GP(selector)如果一个代码段的拟议区段描述符没有表示它是一个代码段。如果提议的新区段描述符同时有D位和L位的设定。如果DPL对于不符合规定的编码段,不等于RPL代码段选择子如果CPL大于RPL代码段选择子如果FRED已启用过渡CPL低于RPL代码段选择子如果FRED已启用过渡CPL=0和远RET将输入兼容模式。如果DPL表示符合的代码段大于返回代码段选择子 RPL如果段选择子索引超出了其描述式表格限制。如果段描述式内存地址是非日历式的。如果堆栈段不是可写数据段。如果堆栈段描述式DPL与RPL返回代码段选择子如果堆栈段选择子 RPL与RPL返回代码段选择子.
#SS(0)如果试图从堆栈中弹出一个值违反了 SS 限制。 如果试图从堆栈中弹出一个值会导致引用一个非冠词地址 。
#NP(selector)如果返回代码或堆栈段不存在。 #PF(fault-code) 如果发生 页面错误 。
#AC(0)如果启用了对齐检查,并且在当前特权级别为3时会给出不对齐的内存引用.#CP(Far-RET/IRET)如果上一个SSP从阴影堆栈( 当返回时)CPL <3) 或从 IA32 PL3 SP(返回CPL3 不是一个 4 字节对齐。如果返回指令指针从堆栈和阴影堆栈不匹配。RORX-- 右转逻辑而不影响旗帜操作码/ 执行部分第64/32段-CPUID描述指令位元模式旗VEX.LZ.F2.0F3A.W0F0/r ib (单位:千美元)RMI V/V BMI2旋转 32 位r/m32对imm8时间和装入r32无RORX r32, r/m32, imm8影响算术旗帜。VEX.LZ.F2.0F3A.W1F0/r ib (单位:千美元)RMI V/N.E. BMI2旋转 64 位r/m64对imm8时间和装入r64无RORX r64, r/m64, imm8影响算术旗帜。

来源