<html>
<head>
<title>
17.3.I 'I' Instructions
</title>
<body>
<pre>
<a name="17-03-I"></a>
Prev: <a href="chp17-h3.htm">17.3.H 'H' Instructions </a>
Next: <a href="chp17-j3.htm">17.3.J 'J' Instructions </a>
<hr>
<h2>
17.3.I 'I' Instructions
</h2>
<a name="17-03-IDIV"></a>
<h3>IDIV -- Signed Divide</h3>
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."
��������������������������������������
<b>Description</b>
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:EAX
If 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.
<b>Flags Affected</b>
OF, SF, ZF, AR, PF, CF are undefined.
<b>Protected Mode Exceptions</b>
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
<b>Real Address Mode Exceptions</b>
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
<b>Virtual 8086 Mode Exceptions</b>
Same exceptions as in Real Address Mode; #PF(fault-code) for a page
fault
<a name="17-03-IMUL"></a>
<h3>IMUL -- Signed Multiply</h3>
Opcode Instruction Clocks Description
F6 /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} ��, 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;
<b>Description</b>
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 r32
<b>Flags Affected</b>
OF and CF as described above; SF, ZF, AF, and PF are undefined
<b>Protected Mode Exceptions</b>
#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
<b>Real Address Mode Exceptions</b>
Interrupt 13 if any part of the operand would lie outside of the effective
address space from 0 to 0FFFFH
<b>Virtual 8086 Mode Exceptions</b>
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.
<a name="17-03-IN"></a>
<h3>IN -- Input from Port</h3>
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 �PL
**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 *)
<b>Description</b>
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.
<b>Flags Affected</b>
None
<b>Protected Mode Exceptions</b>
#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
<b>Real Address Mode Exceptions</b>
None
<b>Virtual 8086 Mode Exceptions</b>
#GP(0) fault if any of the corresponding I/O permission bits in TSS
equals 1
<a name="17-03-INC"></a>
<h3>INC -- Increment by 1</h3>
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;
<b>Description</b>
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.
<b>Flags Affected</b>
OF, SF, ZF, AF, and PF as described in Appendix C
<b>Protected Mode Exceptions</b>
#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
<b>Real Address Mode Exceptions</b>
Interrupt 13 if any part of the operand would lie outside of the effective
address space from 0 to 0FFFFH
<b>Virtual 8086 Mode Exceptions</b>
Same exceptions as in Real Address Mode; #PF(fault-code) for a page
fault
<a name="17-03-INS"></a>
<h3>INS/INSB/INSW/INSD -- Input from Port to String</h3>
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 �PL
**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;
<b>Description</b>
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.
<b>Flags Affected</b>
None
<b>Protected Mode Exceptions</b>
#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
<b>Real Address Mode Exceptions</b>
Interrupt 13 if any part of the operand would lie outside of the effective
address space from 0 to 0FFFFH
<b>Virtual 8086 Mode Exceptions</b>
#GP(0) fault if any of the corresponding I/O permission bits in TSS
equals 1; #PF(fault-code) for a page fault
<a name="17-03-INT"></a>
<h3>INT/INTO -- Call to Interrupt Procedure</h3>
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 = 1
386
TSS VM=0 309 226 282
386
TSS VM=1 314 231 287
286
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);
<b>Description</b>
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.
<b>Flags Affected</b>
None
<b>Protected Mode Exceptions</b>
#GP, #NP, #SS, and #TS as indicated under "Operation" above
<b>Real Address Mode Exceptions</b>
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
<b>Virtual 8086 Mode Exceptions</b>
#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
<a name="17-03-IRET"></a>
<h3>IRET/IRETD -- Interrupt Return</h3>
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 = 1
386
TSS VM=0 275 224 271
286
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 �L, 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 �L, 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 �L, or DPL must be �L;
OD;
<b>Description</b>
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.
<b>Flags Affected</b>
All; the flags register is popped from stack
<b>Protected Mode Exceptions</b>
#GP, #NP, or #SS, as indicated under "Operation" above
<b>Real Address Mode Exceptions</b>
Interrupt 13 if any part of the operand being popped lies beyond address
0FFFFH
<b>Virtual 8086 Mode Exceptions</b>
#GP(0) fault if IOPL is less than 3, to permit emulation
<hr>
Prev: <a href="chp17-h3.htm">17.3.H 'H' Instructions </a>
Next: <a href="chp17-j3.htm">17.3.J 'J' Instructions </a>
</pre>
</body>
</html>
|