Opcode |
Instruction |
Description |
---|---|---|
C3 |
RET |
Near return to calling procedure |
CB |
RET |
Far return to calling procedure |
C2 iw |
RET imm16 |
Near return to calling procedure and pop imm16 bytes from stack |
CA iw |
RET imm16 |
Far return to calling procedure and pop imm16 bytes from stack |
Transfers program control to a return address located on the top of the stack. The address is usually placed on the stack by a CALL instruction, and the return is made to the instruction that follows the CALL instruction.
The optional source operand specifies the number of stack bytes to be released after the return address is popped; the default is none. This operand can be used to release parameters from the stack that were passed to the called procedure and are no longer needed. It must be used when the CALL instruction used to switch to a new procedure uses a call gate with a non-zero word count to access the new procedure. Here, the source operand for the RET instruction must specify the same number of bytes as is specified in the word count field of the call gate.
The RET instruction can be used to execute three different types of returns:
Near return--A return to a calling procedure within the current code segment (the segment currently pointed to by the CS register), sometimes referred to as an intrasegment return.
Far return--A return to a calling procedure located in a different segment than the current code segment, sometimes referred to as an intersegment return.
Inter-privilege-level far return--A far return to a different privilege level than that of the currently executing program or procedure.
The inter-privilege-level return type can only be executed in protected mode. See the section titled "Calling Procedures Using Call and RET" in Chapter 6 of the IA-32 Intel(R) Architecture Software Developer's Manual, Volume 1, for detailed information on near, far, and inter-privilege-level returns.
When executing a near return, the processor pops the return instruction pointer (offset) from the top of the stack into the EIP register and begins program execution at the new instruction pointer. The CS register is unchanged.
When executing a far return, the processor pops the return instruction pointer from the top of the stack into the EIP register, then pops the segment selector from the top of the stack into the CS register. The processor then begins program execution in the new code segment at the new instruction pointer.
The mechanics of an inter-privilege-level far return are similar to an intersegment return, except that the processor examines the privilege levels and access rights of the code and stack segments being returned to determine if the control transfer is allowed to be made. The DS, ES, FS, and GS segment registers are cleared by the RET instruction during an inter-privilege-level return if they refer to segments that are not allowed to be accessed at the new privilege level. Since a stack switch also occurs on an inter-privilege level return, the ESP and SS registers are loaded from the stack.
If parameters are passed to the called procedure during an inter-privilege level call, the optional source operand must be used with the RET instruction to release the parameters on the return. Here, the parameters are released both from the called procedure's stack and the calling procedure's stack (that is, the stack being returned to).
(* Near return *)
IF instruction near
return
THEN;
IF OperandSize 32
THEN
IF top 12 bytes of stack not within stack limits THEN #SS(0); FI;
EIP Pop();
ELSE (* OperandSize
16 *)
IF top 6 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;
FI;
IF instruction has immediate operand
THEN IF StackAddressSize=32
THEN
ESP ESP + SRC; (*
release parameters from stack *)
ELSE (* StackAddressSize=16 *)
SP SP + SRC; (*
release parameters from stack *)
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 12 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 6 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
SP SP + (SRC AND
FFFFH); (* release parameters from stack *)
FI;
FI;
(* Protected mode, not virtual-8086 mode *)
IF (PE 1 AND VM
0) AND instruction
far RET
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 not present THEN #NP(selector); FI:
IF return code segment selector RPL > CPL
THEN GOTO RETURN-OUTER-PRIVILEGE-LEVEL;
ELSE GOTO RETURN-TO-SAME-PRIVILEGE-LEVEL
FI;
END;FI;
RETURN-SAME-PRIVILEGE-LEVEL:
IF the return instruction pointer is not within then return code segment
limit
THEN #GP(0);
FI;
IF OperandSize=32
THEN
EIP Pop();
CS Pop(); (* 32-bit
pop, high-order 16 bits discarded *)
ESP ESP + SRC; (*
release parameters from stack *)
ELSE (* OperandSize=16 *)
EIP Pop();
EIP EIP AND 0000FFFFH;
CS Pop(); (* 16-bit
pop *)
ESP ESP + SRC; (*
release parameters from stack *)
FI;
RETURN-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;
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:
CPL ReturnCodeSegmentSelector(RPL);
IF OperandSize=32
THEN
EIP Pop();
CS Pop(); (* 32-bit
pop, high-order 16 bits discarded *)
(* segment descriptor information also loaded *)
CS(RPL) CPL;
ESP ESP + SRC; (*
release parameters from called procedure's stack *)
tempESP Pop();
tempSS Pop(); (*
32-bit pop, high-order 16 bits discarded *)
(* segment descriptor information also loaded *)
ESP tempESP;
SS tempSS;
ELSE (* OperandSize=16 *)
EIP Pop();
EIP EIP AND 0000FFFFH;
CS Pop(); (* 16-bit
pop; segment descriptor information also loaded *)
CS(RPL) CPL;
ESP ESP + SRC; (*
release parameters from called procedure's stack *)
tempESP Pop();
tempSS Pop(); (*
16-bit pop; segment descriptor information also loaded *)
(* segment descriptor information also loaded *)
ESP tempESP;
SS tempSS;
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 (* segment register invalid *)
SegmentSelector 0;
(* null segment selector *)
FI;
OD;
For each of ES, FS, GS, and DS
DO
IF segment selector index is not within descriptor table limits
OR segment descriptor indicates the segment is not a data or
readable code segment
OR if the segment is a data or non-conforming code segment and the segment
descriptor's DPL < CPL or RPL of code segment's segment selector
THEN
segment selector register null selector;
OD;
ESP ESP + SRC; (*
release parameters from calling procedure's stack *)
None.
#GP(0) - If the return code or stack segment selector null. If the return instruction pointer is not within the return code segment limit
#GP(selector) - If the RPL of the return code segment selector is less then the CPL. If the return code or stack segment selector index is not within its descriptor table limits. If the return code segment descriptor does not indicate a code segment. If the return code segment is non-conforming and the segment selector's DPL is not equal to the RPL of the code segment's segment selector If the return code segment is conforming and the segment selector's DPL greater than the RPL of the code segment's segment selector If the stack segment is not a writable data segment. If the stack segment selector RPL is not equal to the RPL of the return code segment selector. If the stack segment descriptor DPL is not equal to the RPL of the return code segment selector.
#SS(0) - If the top bytes of stack are not within stack limits. If the return stack segment is not present.
#NP(selector) - If the return code segment is not present.
#PF(fault-code) - If a page fault occurs.
#AC(0) - If an unaligned memory access occurs when the CPL is 3 and alignment checking is enabled.
#GP - If the return instruction pointer is not within the return code segment limit
#SS - If the top bytes of stack are not within stack limits.
#GP(0) - If the return instruction pointer is not within the return code segment limit.
#SS(0) - If the top bytes of stack are not within stack limits.
#PF(fault-code) - If a page fault occurs.
#AC(0) - If an unaligned memory access occurs when alignment checking is enabled.
For details, see Volume 2A and Volume 2B of the Intel(R) 64 and IA-32 Intel Architecture Software Developer's Manual. For the latest updates on the instruction set information, go to the web site.