Opcode Instruction Clocks Description F6 /7 IDIV r/m8 19 Signed divide AX by r/m byte (AL=Quo, AH=Rem) F7 /7 IDIV AX,r/m16 27 Signed divide DX:AX by EA word (AX=Quo, DX=Rem) F7 /7 IDIV EAX,r/m32 43 Signed divide EDX:EAX by DWORD byte (EAX=Quo, EDX=Rem)
Operation
temp <- dividend / divisor; IF temp does not fit in quotient THEN Interrupt 0; ELSE quotient <- temp; remainder <- dividend MOD (r/m); FI;
--------------------------------------------------------------------------- Notes: Divisions are signed. The divisor is given by the r/m operand. The dividend, quotient, and remainder use implicit registers. Refer to the table under "Description." ---------------------------------------------------------------------------Description
IDIV performs a signed division. The dividend, quotient, and remainder are implicitly allocated to fixed registers. Only the divisor is given as an explicit r/m operand. The type of the divisor determines which registers to use as follows:
Size Divisor Quotient Remainder Dividend byte r/m8 AL AH AX word r/m16 AX DX DX:AX dword r/m32 EAX EDX EDX:EAXIf the resulting quotient is too large to fit in the destination, or if the division is 0, an Interrupt 0 is generated. Nonintegral quotients are truncated toward 0. The remainder has the same sign as the dividend and the absolute value of the remainder is always less than the absolute value of the divisor.
Flags Affected
OF, SF, ZF, AR, PF, CF are undefined.
Protected Mode Exceptions
Interrupt 0 if the quotient is too large to fit in the designated register (AL or AX), or if the divisor is 0; #GP (0) for an illegal memory operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page fault
Real Address Mode Exceptions
Interrupt 0 if the quotient is too large to fit in the designated register (AL or AX), or if the divisor is 0; Interrupt 13 if any part of the operand would lie outside of the effective address space from 0 to 0FFFFH
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
Opcode Instruction Clocks DescriptionF6 /5 IMUL r/m8 9-14/12-17 AX<- AL * r/m byte F7 /5 IMUL r/m16 9-22/12-25 DX:AX <- AX * r/m word F7 /5 IMUL r/m32 9-38/12-41 EDX:EAX <- EAX * r/m dword 0F AF /r IMUL r16,r/m16 9-22/12-25 word register <- word
register * r/m word 0F AF /r IMUL r32,r/m32 9-38/12-41 dword register <- dword register * r/m dword 6B /r ib IMUL r16,r/m16,imm8 9-14/12-17 word register <- r/m16 * sign-extended immediate byte 6B /r ib IMUL r32,r/m32,imm8 9-14/12-17 dword register <- r/m32 * sign-extended immediate byte 6B /r ib IMUL r16,imm8 9-14/12-17 word register <- word register * sign-extended immediate byte 6B /r ib IMUL r32,imm8 9-14/12-17 dword register <- dword register * sign-extended immediate byte 69 /r iw IMUL r16,r/m16,imm16 9-22/12-25 word register <- r/m16 * immediate word 69 /r id IMUL r32,r/m32,imm32 9-38/12-41 dword register <- r/m32 * immediate dword 69 /r iw IMUL r16,imm16 9-22/12-25 word register <- r/m16 * immediate word 69 /r id IMUL r32,imm32 9-38/12-41 dword register <- r/m32 * immediate dword
--------------------------------------------------------------------------- NOTES: The 80386 uses an early-out multiply algorithm. The actual number of clocks depends on the position of the most significant bit in the optimizing multiplier, shown underlined above. The optimization occurs for positive and negative values. Because of the early-out algorithm, clock counts given are minimum to maximum. To calculate the actual clocks, use the following formula: --------------------------------------------------------------------------- Actual clock = if m <> 0 then max(ceiling(log{2} |m|), 3) + 6 clocks Actual clock = if m = 0 then 9 clocks (where m is the multiplier)Add three clocks if the multiplier is a memory operand.
Operation
result <- multiplicand * multiplier;
Description
IMUL performs signed multiplication. Some forms of the instruction use implicit register operands. The operand combinations for all forms of the instruction are shown in the "Description" column above.
IMUL clears the overflow and carry flags under the following conditions:
Instruction Form Condition for Clearing CF and OF r/m8 AL = sign-extend of AL to 16 bits r/m16 AX = sign-extend of AX to 32 bits r/m32 EDX:EAX = sign-extend of EAX to 32 bits r16,r/m16 Result exactly fits within r16 r/32,r/m32 Result exactly fits within r32 r16,r/m16,imm16 Result exactly fits within r16 r32,r/m32,imm32 Result exactly fits within r32Flags Affected
OF and CF as described above; SF, ZF, AF, and PF are undefined
Protected Mode Exceptions
#GP(0) for an illegal memory operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page fault
Real Address Mode Exceptions
Interrupt 13 if any part of the operand would lie outside of the effective address space from 0 to 0FFFFH
Virtual 8086 Mode Exceptions
Same exeptions as in Real Address Mode; #PF(fault-code) for a page fault
Notes
When using the accumulator forms (IMUL r/m8, IMUL r/m16, or IMUL r/m32), the result of the multiplication is available even if the overflow flag is set because the result is two times the size of the multiplicand and multiplier. This is large enough to handle any possible result.
Opcode Instruction Clocks Description E4 ib IN AL,imm8 12,pm=6*/26** Input byte from immediate port into AL E5 ib IN AX,imm8 12,pm=6*/26** Input word from immediate port into AX E5 ib IN EAX,imm8 12,pm=6*/26** Input dword from immediate port into EAX EC IN AL,DX 13,pm=7*/27** Input byte from port DX into AL ED IN AX,DX 13,pm=7*/27** Input word from port DX into AX ED IN EAX,DX 13,pm=7*/27** Input dword from port DX into EAX
--------------------------------------------------------------------------- NOTES: *If CPL . IOPL **If CPL > IOPL or if in virtual 8086 mode ---------------------------------------------------------------------------Operation
IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *)
IF NOT I-O-Permission (SRC, width(SRC)) THEN #GP(0); FI; FI; DEST <- [SRC]; (* Reads from I/O address space *)
Description
IN transfers a data byte or data word from the port numbered by the second operand into the register (AL, AX, or EAX) specified by the first operand. Access any port from 0 to 65535 by placing the port number in the DX register and using an IN instruction with DX as the second parameter. These I/O instructions can be shortened by using an 8-bit port I/O in the instruction. The upper eight bits of the port address will be 0 when 8-bit port I/O is used.
Flags Affected
None
Protected Mode Exceptions
#GP(0) if the current privilege level is larger (has less privilege) than IOPL and any of the corresponding I/O permission bits in TSS equals 1
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
#GP(0) fault if any of the corresponding I/O permission bits in TSS equals 1
Opcode Instruction Clocks Description FE /0 INC r/m8 Increment r/m byte by 1 FF /0 INC r/m16 Increment r/m word by 1 FF /6 INC r/m32 Increment r/m dword by 1 40 + rw INC r16 Increment word register by 1 40 + rd INC r32 Increment dword register by 1
Operation
DEST <- DEST + 1;
Description
INC adds 1 to the operand. It does not change the carry flag. To affect the carry flag, use the ADD instruction with a second operand of 1.
Flags Affected
OF, SF, ZF, AF, and PF as described in Appendix C
Protected Mode Exceptions
#GP(0) if the operand is in a nonwritable segment; #GP(0) for an illegal memory operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page fault
Real Address Mode Exceptions
Interrupt 13 if any part of the operand would lie outside of the effective address space from 0 to 0FFFFH
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
Opcode Instruction Clocks Description 6C INS r/m8,DX 15,pm=9*/29** Input byte from port DX into ES:(E)DI 6D INS r/m16,DX 15,pm=9*/29** Input word from port DX into ES:(E)DI 6D INS r/m32,DX 15,pm=9*/29** Input dword from port DX into ES:(E)DI 6C INSB 15,pm=9*/29** Input byte from port DX into ES:(E)DI 6D INSW 15,pm=9*/29** Input word from port DX into ES:(E)DI 6D INSD 15,pm=9*/29** Input dword from port DX into ES:(E)DI
--------------------------------------------------------------------------- NOTES: *If CPL . IOPL **If CPL > IOPL or if in virtual 8086 mode ---------------------------------------------------------------------------Operation
IF AddressSize = 16 THEN use DI for dest-index; ELSE (* AddressSize = 32 *)
use EDI for dest-index; FI; IF (PE = 1) AND ((VM = 1) OR (CPL > IOPL)) THEN (* Virtual 8086 mode, or protected mode with CPL > IOPL *) IF NOT I-O-Permission (SRC, width(SRC)) THEN #GP(0); FI; FI; IF byte type of instruction THEN ES:[dest-index] <- [DX]; (* Reads byte at DX from I/O address space *) IF DF = 0 THEN IncDec <- 1 ELSE IncDec <- -1; FI; FI; IF OperandSize = 16 THEN ES:[dest-index] <- [DX]; (* Reads word at DX from I/O address space *) IF DF = 0 THEN IncDec <- 2 ELSE IncDec <- -2; FI; FI; IF OperandSize = 32 THEN ES:[dest-index] <- [DX]; (* Reads dword at DX from I/O address space *) IF DF = 0 THEN IncDec <- 4 ELSE IncDec <- -4; FI; FI; dest-index <- dest-index + IncDec;
Description
INS transfers data from the input port numbered by the DX register to the memory byte or word at ES:dest-index. The memory operand must be addressable from ES; no segment override is possible. The destination register is DI if the address-size attribute of the instruction is 16 bits, or EDI if the address-size attribute is 32 bits.
INS does not allow the specification of the port number as an immediate value. The port must be addressed through the DX register value. Load the correct value into DX before executing the INS instruction.
The destination address is determined by the contents of the destination index register. Load the correct index into the destination index register before executing INS.
After the transfer is made, DI or EDI advances automatically. If the direction flag is 0 (CLD was executed), DI or EDI increments; if the direction flag is 1 (STD was executed), DI or EDI decrements. DI increments or decrements by 1 if a byte is input, by 2 if a word is input, or by 4 if a doubleword is input.
INSB, INSW and INSD are synonyms of the byte, word, and doubleword INS instructions. INS can be preceded by the REP prefix for block input of CX bytes or words. Refer to the REP instruction for details of this operation.
Flags Affected
None
Protected Mode Exceptions
#GP(0) if CPL is numerically greater than IOPL and any of the corresponding I/O permission bits in TSS equals 1; #GP(0) if the destination is in a nonwritable segment; #GP(0) for an illegal memory operand effective address in the CS, DS, ES, FS, or GS segments; #SS(0) for an illegal address in the SS segment; #PF(fault-code) for a page fault
Real Address Mode Exceptions
Interrupt 13 if any part of the operand would lie outside of the effective address space from 0 to 0FFFFH
Virtual 8086 Mode Exceptions
#GP(0) fault if any of the corresponding I/O permission bits in TSS equals 1; #PF(fault-code) for a page fault
Opcode Instruction Clocks Description CC INT 3 33 Interrupt 3--trap to debugger CC INT 3 pm=59 Interrupt 3--Protected Mode, same privilege CC INT 3 pm=99 Interrupt 3--Protected Mode, more privilege CC INT 3 pm=119 Interrupt 3--from V86 mode to PL 0 CC INT 3 ts Interrupt 3--Protected Mode, via task gate CD ib INT imm8 37 Interrupt numbered by immediate byte CD ib INT imm8 pm=59 Interrupt--Protected Mode, same privilege CD ib INT imm8 pm=99 Interrupt--Protected Mode, more privilege CD ib INT imm8 pm=119 Interrupt--from V86 mode to PL 0 CD ib INT imm8 ts Interrupt--Protected Mode, via task gate CE INTO Fail:3,pm=3; Pass:35 Interrupt 4--if overflow flag is 1 CE INTO pm=59 Interrupt 4--Protected Mode, same privilege CE INTO pm=99 Interrupt 4--Protected Mode, more privilege CE INTO pm=119 Interrupt 4--from V86 mode to PL 0 CE INTO ts Interrupt 4--Protected Mode, via task gate
--------------------------------------------------------------------------- NOTE: Approximate values of ts are given by the following table: New Task Old Task 386 TSS 386 TSS 286 TSS VM = 0 VM = 1386
TSS VM=0 309 226 282386
TSS VM=1 314 231 287286
TSS 307 224 280 ---------------------------------------------------------------------------Operation
--------------------------------------------------------------------------- NOTE: The following operational description applies not only to the above instructions but also to external interrupts and exceptions. ---------------------------------------------------------------------------IF PE = 0 THEN GOTO REAL-ADDRESS-MODE; ELSE GOTO PROTECTED-MODE; FI;
REAL-ADDRESS-MODE:
Push (FLAGS); IF <- 0; (* Clear interrupt flag *) TF <- 0; (* Clear trap flag *) Push(CS); Push(IP); (* No error codes are pushed *) CS <- IDT[Interrupt number * 4].selector; IP <- IDT[Interrupt number * 4].offset;PROTECTED-MODE:
Interrupt vector must be within IDT table limits, else #GP(vector number * 8+2+EXT); Descriptor AR byte must indicate interrupt gate, trap gate, or task gate, else #GP(vector number * 8+2+EXT); IF software interrupt (* i.e. caused by INT n, INT 3, or INTO *) THEN IF gate descriptor DPL < CPL THEN #GP(vector number * 8+2+EXT); FI; FI; Gate must be present, else #NP(vector number * 8+2+EXT); IF trap gate OR interrupt gate THEN GOTO TRAP-GATE-OR-INTERRUPT-GATE; ELSE GOTO TASK-GATE; FI;TRAP-GATE-OR-INTERRUPT-GATE:
Examine CS selector and descriptor given in the gate descriptor; Selector must be non-null, else #GP (EXT); Selector must be within its descriptor table limits ELSE #GP(selector+EXT); Descriptor AR byte must indicate code segment ELSE #GP(selector + EXT); Segment must be present, else #NP(selector+EXT); IF code segment is non-conforming AND DPL < CPL THEN GOTO INTERRUPT-TO-INNER-PRIVILEGE; ELSE IF code segment is conforming OR code segment DPL = CPL THEN GOTO INTERRUPT-TO-SAME-PRIVILEGE-LEVEL; ELSE #GP(CS selector + EXT); FI; FI;INTERRUPT-TO-INNER-PRIVILEGE:
Check selector and descriptor for new stack in current TSS; Selector must be non-null, else #GP(EXT); Selector index must be within its descriptor table limits ELSE #TS(SS selector+EXT); Selector's RPL must equal DPL of code segment, else #TS(SS selector+EXT); Stack segment DPL must equal DPL of code segment, else #TS(SS selector+EXT); Descriptor must indicate writable data segment, else #TS(SS selector+EXT); Segment must be present, else #SS(SS selector+EXT); IF 32-bit gate THEN New stack must have room for 20 bytes else #SS(0) ELSE New stack must have room for 10 bytes else #SS(0) FI; Instruction pointer must be within CS segment boundaries else #GP(0); Load new SS and eSP value from TSS; IF 32-bit gate THEN CS:EIP <- selector:offset from gate; ELSE CS:IP <- selector:offset from gate; FI; Load CS descriptor into invisible portion of CS register; Load SS descriptor into invisible portion of SS register; IF 32-bit gate THEN Push (long pointer to old stack) (* 3 words padded to 4 *); Push (EFLAGS); Push (long pointer to return location) (* 3 words padded to 4*); ELSE Push (long pointer to old stack) (* 2 words *); Push (FLAGS); Push (long pointer to return location) (* 2 words *); FI; Set CPL to new code segment DPL; Set RPL of CS to CPL; IF interrupt gate THEN IF <- 0 (* interrupt flag to 0 (disabled) *); FI; TF <- 0; NT <- 0;INTERRUPT-FROM-V86-MODE: TempEFlags <- EFLAGS; VM <- 0; TF <- 0; IF service through Interrupt Gate THEN IF <- 0; TempSS <- SS; TempESP <- ESP; SS <- TSS.SS0; (* Change to level 0 stack segment *) ESP <- TSS.ESP0; (* Change to level 0 stack pointer *)
Push(GS); (* padded to two words *) Push(FS); (* padded to two words *) Push(DS); (* padded to two words *) Push(ES); (* padded to two words *) GS <- 0; FS <- 0; DS <- 0; ES <- 0; Push(TempSS); (* padded to two words *) Push(TempESP); Push(TempEFlags); Push(CS); (* padded to two words *) Push(EIP); CS:EIP <- selector:offset from interrupt gate; (* Starts execution of new routine in 80386 Protected Mode *)INTERRUPT-TO-SAME-PRIVILEGE-LEVEL:
IF 32-bit gate THEN Current stack limits must allow pushing 10 bytes, else #SS(0); ELSE Current stack limits must allow pushing 6 bytes, else #SS(0); FI; IF interrupt was caused by exception with error code THEN Stack limits must allow push of two more bytes; ELSE #SS(0); FI; Instruction pointer must be in CS limit, else #GP(0); IF 32-bit gate THEN Push (EFLAGS); Push (long pointer to return location); (* 3 words padded to 4 *) CS:EIP <- selector:offset from gate; ELSE (* 16-bit gate *) Push (FLAGS); Push (long pointer to return location); (* 2 words *) CS:IP <- selector:offset from gate; FI; Load CS descriptor into invisible portion of CS register; Set the RPL field of CS to CPL; Push (error code); (* if any *) IF interrupt gate THEN IF <- 0; FI; TF <- 0; NT <- 0;TASK-GATE:
Examine selector to TSS, given in task gate descriptor; Must specify global in the local/global bit, else #TS(TSS selector); Index must be within GDT limits, else #TS(TSS selector); AR byte must specify available TSS (bottom bits 00001), else #TS(TSS selector; TSS must be present, else #NP(TSS selector); SWITCH-TASKS with nesting to TSS; IF interrupt was caused by fault with error code THEN Stack limits must allow push of two more bytes, else #SS(0); Push error code onto stack; FI; Instruction pointer must be in CS limit, else #GP(0);Description
The INT instruction generates via software a call to an interrupt handler. The immediate operand, from 0 to 255, gives the index number into the Interrupt Descriptor Table (IDT) of the interrupt routine to be called. In Protected Mode, the IDT consists of an array of eight-byte descriptors; the descriptor for the interrupt invoked must indicate an interrupt, trap, or task gate. In Real Address Mode, the IDT is an array of four byte-long pointers. In Protected and Real Address Modes, the base linear address of the IDT is defined by the contents of the IDTR.
The INTO conditional software instruction is identical to the INT interrupt instruction except that the interrupt number is implicitly 4, and the interrupt is made only if the 80386 overflow flag is set.
The first 32 interrupts are reserved by Intel for system use. Some of these interrupts are use for internally generated exceptions.
INT n generally behaves like a far call except that the flags register is pushed onto the stack before the return address. Interrupt procedures return via the IRET instruction, which pops the flags and return address from the stack.
In Real Address Mode, INT n pushes the flags, CS, and the return IP onto the stack, in that order, then jumps to the long pointer indexed by the interrupt number.
Flags Affected
None
Protected Mode Exceptions
#GP, #NP, #SS, and #TS as indicated under "Operation" above
Real Address Mode Exceptions
None; if the SP or ESP = 1, 3, or 5 before executing INT or INTO, the 80386 will shut down due to insufficient stack space
Virtual 8086 Mode Exceptions
#GP(0) fault if IOPL is less than 3, for INT only, to permit emulation; Interrupt 3 (0CCH) generates Interrupt 3; INTO generates Interrupt 4 if the overflow flag equals 1
Opcode Instruction Clocks Description CF IRET 22,pm=38 Interrupt return (far return and pop flags) CF IRET pm=82 Interrupt return to lesser privilege CF IRET ts Interrupt return, different task (NT = 1) CF IRETD 22,pm=38 Interrupt return (far return and pop flags) CF IRETD pm=82 Interrupt return to lesser privilege CF IRETD pm=60 Interrupt return to V86 mode CF IRETD ts Interrupt return, different task (NT = 1)
--------------------------------------------------------------------------- NOTE: Values of ts are given by the following table: New Task Old Task 386 TSS 386 TSS 286 TSS VM = 0 VM = 1386
TSS VM=0 275 224 271286
TSS 265 214 232 ---------------------------------------------------------------------------Operation
IF PE = 0 THEN (* Real-address mode *)
IF OperandSize = 32 (* Instruction = IRETD *) THEN EIP <- Pop(); ELSE (* Instruction = IRET *) IP <- Pop(); FI; CS <- Pop(); IF OperandSize = 32 (* Instruction = IRETD *) THEN EFLAGS <- Pop(); ELSE (* Instruction = IRET *) FLAGS <- Pop(); FI; ELSE (* Protected mode *) IF VM = 1 THEN #GP(0); ELSE IF NT = 1 THEN GOTO TASK-RETURN; ELSE IF VM = 1 in flags image on stack THEN GO TO STACK-RETURN-TO-V86; ELSE GOTO STACK-RETURN; FI; FI; FI; FI;STACK-RETURN-TO-V86: (* Interrupted procedure was in V86 mode *) IF return CS selector RPL < > 3 THEN #GP(Return selector); FI; IF top 36 bytes of stack not within limits THEN #SS(0); FI; Examine return CS selector and associated descriptor: IF selector is null, THEN #GP(0); FI; IF selector index not within its descriptor table limits; THEN #GP(Return selector); FI; IF AR byte does not indicate code segment THEN #GP(Return selector); FI; IF code segment DPL not = 3; THEN #GP(Return selector); FI; IF code segment not present THEN #NP(Return selector); FI; Examine return SS selector and associated descriptor: IF selector is null THEN #GP(0); FI; IF selector index not within its descriptor table limits THEN #GP(SS selector); FI; IF selector RPL not = RPL of return CS selector THEN #GP(SS selector); FI; IF AR byte does not indicate a writable data segment THEN #GP(SS selector); FI; IF stack segment DPL not = RPL of return CS selector THEN #GP(SS selector); FI; IF SS not present THEN #NP(SS selector); FI; IF instruction pointer not within code segment limit THEN #GP(0); FI; EFLAGS <- SS:[eSP + 8]; (* Sets VM in interrupted routine *) EIP <- Pop(); CS <- Pop(); (* CS behaves as in 8086, due to VM = 1 *) throwaway <- Pop(); (* pop away EFLAGS already read *) ES <- Pop(); (* pop 2 words; throw away high-order word *) DS <- Pop(); (* pop 2 words; throw away high-order word *) FS <- Pop(); (* pop 2 words; throw away high-order word *) GS <- Pop(); (* pop 2 words; throw away high-order word *) IF CS.RPL > CPL THEN TempESP <- Pop(); TempSS <- Pop(); SS:ESP <- TempSS:TempESP; FI; (* Resume execution in Virtual 8086 mode *)TASK-RETURN:
Examine Back Link Selector in TSS addressed by the current task register: Must specify global in the local/global bit, else #TS(new TSS selector); Index must be within GDT limits, else #TS(new TSS selector); AR byte must specify TSS, else #TS(new TSS selector); New TSS must be busy, else #TS(new TSS selector); TSS must be present, else #NP(new TSS selector); SWITCH-TASKS without nesting to TSS specified by back link selector; Mark the task just abandoned as NOT BUSY; Instruction pointer must be within code segment limit ELSE #GP(0);STACK-RETURN:
IF OperandSize=32 THEN Third word on stack must be within stack limits, else #SS(0); ELSE Second word on stack must be within stack limits, else #SS(0); FI; Return CS selector RPL must be . CPL, else #GP(Return selector); IF return selector RPL = CPL THEN GOTO RETURN-SAME-LEVEL; ELSE GOTO RETURN-OUTER-LEVEL; FI;RETURN-SAME-LEVEL:
IF OperandSize=32 THEN Top 12 bytes on stack must be within limits, else #SS(0); Return CS selector (at eSP+4) must be non-null, else #GP(0); ELSE Top 6 bytes on stack must be within limits, else #SS(0); Return CS selector (at eSP+2) must be non-null, else #GP(0); FI; Selector index must be within its descriptor table limits, else #GP (Return selector); AR byte must indicate code segment, else #GP(Return selector); IF non-conforming THEN code segment DPL must = CPL; ELSE #GP(Return selector); FI; IF conforming THEN code segment DPL must be . CPL, else #GP(Return selector); Segment must be present, else #NP(Return selector); Instruction pointer must be within code segment boundaries, else #GP(0); FI; IF OperandSize=32 THEN Load CS:EIP from stack; Load CS-register with new code segment descriptor; Load EFLAGS with third doubleword from stack; Increment eSP by 12; ELSE Load CS-register with new code segment descriptor; Load FLAGS with third word on stack; Increment eSP by 6; FI;RETURN-OUTER-LEVEL:
IF OperandSize=32 THEN Top 20 bytes on stack must be within limits, else #SS(0); ELSE Top 10 bytes on stack must be within limits, else #SS(0); FI; Examine return CS selector and associated descriptor: Selector must be non-null, else #GP(0); Selector index must be within its descriptor table limits; ELSE #GP(Return selector); AR byte must indicate code segment, else #GP(Return selector); IF non-conforming THEN code segment DPL must = CS selector RPL; ELSE #GP(Return selector); FI; IF conforming THEN code segment DPL must be > CPL; ELSE #GP(Return selector); FI; Segment must be present, else #NP(Return selector); Examine return SS selector and associated descriptor: Selector must be non-null, else #GP(0); Selector index must be within its descriptor table limits ELSE #GP(SS selector); Selector RPL must equal the RPL of the return CS selector ELSE #GP(SS selector); AR byte must indicate a writable data segment, else #GP(SS selector); Stack segment DPL must equal the RPL of the return CS selector ELSE #GP(SS selector); SS must be present, else #NP(SS selector); Instruction pointer must be within code segment limit ELSE #GP(0); IF OperandSize=32 THEN Load CS:EIP from stack; Load EFLAGS with values at (eSP+8); ELSE Load CS:IP from stack; Load FLAGS with values at (eSP+4); FI; Load SS:eSP from stack; Set CPL to the RPL of the return CS selector; Load the CS register with the CS descriptor; Load the SS register with the SS descriptor; FOR each of ES, FS, GS, and DS DO; IF the current value of the register is not valid for the outer level; THEN zero the register and clear the valid flag; FI; To be valid, the register setting must satisfy the following properties: Selector index must be within descriptor table limits; AR byte must indicate data or readable code segment; IF segment is data or non-conforming code, THEN DPL must be . CPL, or DPL must be . RPL; OD;Description
In Real Address Mode, IRET pops the instruction pointer, CS, and the flags register from the stack and resumes the interrupted routine.
In Protected Mode, the action of IRET depends on the setting of the nested task flag (NT) bit in the flag register. When popping the new flag image from the stack, the IOPL bits in the flag register are changed only when CPL equals 0.
If NT equals 0, IRET returns from an interrupt procedure without a task switch. The code returned to must be equally or less privileged than the interrupt routine (as indicated by the RPL bits of the CS selector popped from the stack). If the destination code is less privileged, IRET also pops the stack pointer and SS from the stack.
If NT equals 1, IRET reverses the operation of a CALL or INT that caused a task switch. The updated state of the task executing IRET is saved in its task state segment. If the task is reentered later, the code that follows IRET is executed.
Flags Affected
All; the flags register is popped from stack
Protected Mode Exceptions
#GP, #NP, or #SS, as indicated under "Operation" above
Real Address Mode Exceptions
Interrupt 13 if any part of the operand being popped lies beyond address 0FFFFH
Virtual 8086 Mode Exceptions
#GP(0) fault if IOPL is less than 3, to permit emulation