Оригинал лежит тут
AAA -- ASCII Adjust after Addition
Opcode | Instruction | Clocks |
Description | Example |
37 | aaa | 4 |
ASCII adjust AL after addition | aaa |
Operation
IF ((AL AND 0FH) > 9) OR (AF = 1)
THEN
AL := (AL + 6) AND 0FH;
AH := AH + 1;
AF := 1;
CF := 1;
ELSE
CF := 0;
AF := 0;
FI;
Description
Execute AAA only following an ADD instruction that leaves a byte result in the AL register. The lower nibbles of the operands of the ADD
instruction should be in the range 0 through 9 (BCD digits). In this
case, AAA adjusts AL to contain the correct decimal digit result. If
the addition produced a decimal carry, the AH register is incremented,
and the carry and auxiliary carry flags are set to 1. If there was no
decimal carry, the carry and auxiliary flags are set to 0 and AH is
unchanged. In either case, AL is left with its top nibble set to 0. To
convert AL to an ASCII result, follow the AAA instruction with OR AL, 30H.
Flags Affected
AF and CF as described above; OF, SF, ZF, and PF are undefined
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
AAD -- ASCII Adjust AX before Division
Opcode | Instruction | Clocks |
Description | Example |
D5 0A | aad | 19 |
ASCII adjust AX before division | aad |
Operation
AL := AH * 10 + AL;
AH := 0;
Description AAD is used to prepare two unpacked BCD
digits (the least-significant digit in AL, the most-significant digit
in AH) for a division operation that will yield an unpacked result.
This is accomplished by setting AL to AL + (10 * AH), and then setting
AH to 0. AX is then equal to the binary equivalent of the original
unpacked two-digit number. Flags Affected
SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
AAM -- ASCII Adjust AX after Multiply
Opcode | Instruction | Clocks |
Description | Example |
D4 0A | aam | 17 |
ASCII adjust AX after multiply | aam |
Operation
AH := AL / 10;
AL := AL MOD 10;
Description
Execute AAM only after executing a MUL
instruction between two unpacked BCD digits that leaves the result in
the AX register. Because the result is less than 100, it is contained
entirely in the AL register. AAM unpacks the AL result by dividing AL
by 10, leaving the quotient (most-significant digit) in AH and the
remainder (least-significant digit) in AL. Flags Affected
SF, ZF, and PF as described in Appendix C; OF, AF, and CF are undefined
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
AAS -- ASCII Adjust AL after Subtraction
Opcode | Instruction | Clocks |
Description | Example |
3F | aas | 4 |
ASCII adjust AL after subtraction | aas |
Operation
IF (AL AND 0FH) > 9 OR AF = 1
THEN
AL := AL - 6;
AL := AL AND 0FH;
AH := AH - 1;
AF := 1;
CF := 1;
ELSE
CF := 0;
AF := 0;
FI;
Description
Execute AAS only after a SUB instruction that leaves the byte result in the AL register. The lower nibbles of the operands of the SUB
instruction must have been in the range 0 through 9 (BCD digits). In
this case, AAS adjusts AL so it contains the correct decimal digit
result. If the subtraction produced a decimal carry, the AH register is
decremented, and the carry and auxiliary carry flags are set to 1. If
no decimal carry occurred, the carry and auxiliary carry flags are set
to 0, and AH is unchanged. In either case, AL is left with its top
nibble set to 0. To convert AL to an ASCII result, follow the AAS with OR AL, 30H.
Flags Affected
AF and CF as described above; OF, SF, ZF, and PF are undefined
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
ADC -- Add with Carry
Opcode | Instruction | Clocks |
Description | Example |
14 ib | adcb imm8,al | 2 |
Add with carry immediate byte to AL | adcb $0x7f,%al |
15 iw | adcw imm16,ax | 2 |
Add with carry immediate word to AX | adcw $0x7fff,%ax |
15 id | adcl imm32,eax | 2 |
Add with carry immediate dword to EAX | adcl $0x7fffffff,%eax |
80 /2 ib | adcb imm8,r/m8 | 2/7 |
Add with carry immediate byte to r/m byte | adcb $0x7f,%dl
adcb $0x7f,(%ebx,1)
adcb $0x7f,m8(%ebx,1)
adcb $0x7f,m8(%ebx,%ebp,1) |
81 /2 iw | adcw imm16,r/m16 | 2/7 |
Add with carry immediate word to r/m word | adcw $0x7fff,%cx
adcw $0x7fff,(%ebx,1)
adcw $0x7fff,(%ebx,2)
adcw $0x7fff,(%ebx,%ebp,1) |
81 /2 id | adcl imm32,r/m32 | 2/7 |
Add with CF immediate dword to r/m dword | adcl $0x7fffffff,%ecx
adcl $0x7fffffff,(%ebx,2)
adcl $0x7fffffff,(%ebx,4)
adcl $0x7fffffff,(%ebx,%ebp,1) |
83 /2 ib | adcw imm8,r/m16 | 2/7 |
Add with CF sign-extended immediate byte to r/m word | adcw $0x7f,%cx
adcw $0x7f,(%ebx,1)
adcw $0x7f,(%ebx,2)
adcw $0x7f,(%ebx,%ebp,1) |
83 /2 ib | adcl imm8,r/m32 | 2/7 |
Add with CF sign-extended immediate byte into r/m dword | adcl $0x7f,%ecx
adcl $0x7f,(%ebx,2)
adcl $0x7f,(%ebx,4)
adcl $0x7f,(%ebx,%ebp,1) |
10 /r | adcb r8,r/m8 | 2/7 |
Add with carry byte register to r/m byte | adcb %bh,%dl
adcb %bh,(%ebx,1)
adcb %bh,m8(%ebx,1)
adcb %bh,m8(%ebx,%ebp,1) |
11 /r | adcw r16,r/m16 | 2/7 |
Add with carry word register to r/m word | adcw %bx,%cx
adcw %bx,(%ebx,1)
adcw %bx,(%ebx,2)
adcw %bx,(%ebx,%ebp,1) |
11 /r | adcl r32,r/m32 | 2/7 |
Add with CF dword register to r/m dword | adcl %ebx,%ecx
adcl %ebx,(%ebx,2)
adcl %ebx,(%ebx,4)
adcl %ebx,(%ebx,%ebp,1) |
12 /r | adcb r/m8,r8 | 2/6 |
Add with carry r/m byte to byte register | adcb %dl,%bh
adcb (%ebx,1),%bh
adcb m8(%ebx,1),%bh
adcb m8(%ebx,%ebp,1),%bh |
13 /r | adcw r/m16,r16 | 2/6 |
Add with carry r/m word to word register | adcw %cx,%bx
adcw (%ebx,1),%bx
adcw (%ebx,2),%bx
adcw (%ebx,%ebp,1),%bx |
13 /r | adcl r/m32,r32 | 2/6 |
Add with CF r/m dword to dword register | adcl %ecx,%ebx
adcl (%ebx,2),%ebx
adcl (%ebx,4),%ebx
adcl (%ebx,%ebp,1),%ebx |
Operation
DEST := DEST + SRC + CF;
Description ADC performs an integer addition of the
two operands DEST and SRC and the carry flag, CF. The result of the
addition is assigned to the first operand (DEST), and the flags are set
accordingly. ADC is usually executed as part of a multi-byte or
multi-word addition operation. When an immediate byte value is added to
a word or doubleword operand, the immediate value is first
sign-extended to the size of the word or doubleword operand. Flags Affected
OF, SF, ZF, AF, CF, and PF as described in Appendix C
Protected Mode Exceptions
#GP(0) if the result 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) if
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
ADD -- Add
Opcode | Instruction | Clocks |
Description | Example |
04 ib | addb imm8,al | 2 |
Add immediate byte to AL | addb $0x7f,%al |
05 iw | addw imm16,ax | 2 |
Add immediate word to AX | addw $0x7fff,%ax |
05 id | addl imm32,eax | 2 |
Add immediate dword to EAX | addl $0x7fffffff,%eax |
80 /0 ib | addb imm8,r/m8 | 2/7 |
Add immediate byte to r/m byte | addb $0x7f,%dl
addb $0x7f,(%ebx,1)
addb $0x7f,m8(%ebx,1)
addb $0x7f,m8(%ebx,%ebp,1) |
81 /0 iw | addw imm16,r/m16 | 2/7 |
Add immediate word to r/m word | addw $0x7fff,%cx
addw $0x7fff,(%ebx,1)
addw $0x7fff,(%ebx,2)
addw $0x7fff,(%ebx,%ebp,1) |
81 /0 id | addl imm32,r/m32 | 2/7 |
Add immediate dword to r/m dword | addl $0x7fffffff,%ecx
addl $0x7fffffff,(%ebx,2)
addl $0x7fffffff,(%ebx,4)
addl $0x7fffffff,(%ebx,%ebp,1) |
83 /0 ib | addw imm8,r/m16 | 2/7 |
Add sign-extended immediate byte to r/m word | addw $0x7f,%cx
addw $0x7f,(%ebx,1)
addw $0x7f,(%ebx,2)
addw $0x7f,(%ebx,%ebp,1) |
83 /0 ib | addl imm8,r/m32 | 2/7 |
Add sign-extended immediate byte to r/m dword | addl $0x7f,%ecx
addl $0x7f,(%ebx,2)
addl $0x7f,(%ebx,4)
addl $0x7f,(%ebx,%ebp,1) |
00 /r | addb r8,r/m8 | 2/7 |
Add byte register to r/m byte | addb %bh,%dl
addb %bh,(%ebx,1)
addb %bh,m8(%ebx,1)
addb %bh,m8(%ebx,%ebp,1) |
01 /r | addw r16,r/m16 | 2/7 |
Add word register to r/m word | addw %bx,%cx
addw %bx,(%ebx,1)
addw %bx,(%ebx,2)
addw %bx,(%ebx,%ebp,1) |
01 /r | addl r32,r/m32 | 2/7 |
Add dword register to r/m dword | addl %ebx,%ecx
addl %ebx,(%ebx,2)
addl %ebx,(%ebx,4)
addl %ebx,(%ebx,%ebp,1) |
02 /r | addb r/m8,r8 | 2/6 |
Add r/m byte to byte register | addb %dl,%bh
addb (%ebx,1),%bh
addb m8(%ebx,1),%bh
addb m8(%ebx,%ebp,1),%bh |
03 /r | addw r/m16,r16 | 2/6 |
Add r/m word to word register | addw %cx,%bx
addw (%ebx,1),%bx
addw (%ebx,2),%bx
addw (%ebx,%ebp,1),%bx |
03 /r | addl r/m32,r32 | 2/6 |
Add r/m dword to dword register | addl %ecx,%ebx
addl (%ebx,2),%ebx
addl (%ebx,4),%ebx
addl (%ebx,%ebp,1),%ebx |
Operation
DEST := DEST + SRC;
Description ADD performs an integer addition of the
two operands (DEST and SRC). The result of the addition is assigned to
the first operand (DEST), and the flags are set accordingly. When an immediate byte is added to a word or doubleword operand,
the immediate value is sign-extended to the size of the word or
doubleword operand. Flags Affected
OF, SF, ZF, AF, CF, and PF as described in Appendix C
Protected Mode Exceptions
#GP(0) if the result 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
AND -- Logical AND
Opcode | Instruction | Clocks |
Description | Example |
24 ib | andb imm8,al | 2 |
AND immediate byte to AL | andb $0x7f,%al |
25 iw | andw imm16,ax | 2 |
AND immediate word to AX | andw $0x7fff,%ax |
25 id | andl imm32,eax | 2 |
AND immediate dword to EAX | andl $0x7fffffff,%eax |
80 /4 ib | andb imm8,r/m8 | 2/7 |
AND immediate byte to r/m byte | andb $0x7f,%dl
andb $0x7f,(%ebx,1)
andb $0x7f,m8(%ebx,1)
andb $0x7f,m8(%ebx,%ebp,1) |
81 /4 iw | andw imm16,r/m16 | 2/7 |
AND immediate word to r/m word | andw $0x7fff,%cx
andw $0x7fff,(%ebx,1)
andw $0x7fff,(%ebx,2)
andw $0x7fff,(%ebx,%ebp,1) |
81 /4 id | andl imm32,r/m32 | 2/7 |
AND immediate dword to r/m dword | andl $0x7fffffff,%ecx
andl $0x7fffffff,(%ebx,2)
andl $0x7fffffff,(%ebx,4)
andl $0x7fffffff,(%ebx,%ebp,1) |
83 /4 ib | andw imm8,r/m16 | 2/7 |
AND sign-extended immediate byte with r/m word | andw $0x7f,%cx
andw $0x7f,(%ebx,1)
andw $0x7f,(%ebx,2)
andw $0x7f,(%ebx,%ebp,1) |
83 /4 ib | andl imm8,r/m32 | 2/7 |
AND sign-extended immediate byte with r/m dword | andl $0x7f,%ecx
andl $0x7f,(%ebx,2)
andl $0x7f,(%ebx,4)
andl $0x7f,(%ebx,%ebp,1) |
20 /r | andb r8,r/m8 | 2/7 |
AND byte register to r/m byte | andb %bh,%dl
andb %bh,(%ebx,1)
andb %bh,m8(%ebx,1)
andb %bh,m8(%ebx,%ebp,1) |
21 /r | andw r16,r/m16 | 2/7 |
AND word register to r/m word | andw %bx,%cx
andw %bx,(%ebx,1)
andw %bx,(%ebx,2)
andw %bx,(%ebx,%ebp,1) |
21 /r | andl r32,r/m32 | 2/7 |
AND dword register to r/m dword | andl %ebx,%ecx
andl %ebx,(%ebx,2)
andl %ebx,(%ebx,4)
andl %ebx,(%ebx,%ebp,1) |
22 /r | andb r/m8,r8 | 2/6 |
AND r/m byte to byte register | andb %dl,%bh
andb (%ebx,1),%bh
andb m8(%ebx,1),%bh
andb m8(%ebx,%ebp,1),%bh |
23 /r | andw r/m16,r16 | 2/6 |
AND r/m word to word register | andw %cx,%bx
andw (%ebx,1),%bx
andw (%ebx,2),%bx
andw (%ebx,%ebp,1),%bx |
23 /r | andl r/m32,r32 | 2/6 |
AND r/m dword to dword register | andl %ecx,%ebx
andl (%ebx,2),%ebx
andl (%ebx,4),%ebx
andl (%ebx,%ebp,1),%ebx |
Operation
DEST := DEST AND SRC;
CF := 0;
OF := 0;
Description Each bit of the result of the AND
instruction is a 1 if both corresponding bits of the operands are 1;
otherwise, it becomes a 0. Flags Affected
CF := 0, OF := 0; PF, SF, and ZF as described in Appendix C
Protected Mode Exceptions
#GP(0) if the result 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
ARPL -- Adjust RPL Field of Selector
Opcode | Instruction | Clocks |
Description | Example |
63 /r | arplw r16,r/m16 | pm=20/21 |
Adjust RPL of r/m16 to not less than RPL of r16 | arplw %bx,%cx
arplw %bx,(%ebx,1)
arplw %bx,(%ebx,2)
arplw %bx,(%ebx,%ebp,1) |
Operation
IF RPL bits(0,1) of DEST < RPL bits(0,1) of SRC
THEN
ZF := 1;
RPL bits(0,1) of DEST := RPL bits(0,1) of SRC;
ELSE
ZF := 0;
FI;
Description The ARPL instruction has two operands.
The first operand is a 16-bit memory variable or word register that
contains the value of a selector. The second operand is a word
register. If the RPL field ("requested privilege level"--bottom two
bits) of the first operand is less than the RPL field of the second
operand, the zero flag is set to 1 and the RPL field of the first
operand is increased to match the second operand. Otherwise, the zero
flag is set to 0 and no change is made to the first operand. ARPL appears in operating system software, not in application
programs. It is used to guarantee that a selector parameter to a
subroutine does not request more privilege than the caller is allowed.
The second operand of ARPL is normally a register that contains the CS
selector value of the caller. Flags Affected
ZF as described above
Protected Mode Exceptions
#GP(0) if the result 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 6; ARPL is not recognized in Real Address Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
BOUND -- Check Array Index Against Bounds
Opcode | Instruction | Clocks |
Description | Example |
62 /r | boundw r16,m16&16 | 10 |
Check if r16 is within bounds (passes test) | boundw %bx,m16 |
62 /r | boundl r32,m32&32 | 10 |
Check if r32 is within bounds (passes test) | boundl %ebx,m32 |
Operation
IF (LeftSRC < [RightSRC] OR LeftSRC > [RightSRC + OperandSize/8])
(* Under lower bound or over upper bound *)
THEN Interrupt 5;
FI;
Description BOUND ensures that a signed array index
is within the limits specified by a block of memory consisting of an
upper and a lower bound. Each bound uses one word for an operand-size
attribute of 16 bits and a doubleword for an operand-size attribute of
32 bits. The first operand (a register) must be greater than or equal
to the first bound in memory (lower bound), and less than or equal to
the second bound in memory (upper bound). If the register is not within
bounds, an Interrupt 5 occurs; the return EIP points to the BOUND
instruction. The bounds limit data structure is usually placed just before
the array itself, making the limits addressable via a constant offset
from the beginning of the array. Flags Affected
None
Protected Mode Exceptions
Interrupt 5 if the bounds test fails, as described above; #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 The second operand must be a memory operand, not a register. If
BOUND is executed with a ModRM byte representing a register as the
second operand, #UD occurs. Real Address Mode Exceptions Interrupt 5 if the bounds
test fails; Interrupt 13 if any part of the operand would lie outside
of the effective address space from 0 to 0FFFFH; Interrupt 6 if the
second operand is a register Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
BSF -- Bit Scan Forward
Opcode | Instruction | Clocks |
Description | Example |
0F BC | bsfw r/m16,r16 | 10+3n |
Bit scan forward on r/m word | bsfw %cx,%bx
bsfw (%ebx,1),%bx
bsfw (%ebx,2),%bx
bsfw (%ebx,%ebp,1),%bx |
0F BC | bsfl r/m32,r32 | 10+3n |
Bit scan forward on r/m dword | bsfl %ecx,%ebx
bsfl (%ebx,2),%ebx
bsfl (%ebx,4),%ebx
bsfl (%ebx,%ebp,1),%ebx |
Notes
is the number of leading zero bits.
Operation
IF r/m = 0
THEN
ZF := 1;
register := UNDEFINED;
ELSE
temp := 0;
ZF := 0;
WHILE BIT[r/m, temp = 0]
DO
temp := temp + 1;
register := temp;
OD;
FI;
Description BSF scans the bits in the second word or
doubleword operand starting with bit 0. The ZF flag is cleared if the
bits are all 0; otherwise, the ZF flag is set and the destination
register is loaded with the bit index of the first set bit. Flags Affected
ZF as described above
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 exceptions as in Real Address Mode; #PF(fault-code) for a page fault
BSR -- Bit Scan Reverse
Opcode | Instruction | Clocks |
Description | Example |
0F BD | bsrw r/m16,r16 | 10+3n |
Bit scan reverse on r/m word | bsrw %cx,%bx
bsrw (%ebx,1),%bx
bsrw (%ebx,2),%bx
bsrw (%ebx,%ebp,1),%bx |
0F BD | bsrl r/m32,r32 | 10+3n |
Bit scan reverse on r/m dword | bsrl %ecx,%ebx
bsrl (%ebx,2),%ebx
bsrl (%ebx,4),%ebx
bsrl (%ebx,%ebp,1),%ebx |
Operation
IF r/m = 0
THEN
ZF := 1;
register := UNDEFINED;
ELSE
temp := OperandSize - 1;
ZF := 0;
WHILE BIT[r/m, temp] = 0
DO
temp := temp - 1;
register := temp;
OD;
FI;
Description BSR scans the bits in the second word or
doubleword operand from the most significant bit to the least
significant bit. The ZF flag is cleared if the bits are all 0;
otherwise, ZF is set and the destination register is loaded with the
bit index of the first set bit found when scanning in the reverse
direction. Flags Affected
ZF as described above
Protected Mode Exceptions
#GP(0) if the result 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
BT -- Bit Test
Opcode | Instruction | Clocks |
Description | Example |
0F A3 | btw r16,r/m16 | 3/12 |
Save bit in carry flag | btw %bx,%cx
btw %bx,(%ebx,1)
btw %bx,(%ebx,2)
btw %bx,(%ebx,%ebp,1) |
0F A3 | btl r32,r/m32 | 3/12 |
Save bit in carry flag | btl %ebx,%ecx
btl %ebx,(%ebx,2)
btl %ebx,(%ebx,4)
btl %ebx,(%ebx,%ebp,1) |
0F BA /4 ib | btw imm8,r/m16 | 3/6 |
Save bit in carry flag | btw $0x7f,%cx
btw $0x7f,(%ebx,1)
btw $0x7f,(%ebx,2)
btw $0x7f,(%ebx,%ebp,1) |
0F BA /4 ib | btl imm8,r/m32 | 3/6 |
Save bit in carry flag | btl $0x7f,%ecx
btl $0x7f,(%ebx,2)
btl $0x7f,(%ebx,4)
btl $0x7f,(%ebx,%ebp,1) |
Operation
CF := BIT[LeftSRC, RightSRC];
Description
BT saves the value of the bit indicated by the base (first operand) and the bit offset (second operand) into the carry flag.
Flags Affected
CF as described above
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 exceptions as in Real Address Mode; #PF(fault-code) for a page fault
Notes
The index of the selected bit can be given by the immediate constant in
the instruction or by a value in a general register. Only an 8-bit
immediate value is used in the instruction. This operand is taken
modulo 32, so the range of immediate bit offsets is 0..31. This allows
any bit within a register to be selected. For memory bit strings, this
immediate field gives only the bit offset within a word or doubleword.
Immediate bit offsets larger than 31 are supported by using the
immediate bit offset field in combination with the displacement field
of the memory operand. The low-order 3 to 5 bits of the immediate bit
offset are stored in the immediate bit offset field, and the high-order
27 to 29 bits are shifted and combined with the byte displacement in
the addressing mode. When accessing a bit in memory, the 80386 may access four bytes starting from the memory address given by:
Effective Address + (4 * (BitOffset DIV 32))
for a 32-bit operand size, or two bytes starting from the memory address given by:
Effective Address + (2 * (BitOffset DIV 16))
for a 16-bit operand size. It may do so even when only a single
byte needs to be accessed in order to reach the given bit. You must
therefore avoid referencing areas of memory close to address space
holes. In particular, avoid references to memory-mapped I/O registers.
Instead, use the MOV instructions to load from or store to these addresses, and use the register form of these instructions to manipulate the data.
BTC -- Bit Test and Complement
Opcode | Instruction | Clocks |
Description | Example |
0F BB | btcw r16,r/m16 | 6/13 |
Save bit in carry flag and complement | btcw %bx,%cx
btcw %bx,(%ebx,1)
btcw %bx,(%ebx,2)
btcw %bx,(%ebx,%ebp,1) |
0F BB | btcl r32,r/m32 | 6/13 |
Save bit in carry flag and complement | btcl %ebx,%ecx
btcl %ebx,(%ebx,2)
btcl %ebx,(%ebx,4)
btcl %ebx,(%ebx,%ebp,1) |
0F BA /7 ib | btcw imm8,r/m16 | 6/8 |
Save bit in carry flag and complement | btcw $0x7f,%cx
btcw $0x7f,(%ebx,1)
btcw $0x7f,(%ebx,2)
btcw $0x7f,(%ebx,%ebp,1) |
0F BA /7 ib | btcl imm8,r/m32 | 6/8 |
Save bit in carry flag and complement | btcl $0x7f,%ecx
btcl $0x7f,(%ebx,2)
btcl $0x7f,(%ebx,4)
btcl $0x7f,(%ebx,%ebp,1) |
Operation
CF := BIT[LeftSRC, RightSRC];
BIT[LeftSRC, RightSRC] := NOT BIT[LeftSRC, RightSRC];
Description BTC saves the value of the bit indicated
by the base (first operand) and the bit offset (second operand) into
the carry flag and then complements the bit. Flags Affected
CF as described above
Protected Mode Exceptions
#GP(0) if the result 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
Notes
The index of the selected bit can be given by the immediate constant in
the instruction or by a value in a general register. Only an 8-bit
immediate value is used in the instruction. This operand is taken
modulo 32, so the range of immediate bit offsets is 0..31. This allows
any bit within a register to be selected. For memory bit strings, this
immediate field gives only the bit offset within a word or doubleword.
Immediate bit offsets larger than 31 are supported by using the
immediate bit offset field in combination with the displacement field
of the memory operand. The low-order 3 to 5 bits of the immediate bit
offset are stored in the immediate bit offset field, and the high-order
27 to 29 bits are shifted and combined with the byte displacement in
the addressing mode. When accessing a bit in memory, the 80386 may access four bytes starting from the memory address given by:
Effective Address + (4 * (BitOffset DIV 32))
for a 32-bit operand size, or two bytes starting from the memory address given by:
Effective Address + (2 * (BitOffset DIV 16))
for a 16-bit operand size. It may do so even when only a single
byte needs to be accessed in order to reach the given bit. You must
therefore avoid referencing areas of memory close to address space
holes. In particular, avoid references to memory-mapped I/O registers.
Instead, use the MOV instructions to load from or store to these addresses, and use the register form of these instructions to manipulate the data.
BTR -- Bit Test and Reset
Opcode | Instruction | Clocks |
Description | Example |
0F B3 | btrw r16,r/m16 | 6/13 |
Save bit in carry flag and reset | btrw %bx,%cx
btrw %bx,(%ebx,1)
btrw %bx,(%ebx,2)
btrw %bx,(%ebx,%ebp,1) |
0F B3 | btrl r32,r/m32 | 6/13 |
Save bit in carry flag and reset | btrl %ebx,%ecx
btrl %ebx,(%ebx,2)
btrl %ebx,(%ebx,4)
btrl %ebx,(%ebx,%ebp,1) |
0F BA /6 ib | btrw imm8,r/m16 | 6/8 |
Save bit in carry flag and reset | btrw $0x7f,%cx
btrw $0x7f,(%ebx,1)
btrw $0x7f,(%ebx,2)
btrw $0x7f,(%ebx,%ebp,1) |
0F BA /6 ib | btrl imm8,r/m32 | 6/8 |
Save bit in carry flag and reset | btrl $0x7f,%ecx
btrl $0x7f,(%ebx,2)
btrl $0x7f,(%ebx,4)
btrl $0x7f,(%ebx,%ebp,1) |
Operation
CF := BIT[LeftSRC, RightSRC];
BIT[LeftSRC, RightSRC] := 0;
Description BTR saves the value of the bit indicated
by the base (first operand) and the bit offset (second operand) into
the carry flag and then stores 0 in the bit. Flags Affected
CF as described above
Protected Mode Exceptions
#GP(0) if the result 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
Notes
The index of the selected bit can be given by the immediate constant in
the instruction or by a value in a general register. Only an 8-bit
immediate value is used in the instruction. This operand is taken
modulo 32, so the range of immediate bit offsets is 0..31. This allows
any bit within a register to be selected. For memory bit strings, this
immediate field gives only the bit offset within a word or doubleword.
Immediate bit offsets larger than 31 (or 15) are supported by using the
immediate bit offset field in combination with the displacement field
of the memory operand. The low-order 3 to 5 bits of the immediate bit
offset are stored in the immediate bit offset field, and the high-order
27 to 29 bits are shifted and combined with the byte displacement in
the addressing mode. When accessing a bit in memory, the 80386 may access four bytes starting from the memory address given by:
Effective Address + 4 * (BitOffset DIV 32)
for a 32-bit operand size, or two bytes starting from the memory address given by:
Effective Address + 2 * (BitOffset DIV 16)
for a 16-bit operand size. It may do so even when only a single
byte needs to be accessed in order to reach the given bit. You must
therefore avoid referencing areas of memory close to address space
holes. In particular, avoid references to memory-mapped I/O registers.
Instead, use the MOV instructions to load from or store to these addresses, and use the register form of these instructions to manipulate the data.
BTS -- Bit Test and Set
Opcode | Instruction | Clocks |
Description | Example |
0F AB | btsw r16,r/m16 | 6/13 |
Save bit in carry flag and set | btsw %bx,%cx
btsw %bx,(%ebx,1)
btsw %bx,(%ebx,2)
btsw %bx,(%ebx,%ebp,1) |
0F AB | btsl r32,r/m32 | 6/13 |
Save bit in carry flag and set | btsl %ebx,%ecx
btsl %ebx,(%ebx,2)
btsl %ebx,(%ebx,4)
btsl %ebx,(%ebx,%ebp,1) |
0F BA /5 ib | btsw imm8,r/m16 | 6/8 |
Save bit in carry flag and set | btsw $0x7f,%cx
btsw $0x7f,(%ebx,1)
btsw $0x7f,(%ebx,2)
btsw $0x7f,(%ebx,%ebp,1) |
0F BA /5 ib | btsl imm8,r/m32 | 6/8 |
Save bit in carry flag and set | btsl $0x7f,%ecx
btsl $0x7f,(%ebx,2)
btsl $0x7f,(%ebx,4)
btsl $0x7f,(%ebx,%ebp,1) |
Operation
CF := BIT[LeftSRC, RightSRC];
BIT[LeftSRC, RightSRC] := 1;
Description BTS saves the value of the bit indicated
by the base (first operand) and the bit offset (second operand) into
the carry flag and then stores 1 in the bit. Flags Affected
CF as described above
Protected Mode Exceptions
#GP(0) if the result 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
Notes
The index of the selected bit can be given by the immediate constant in
the instruction or by a value in a general register. Only an 8-bit
immediate value is used in the instruction. This operand is taken
modulo 32, so the range of immediate bit offsets is 0..31. This allows
any bit within a register to be selected. For memory bit strings, this
immediate field gives only the bit offset within a word or doubleword.
Immediate bit offsets larger than 31 are supported by using the
immediate bit offset field in combination with the displacement field
of the memory operand. The low-order 3 to 5 bits of the immediate bit
offset are stored in the immediate bit offset field, and the high order
27 to 29 bits are shifted and combined with the byte displacement in
the addressing mode. When accessing a bit in memory, the processor may access four bytes starting from the memory address given by:
Effective Address + (4 * (BitOffset DIV 32))
for a 32-bit operand size, or two bytes starting from the memory address given by:
Effective Address + (2 * (BitOffset DIV 16))
for a 16-bit operand size. It may do this even when only a
single byte needs to be accessed in order to get at the given bit. Thus
the programmer must be careful to avoid referencing areas of memory
close to address space holes. In particular, avoid references to
memory-mapped I/O registers. Instead, use the MOV instructions to load from or store to these addresses, and use the register form of these instructions to manipulate the data.
CALL -- Call Procedure
Opcode | Instruction | Clocks |
Description | Example |
E8 cw | call rel16 | 7+m |
Call near, displacement relative to next instruction | call rel16 |
FF /2 | callw r/m16 | 7+m/10+m |
Call near, register indirect/memory indirect | callw *%cx
callw *(%ebx,1)
callw (%ebx,2)
callw (%ebx,%ebp,1) |
9A cd | callw ptr16:16 | 17+m,pm=34+m |
Call intersegment, to full pointer given | callw *(%ebx,1) |
9A cd | callw ptr16:16 | pm=52+m |
Call gate, same privilege | callw *(%ebx,1) |
9A cd | callw ptr16:16 | pm=86+m |
Call gate, more privilege, no parameters | callw *(%ebx,1) |
9A cd | callw ptr16:16 | pm=94+4x+m |
Call gate, more privilege, x parameters | callw *(%ebx,1) |
9A cd | callw ptr16:16 | ts |
Call to task | callw *(%ebx,1) |
FF /3 | callw m16:16 | 22+m,pm=38+m |
Call intersegment, address at r/m dword | call tocall |
FF /3 | callw m16:16 | pm=56+m |
Call gate, same privilege | call tocall |
FF /3 | callw m16:16 | pm=90+m |
Call gate, more privilege, no parameters | call tocall |
FF /3 | callw m16:16 | pm=98+4x+m |
Call gate, more privilege, x parameters | call tocall |
FF /3 | callw m16:16 | 5 + ts |
Call to task | call tocall |
E8 cd | call rel32 | 7+m |
Call near, displacement relative to next instruction | call rel32 |
FF /2 | calll r/m32 | 7+m/10+m |
Call near, indirect | calll *%ecx
calll *(%ebx,2)
calll (%ebx,4)
calll (%ebx,%ebp,1) |
9A cp | callw ptr16:32 | 17+m,pm=34+m |
Call intersegment, to full pointer given | callw *(%ebx,1) |
9A cp | callw ptr16:32 | pm=52+m |
Call gate, same privilege | callw *(%ebx,1) |
9A cp | callw ptr16:32 | pm=86+m |
Call gate, more privilege, no parameters | callw *(%ebx,1) |
9A cp | calll ptr32:32 | pm=94+4x+m |
Call gate, more privilege, x parameters | calll *(%ebx,1) |
9A cp | callw ptr16:32 | ts |
Call to task | callw *(%ebx,1) |
FF /3 | callw m16:32 | 22+m,pm=38+m |
Call intersegment, address at r/m dword | call tocall |
FF /3 | callw m16:32 | pm=56+m |
Call gate, same privilege | call tocall |
FF /3 | callw m16:32 | pm=90+m |
Call gate, more privilege, no parameters | call tocall |
FF /3 | callw m16:32 | pm=98+4x+m |
Call gate, more privilege, x parameters | call tocall |
FF /3 | callw m16:32 | 5 + ts |
Call to task | call tocall |
Note
Values of ts are given by the following table:
New Task
386 TSS 386 TSS 286 TSS
Old VM = 0 VM = 1
Task Via Task Gate?
N Y N Y N Y
386 300 309 217 226 273 282
TSS VM=0
286 298 307 217 226 273 282
TSS
Operation
IF rel16 or rel32 type of call
THEN (* near relative call *)
IF OperandSize = 16
THEN
Push(IP);
EIP := (EIP + rel16) AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
Push(EIP);
EIP := EIP + rel32;
FI;
FI;
IF r/m16 or r/m32 type of call
THEN (* near absolute call *)
IF OperandSize = 16
THEN
Push(IP);
EIP := [r/m16] AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
Push(EIP);
EIP := [r/m32];
FI;
FI;
IF (PE = 0 OR (PE = 1 AND VM = 1))
(* real mode or virtual 8086 mode *)
AND instruction = far CALL
(* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *)
THEN
IF OperandSize = 16
THEN
Push(CS);
Push(IP); (* address of next instruction; 16 bits *)
ELSE
Push(CS); (* padded with 16 high-order bits *)
Push(EIP); (* address of next instruction; 32 bits *)
FI;
IF operand type is m16:16 or m16:32
THEN (* indirect far call *)
IF OperandSize = 16
THEN
CS:IP := [m16:16];
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := [m16:32];
FI;
FI;
IF operand type is ptr16:16 or ptr16:32
THEN (* direct far call *)
IF OperandSize = 16
THEN
CS:IP := ptr16:16;
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := ptr16:32;
FI;
FI;
FI;
IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *)
AND instruction = far CALL
THEN
If indirect, then check access of EA doubleword;
#GP(0) if limit violation;
New CS selector must not be null else #GP(0);
Check that new CS selector index is within its
descriptor table limits; else #GP(new CS selector);
Examine AR byte of selected descriptor for various legal values;
depending on value:
go to CONFORMING-CODE-SEGMENT;
go to NONCONFORMING-CODE-SEGMENT;
go to CALL-GATE;
go to TASK-GATE;
go to TASK-STATE-SEGMENT;
ELSE #GP(code segment selector);
FI;
CONFORMING-CODE-SEGMENT:
DPL must be <= CPL ELSE #GP(code segment selector);
Segment must be present ELSE #NP(code segment selector);
Stack must be big enough for return address ELSE #SS(0);
Instruction pointer must be in code segment limit ELSE #GP(0);
Load code segment descriptor into CS register;
Load CS with new code segment selector;
Load EIP with zero-extend(new offset);
IF OperandSize=16 THEN EIP := EIP AND 0000FFFFH; FI;
NONCONFORMING-CODE-SEGMENT:
RPL must be <= CPL ELSE #GP(code segment selector)
DPL must be = CPL ELSE #GP(code segment selector)
Segment must be present ELSE #NP(code segment selector)
Stack must be big enough for return address ELSE #SS(0)
Instruction pointer must be in code segment limit ELSE #GP(0)
Load code segment descriptor into CS register
Load CS with new code segment selector
Set RPL of CS to CPL
Load EIP with zero-extend(new offset);
IF OperandSize=16 THEN EIP := EIP AND 0000FFFFH; FI;
CALL-GATE:
Call gate DPL must be >= CPL ELSE #GP(call gate selector)
Call gate DPL must be >= RPL ELSE #GP(call gate selector)
Call gate must be present ELSE #NP(call gate selector)
Examine code segment selector in call gate descriptor:
Selector must not be null ELSE #GP(0)
Selector must be within its descriptor table
limits ELSE #GP(code segment selector)
AR byte of selected descriptor must indicate code
segment ELSE #GP(code segment selector)
DPL of selected descriptor must be <= CPL ELSE
#GP(code segment selector)
IF non-conforming code segment AND DPL < CPL
THEN go to MORE-PRIVILEGE
ELSE go to SAME-PRIVILEGE
FI;
MORE-PRIVILEGE:
Get new SS selector for new privilege level from TSS
Check selector and descriptor for new SS:
Selector must not be null ELSE #TS(0)
Selector index must be within its descriptor
table limits ELSE #TS(SS selector)
Selector's RPL must equal DPL of code segment
ELSE #TS(SS selector)
Stack segment DPL must equal DPL of code
segment ELSE #TS(SS selector)
Descriptor must indicate writable data segment
ELSE #TS(SS selector)
Segment present ELSE #SS(SS selector)
IF OperandSize=32
THEN
New stack must have room for parameters plus 16 bytes
ELSE #SS(0)
EIP must be in code segment limit ELSE #GP(0)
Load new SS:eSP value from TSS
Load new CS:EIP value from gate
ELSE
New stack must have room for parameters plus 8 bytes ELSE #SS(0)
IP must be in code segment limit ELSE #GP(0)
Load new SS:eSP value from TSS
Load new CS:IP value from gate
FI;
Load CS descriptor
Load SS descriptor
Push long pointer of old stack onto new stack
Get word count from call gate, mask to 5 bits
Copy parameters from old stack onto new stack
Push return address onto new stack
Set CPL to stack segment DPL
Set RPL of CS to CPL
SAME-PRIVILEGE:
IF OperandSize=32
THEN
Stack must have room for 6-byte return address (padded to 8 bytes)
ELSE #SS(0)
EIP must be within code segment limit ELSE #GP(0)
Load CS:EIP from gate
ELSE
Stack must have room for 4-byte return address ELSE #SS(0)
IP must be within code segment limit ELSE #GP(0)
Load CS:IP from gate
FI;
Push return address onto stack
Load code segment descriptor into CS register
Set RPL of CS to CPL
TASK-GATE:
Task gate DPL must be >= CPL ELSE #TS(gate selector)
Task gate DPL must be >= RPL ELSE #TS(gate selector)
Task Gate must be present ELSE #NP(gate selector)
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)
TSS descriptor AR byte must specify nonbusy TSS
ELSE #TS(TSS selector)
Task State Segment must be present ELSE #NP(TSS selector)
SWITCH-TASKS (with nesting) to TSS
IP must be in code segment limit ELSE #TS(0)
TASK-STATE-SEGMENT:
TSS DPL must be >= CPL else #TS(TSS selector)
TSS DPL must be >= RPL ELSE #TS(TSS selector)
TSS descriptor AR byte must specify available TSS
ELSE #TS(TSS selector)
Task State Segment must be present ELSE #NP(TSS selector)
SWITCH-TASKS (with nesting) to TSS
IP must be in code segment limit ELSE #TS(0)
Description The CALL instruction causes the procedure
named in the operand to be executed. When the procedure is complete (a
return instruction is executed within the procedure), execution
continues at the instruction that follows the CALL instruction. The action of the different forms of the instruction are described below.
Near calls
are those with destinations of type r/m16, r/m32, rel16, rel32;
changing or saving the segment register value is not necessary. The
CALL rel16 and CALL rel32 forms add a signed offset to the address of
the instruction following CALL to determine the destination. The rel16
form is used when the instruction's operand-size attribute is 16 bits;
rel32 is used when the operand-size attribute is 32 bits. The result is
stored in the 32-bit EIP register. With rel16, the upper 16 bits of EIP
are cleared, resulting in an offset whose value does not exceed 16
bits. CALL r/m16 and CALL r/m32 specify a register or memory location
from which the absolute segment offset is fetched. The offset fetched
from r/m is 32 bits for an operand-size attribute of 32 (r/m32), or 16
bits for an operand-size of 16 (r/m16). The offset of the instruction
following CALL is pushed onto the stack. It will be popped by a near RET instruction within the procedure. The CS register is not changed by this form of CALL.
The far calls,
CALL ptr16:16 and CALL ptr16:32, use a four-byte or six-byte operand as
a long pointer to the procedure called. The CALL m16:16 and m16:32
forms fetch the long pointer from the memory location specified
(indirection). In Real Address Mode or Virtual 8086 Mode, the long
pointer provides 16 bits for the CS register and 16 or 32 bits for the
EIP register (depending on the operand-size attribute). These forms of
the instruction push both CS and IP or EIP as a return address. In Protected Mode, both long pointer forms consult the AR
byte in the descriptor indexed by the selector part of the long
pointer. Depending on the value of the AR byte, the call will perform
one of the following types of control transfers:
- A far call to the same protection level
- An inter-protection level far call
- A task switch
For more information on Protected Mode control transfers, refer to Chapter 6 and Chapter 7.
Flags Affected
All flags are affected if a task switch occurs; no flags are affected if a task switch does not occur
Protected Mode Exceptions
For far calls: #GP, #NP, #SS, and #TS, as indicated in the list above
For near direct calls:
#GP(0) if procedure location is beyond the code segment limits; #SS(0)
if pushing the return address exceeds the bounds of the stack segment;
#PF (fault-code) for a page fault For a near indirect call:
#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; #GP(0) if the indirect offset obtained is beyond the code
segment limits; #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
Notes
Any far call from a 32-bit code segment to 16-bit code segments should
be made from the first 64K bytes of the 32-bit code segment, since the
operand-size attribute of the instruction is set to 16, thus allowing
only a 16-bit return address offset to be saved.
CBW/CWDE -- Convert Byte to Word/Convert Word to Doubleword
Opcode | Instruction | Clocks |
Description | Example |
98 | cbw | 3 |
AX := sign-extend of AL | cbw |
98 | cwde | 3 |
EAX := sign-extend of AX | cwde |
Operation
IF OperandSize = 16 (* instruction = CBW *)
THEN AX := SignExtend(AL);
ELSE (* OperandSize = 32, instruction = CWDE *)
EAX := SignExtend(AX);
FI;
Description CBW converts the signed byte in AL to a
signed word in AX by extending the most significant bit of AL (the sign
bit) into all of the bits of AH. CWDE converts the signed word in AX to
a doubleword in EAX by extending the most significant bit of AX into
the two most significant bytes of EAX. Note that CWDE is different from
CWD. CWD uses DX:AX rather than EAX as a destination. Flags Affected
None
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
CLC -- Clear Carry Flag
Opcode | Instruction | Clocks |
Description | Example |
F8 | clc | 2 |
Clear carry flag | clc |
Operation
CF := 0;
Description
CLC sets the carry flag to zero. It does not affect other flags or registers.
Flags Affected
CF := 0
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
CLD -- Clear Direction Flag
Opcode | Instruction | Clocks |
Description | Example |
FC | cld | 2 |
Clear direction flag | cld |
Operation
DF := 0;
Description CLD clears the direction flag. No other
flags or registers are affected. After CLD is executed, string
operations will increment the index registers (SI and/or DI) that they
use. Flags Affected
DF := 0
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
CLI -- Clear Interrupt Flag
Opcode | Instruction | Clocks |
Description | Example |
FA | cli | 3 |
Clear interrupt flag | cli |
Operation
IF := 0;
Description CLI clears the interrupt flag if the
current privilege level is at least as privileged as IOPL. No other
flags are affected. External interrupts are not recognized at the end
of the CLI instruction or from that point on until the interrupt flag
is set. Flags Affected
IF := 0
Protected Mode Exceptions
#GP(0) if the current privilege level is greater (has less privilege)
than the IOPL in the flags register. IOPL specifies the least
privileged level at which I/O can be performed. Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
#GP(0) as for Protected Mode
CLTS -- Clear Task-Switched Flag in CR0
Opcode | Instruction | Clocks |
Description | Example |
OF 06 | clts | 5 |
Clear task-switched flag | clts |
Operation
TS Flag in CR0 := 0;
Description CLTS clears the task-switched (TS) flag
in register CR0. This flag is set by the 80386 every time a task switch
occurs. The TS flag is used to manage processor extensions as follows:
- Every execution of an ESC instruction is trapped if the TS flag is set.
- Execution of a WAIT instruction is trapped if the MP flag and the TS flag are both set.
Thus, if a task switch was made after an ESC instruction was begun, the
processor extension's context may need to be saved before a new ESC
instruction can be issued. The fault handler saves the context and
resets the TS flag. CLTS appears in operating system software, not in application
programs. It is a privileged instruction that can only be executed at
privilege level 0. Flags Affected
TS := 0 (TS is in CR0, not the flag register)
Protected Mode Exceptions
#GP(0) if CLTS is executed with a current privilege level other than 0
Real Address Mode Exceptions
None (valid in Real Address Mode to allow initialization for Protected Mode)
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode
CMC -- Complement Carry Flag
Opcode | Instruction | Clocks |
Description | Example |
F5 | cmc | 2 |
Complement carry flag | cmc |
Operation
CF := NOT CF;
Description
CMC reverses the setting of the carry flag. No other flags are affected.
Flags Affected
CF as described above
Protected Mode Exceptions
None
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
CMP -- Compare Two Operands
Opcode | Instruction | Clocks |
Description | Example |
3C ib | cmpb imm8,al | 2 |
Compare immediate byte to AL | cmpb $0x7f,%al |
3D iw | cmpw imm16,ax | 2 |
Compare immediate word to AX | cmpw $0x7fff,%ax |
3D id | cmpl imm32,eax | 2 |
Compare immediate dword to EAX | cmpl $0x7fffffff,%eax |
80 /7 ib | cmpb imm8,r/m8 | 2/5 |
Compare immediate byte to r/m byte | cmpb $0x7f,%dl
cmpb $0x7f,(%ebx,1)
cmpb $0x7f,m8(%ebx,1)
cmpb $0x7f,m8(%ebx,%ebp,1) |
81 /7 iw | cmpw imm16,r/m16 | 2/5 |
Compare immediate word to r/m word | cmpw $0x7fff,%cx
cmpw $0x7fff,(%ebx,1)
cmpw $0x7fff,(%ebx,2)
cmpw $0x7fff,(%ebx,%ebp,1) |
81 /7 id | cmpl imm32,r/m32 | 2/5 |
Compare immediate dword to r/m dword | cmpl $0x7fffffff,%ecx
cmpl $0x7fffffff,(%ebx,2)
cmpl $0x7fffffff,(%ebx,4)
cmpl $0x7fffffff,(%ebx,%ebp,1) |
83 /7 ib | cmpw imm8,r/m16 | 2/5 |
Compare sign extended immediate byte to r/m word | cmpw $0x7f,%cx
cmpw $0x7f,(%ebx,1)
cmpw $0x7f,(%ebx,2)
cmpw $0x7f,(%ebx,%ebp,1) |
83 /7 ib | cmpl imm8,r/m32 | 2/5 |
Compare sign extended immediate byte to r/m dword | cmpl $0x7f,%ecx
cmpl $0x7f,(%ebx,2)
cmpl $0x7f,(%ebx,4)
cmpl $0x7f,(%ebx,%ebp,1) |
38 /r | cmpb r8,r/m8 | 2/5 |
Compare byte register to r/m byte | cmpb %bh,%dl
cmpb %bh,(%ebx,1)
cmpb %bh,m8(%ebx,1)
cmpb %bh,m8(%ebx,%ebp,1) |
39 /r | cmpw r16,r/m16 | 2/5 |
Compare word register to r/m word | cmpw %bx,%cx
cmpw %bx,(%ebx,1)
cmpw %bx,(%ebx,2)
cmpw %bx,(%ebx,%ebp,1) |
39 /r | cmpl r32,r/m32 | 2/5 |
Compare dword register to r/m dword | cmpl %ebx,%ecx
cmpl %ebx,(%ebx,2)
cmpl %ebx,(%ebx,4)
cmpl %ebx,(%ebx,%ebp,1) |
3A /r | cmpb r/m8,r8 | 2/6 |
Compare r/m byte to byte register | cmpb %dl,%bh
cmpb (%ebx,1),%bh
cmpb m8(%ebx,1),%bh
cmpb m8(%ebx,%ebp,1),%bh |
3B /r | cmpw r/m16,r16 | 2/6 |
Compare r/m word to word register | cmpw %cx,%bx
cmpw (%ebx,1),%bx
cmpw (%ebx,2),%bx
cmpw (%ebx,%ebp,1),%bx |
3B /r | cmpl r/m32,r32 | 2/6 |
Compare r/m dword to dword register | cmpl %ecx,%ebx
cmpl (%ebx,2),%ebx
cmpl (%ebx,4),%ebx
cmpl (%ebx,%ebp,1),%ebx |
Operation
LeftSRC - SignExtend(RightSRC);
(* CMP does not store a result; its purpose is to set the flags *)
Description
CMP subtracts the second operand from the first but, unlike the SUB
instruction, does not store the result; only the flags are changed. CMP
is typically used in conjunction with conditional jumps and the SETcc
instruction. (Refer to Appendix D for the list of signed and unsigned
flag tests provided.) If an operand greater than one byte is compared
to an immediate byte, the byte value is first sign-extended. Flags Affected
OF, SF, ZF, AF, PF, and CF as described in Appendix C
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 exceptions as in Real Address Mode; #PF(fault-code) for a page fault
CMPS/CMPSB/CMPSW/CMPSD -- Compare String Operands
Opcode | Instruction | Clocks |
Description | Example |
A6 | cmpsb | 10 |
Compare bytes ES:[(E)DI] with DS:[SI] | cmpsb |
A7 | cmpsw | 10 |
Compare words ES:[(E)DI] with DS:[SI] | cmpsw |
A7 | cmpsl | 10 |
Compare dwords ES:[(E)DI] with DS:[SI] | cmpsl |
Operation
IF (instruction = CMPSD) OR
(instruction has operands of type DWORD)
THEN OperandSize := 32;
ELSE OperandSize := 16;
FI;
IF AddressSize = 16
THEN
use SI for source-index and DI for destination-index
ELSE (* AddressSize = 32 *)
use ESI for source-index and EDI for destination-index;
FI;
IF byte type of instruction
THEN
[source-index] - [destination-index]; (* byte comparison *)
IF DF = 0 THEN IncDec := 1 ELSE IncDec := -1; FI;
ELSE
IF OperandSize = 16
THEN
[source-index] - [destination-index]; (* word comparison *)
IF DF = 0 THEN IncDec := 2 ELSE IncDec := -2; FI;
ELSE (* OperandSize = 32 *)
[source-index] - [destination-index]; (* dword comparison *)
IF DF = 0 THEN IncDec := 4 ELSE IncDec := -4; FI;
FI;
FI;
source-index := source-index + IncDec;
destination-index := destination-index + IncDec;
Description CMPS compares the byte, word, or
doubleword pointed to by the source-index register with the byte, word,
or doubleword pointed to by the destination-index register. If the address-size attribute of this instruction is 16 bits, SI
and DI will be used for source- and destination-index registers;
otherwise ESI and EDI will be used. Load the correct index values into
SI and DI (or ESI and EDI) before executing CMPS. The comparison is done by subtracting the operand indexed by
the destination-index register from the operand indexed by the
source-index register. Note that the direction of subtraction for CMPS is [SI] -
[DI] or [ESI] - [EDI]. The left operand (SI or ESI) is the source and
the right operand (DI or EDI) is the destination. This is the reverse
of the usual Intel convention in which the left operand is the
destination and the right operand is the source. The result of the subtraction is not stored; only the flags
reflect the change. The types of the operands determine whether bytes,
words, or doublewords are compared. For the first operand (SI or ESI),
the DS register is used, unless a segment override byte is present. The
second operand (DI or EDI) must be addressable from the ES register; no
segment override is possible. After the comparison is made, both the source-index register
and destination-index register are automatically advanced. If the
direction flag is 0 (CLD was executed), the registers increment; if the direction flag is 1 (STD
was executed), the registers decrement. The registers increment or
decrement by 1 if a byte is compared, by 2 if a word is compared, or by
4 if a doubleword is compared. CMPSB, CMPSW and CMPSD are synonyms for the byte, word, and doubleword CMPS instructions, respectively.
CMPS can be preceded by the REPE or REPNE prefix for block comparison of CX or ECX bytes, words, or doublewords. Refer to the description of the REP instruction for more information on this operation.
Flags Affected
OF, SF, ZF, AF, PF, and CF as described in Appendix C
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 exceptions as in Real Address Mode; #PF (fault-code) for a page fault
CWD/CDQ -- Convert Word to Doubleword/Convert Doubleword to Quadword
Opcode | Instruction | Clocks |
Description | Example |
99 | cwd | 2 |
DX:AX := sign-extend of AX | cwd |
99 | cdq | 2 |
EDX:EAX := sign-extend of EAX | cdq |
Operation
IF OperandSize = 16 (* CWD instruction *)
THEN
IF AX < 0 THEN DX := 0FFFFH; ELSE DX := 0; FI;
ELSE (* OperandSize = 32, CDQ instruction *)
IF EAX < 0 THEN EDX := 0FFFFFFFFH; ELSE EDX := 0; FI;
FI;
Description CWD converts the signed word in AX to a
signed doubleword in DX:AX by extending the most significant bit of AX
into all the bits of DX. CDQ converts the signed doubleword in EAX to a
signed 64-bit integer in the register pair EDX:EAX by extending the
most significant bit of EAX (the sign bit) into all the bits of EDX.
Note that CWD is different from CWDE. CWDE uses EAX as a destination,
instead of DX:AX. Flags Affected
None
DAA -- Decimal Adjust AL after Addition
Opcode | Instruction | Clocks |
Description | Example |
27 | daa | 4 |
Decimal adjust AL after addition | daa |
Operation
IF ((AL AND 0FH) > 9) OR (AF = 1)
THEN
AL := AL + 6;
AF := 1;
ELSE
AF := 0;
FI;
IF (AL > 9FH) OR (CF = 1)
THEN
AL := AL + 60H;
CF := 1;
ELSE CF := 0;
FI;
Description
Execute DAA only after executing an ADD instruction that leaves a two-BCD-digit byte result in the AL register. The ADD
operands should consist of two packed BCD digits. The DAA instruction
adjusts AL to contain the correct two-digit packed decimal result. Flags Affected
AF and CF as described above; SF, ZF, PF, and CF as described in Appendix C.
DAS -- Decimal Adjust AL after Subtraction
Opcode | Instruction | Clocks |
Description | Example |
2F | das | 4 |
Decimal adjust AL after subtraction | das |
Operation
IF (AL AND 0FH) > 9 OR AF = 1
THEN
AL := AL - 6;
AF := 1;
ELSE
AF := 0;
FI;
IF (AL > 9FH) OR (CF = 1)
THEN
AL := AL - 60H;
CF := 1;
ELSE CF := 0;
FI;
Description Execute DAS only after a subtraction
instruction that leaves a two-BCD-digit byte result in the AL register.
The operands should consist of two packed BCD digits. DAS adjusts AL to
contain the correct packed two-digit decimal result. Flags Affected
AF and CF as described above; SF, ZF, and PF as described in Appendix C.
DEC -- Decrement by 1
Opcode | Instruction | Clocks |
Description | Example |
FE /1 | decb r/m8 | 2/6 |
Decrement r/m byte by 1 | decb %dl
decb (%ebx,1)
decb m8(%ebx,1)
decb m8(%ebx,%ebp,1) |
FF /1 | decw r/m16 | 2/6 |
Decrement r/m word by 1 Decrement r/m dword by 1 | decw %cx
decw (%ebx,1)
decw (%ebx,2)
decw (%ebx,%ebp,1) |
48+rw | decw r16 | 2 |
Decrement word register by 1 | decw %bx |
48+rw | decl r32 | 2 |
Decrement dword register by 1 | decl %ebx |
Operation
DEST := DEST - 1;
Description
DEC subtracts 1 from the operand. DEC does not change the carry flag. To affect the carry flag, use the SUB instruction with an immediate operand of 1.
Flags Affected
OF, SF, ZF, AF, and PF as described in Appendix C.
Protected Mode Exceptions
#GP(0) if the result is 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
DIV -- Unsigned Divide
Opcode | Instruction | Clocks |
Description | Example |
F6 /6 | divb r/m8,al | 14/17 |
Unsigned divide AX by r/m byte (AL=Quo, AH=Rem) | divb %dl,%al
divb (%ebx,1),%al
divb m8(%ebx,1),%al
divb m8(%ebx,%ebp,1),%al |
F7 /6 | divw r/m16,ax | 22/25 |
Unsigned divide DX:AX by r/m word (AX=Quo, DX=Rem) | divw %cx,%ax
divw (%ebx,1),%ax
divw (%ebx,2),%ax
divw (%ebx,%ebp,1),%ax |
F7 /6 | divl r/m32,eax | 38/41 |
Unsigned divide EDX:EAX by r/m dword (EAX=Quo, EDX=Rem) | divl %ecx,%eax
divl (%ebx,2),%eax
divl (%ebx,4),%eax
divl (%ebx,%ebp,1),%eax |
Operation
temp := dividend / divisor;
IF temp does not fit in quotient
THEN Interrupt 0;
ELSE
quotient := temp;
remainder := dividend MOD (r/m);
FI;
Note Divisions are unsigned. The divisor is
given by the r/m operand. The dividend, quotient, and remainder use
implicit registers. Refer to the table under "Description"
Description
DIV performs an unsigned division. The dividend is implicit; only the
divisor is given as an operand. The remainder is always less than the
divisor. The type of the divisor determines which registers to use as
follows:
Size Dividend Divisor Quotient Remainder
byte AX r/m8 AL AH
word DX:AX r/m16 AX DX
dword EDX:EAX r/m32 EAX EDX
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, AX, or EAX), 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 big to fit in the designated register (AL, AX, or EAX), 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
ENTER -- Make Stack Frame for Procedure Parameters
Opcode | Instruction | Clocks |
Description | Example |
C8 iw 00 | enterw imm16,0 | 10 |
Make procedure stack frame | enterw $0x7fff,$0 |
C8 iw 01 | enterw imm16,1 | 12 |
Make stack frame for procedure parameters | enterw $0x7fff,$1 |
C8 iw ib | enterw imm16,imm8 | 15+4(n-1) |
Make stack frame for procedure parameters | enterw $0x7fff,$0x7f |
Operation
level := level MOD 32
IF OperandSize = 16 THEN Push(BP) ELSE Push (EBP) FI;
(* Save stack pointer *)
frame-ptr := eSP
IF level > 0
THEN (* level is rightmost parameter *)
FOR i := 1 TO level - 1
DO
IF OperandSize = 16
THEN
BP := BP - 2;
Push[BP]
ELSE (* OperandSize = 32 *)
EBP := EBP - 4;
Push[EBP];
FI;
OD;
Push(frame-ptr)
FI;
IF OperandSize = 16 THEN BP := frame-ptr ELSE EBP := frame-ptr; FI;
IF StackAddrSize = 16
THEN SP := SP - First operand;
ELSE ESP := ESP - ZeroExtend(First operand);
FI;
Description ENTER creates the stack frame required by
most block-structured high-level languages. The first operand specifies
the number of bytes of dynamic storage allocated on the stack for the
routine being entered. The second operand gives the lexical nesting
level (0 to 31) of the routine within the high-level language source
code. It determines the number of stack frame pointers copied into the
new stack frame from the preceding frame. BP (or EBP, if the
operand-size attribute is 32 bits) is the current stack frame pointer. If the operand-size attribute is 16 bits, the processor uses BP
as the frame pointer and SP as the stack pointer. If the operand-size
attribute is 32 bits, the processor uses EBP for the frame pointer and
ESP for the stack pointer. If the second operand is 0, ENTER pushes the frame pointer
(BP or EBP) onto the stack; ENTER then subtracts the first operand from
the stack pointer and sets the frame pointer to the current
stack-pointer value. For example, a procedure with 12 bytes of local variables would have an ENTER 12,0 instruction at its entry point and a LEAVE instruction before every RET. The 12 local bytes would be addressed as negative offsets from the frame pointer.
Flags Affected
None
Protected Mode Exceptions
#SS(0) if SP or ESP would exceed the stack limit at any point during instruction execution; #PF(fault-code) for a page fault
HLT -- Halt
Opcode | Instruction | Clocks |
Description | Example |
F4 | hlt | 5 |
Halt | hlt |
Operation
Enter Halt state;
Description
HALT stops instruction execution and places the 80386 in a HALT state.
An enabled interrupt, NMI, or a reset will resume execution. If an
interrupt (including NMI) is used to resume execution after HLT, the
saved CS:IP (or CS:EIP) value points to the instruction following HLT. Flags Affected
None
Protected Mode Exceptions
HLT is a privileged instruction; #GP(0) if the current privilege level is not 0
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
#GP(0); HLT is a privileged instruction
IDIV -- Signed Divide
Opcode | Instruction | Clocks |
Description | Example |
F6 /7 | idivb r/m8 | 19 |
Signed divide AX by r/m byte (AL=Quo, AH=Rem) | idivb %dl
idivb (%ebx,1)
idivb m8(%ebx,1)
idivb m8(%ebx,%ebp,1) |
F7 /7 | idivw r/m16,ax | 27 |
Signed divide DX:AX by EA word (AX=Quo, DX=Rem) | idivw %cx,%ax
idivw (%ebx,1),%ax
idivw (%ebx,2),%ax
idivw (%ebx,%ebp,1),%ax |
F7 /7 | idivl r/m32,eax | 43 |
Signed divide EDX:EAX by DWORD byte (EAX=Quo, EDX=Rem) | idivl %ecx,%eax
idivl (%ebx,2),%eax
idivl (%ebx,4),%eax
idivl (%ebx,%ebp,1),%eax |
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: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. 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
IMUL -- Signed Multiply
Opcode | Instruction | Clocks |
Description | Example |
F6 /5 | imulb r/m8 | 9-14/12-17 |
AX= AL * r/m byte | imulb %dl
imulb (%ebx,1)
imulb m8(%ebx,1)
imulb m8(%ebx,%ebp,1) |
F7 /5 | imulw r/m16 | 9-22/12-25 |
DX:AX := AX * r/m word | imulw %cx
imulw (%ebx,1)
imulw (%ebx,2)
imulw (%ebx,%ebp,1) |
F7 /5 | imull r/m32 | 9-38/12-41 |
EDX:EAX := EAX * r/m dword | imull %ecx
imull (%ebx,2)
imull (%ebx,4)
imull (%ebx,%ebp,1) |
0F AF /r | imulw r/m16,r16 | 9-22/12-25 |
word register := word register * r/m word | imulw %cx,%bx
imulw (%ebx,1),%bx
imulw (%ebx,2),%bx
imulw (%ebx,%ebp,1),%bx |
0F AF /r | imull r/m32,r32 | 9-38/12-41 |
dword register := dword register * r/m dword | imull %ecx,%ebx
imull (%ebx,2),%ebx
imull (%ebx,4),%ebx
imull (%ebx,%ebp,1),%ebx |
6B /r ib | imulw r/m16,r16 | 9-14/12-17 |
word register := r/m16 * sign-extended immediate byte | imulw %cx,%bx
imulw (%ebx,1),%bx
imulw (%ebx,2),%bx
imulw (%ebx,%ebp,1),%bx |
6B /r ib | imull r/m32,r32 | 9-14/12-17 |
dword register := r/m32 * sign-extended immediate byte | imull %ecx,%ebx
imull (%ebx,2),%ebx
imull (%ebx,4),%ebx
imull (%ebx,%ebp,1),%ebx |
6B /r ib | imulw imm8,r16 | 9-14/12-17 |
word register := word register * sign-extended immediate byte | imulw $0x7f,%bx |
6B /r ib | imull imm8,r32 | 9-14/12-17 |
dword register := dword register * sign-extended immediate byte | imull $0x7f,%ebx |
69 /r iw | imulw r/m16,r16 | 9-22/12-25 |
word register := r/m16 * immediate word | imulw %cx,%bx
imulw (%ebx,1),%bx
imulw (%ebx,2),%bx
imulw (%ebx,%ebp,1),%bx |
69 /r id | imull r/m32,r32 | 9-38/12-41 |
dword register := r/m32 * immediate dword | imull %ecx,%ebx
imull (%ebx,2),%ebx
imull (%ebx,4),%ebx
imull (%ebx,%ebp,1),%ebx |
69 /r iw | imulw imm16,r16 | 9-22/12-25 |
word register := r/m16 * immediate word | imulw $0x7fff,%bx |
69 /r id | imull imm32,r32 | 9-38/12-41 |
dword register := r/m32 * immediate dword | imull $0x7fffffff,%ebx |
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 r32
Flags 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.
IN -- Input from Port
Opcode | Instruction | Clocks |
Description | Example |
E4 ib | inb imm8,al | 12,pm=6*/26** |
Input byte from immediate port into AL | inb $0x7f,%al |
E5 ib | inw imm8,ax | 12,pm=6*/26** |
Input word from immediate port into AX | inw $0x7f,%ax |
E5 ib | inl imm8,eax | 12,pm=6*/26** |
Input dword from immediate port into EAX | inl $0x7f,%eax |
EC | inb dx,al | 13,pm=7*/27** |
Input byte from port DX into AL | inb %dx,%al |
ED | inw dx,ax | 13,pm=7*/27** |
Input word from port DX into AX | inw %dx,%ax |
ED | inl dx,eax | 13,pm=7*/27** |
Input dword from port DX into EAX | inl %dx,%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
INC -- Increment by 1
Opcode | Instruction | Clocks |
Description | Example |
FE /0 | incb r/m8 | |
Increment r/m byte by 1 | incb %dl
incb (%ebx,1)
incb m8(%ebx,1)
incb m8(%ebx,%ebp,1) |
FF /0 | incw r/m16 | |
Increment r/m word by 1 | incw %cx
incw (%ebx,1)
incw (%ebx,2)
incw (%ebx,%ebp,1) |
FF /6 | incl r/m32 | |
Increment r/m dword by 1 | incl %ecx
incl (%ebx,2)
incl (%ebx,4)
incl (%ebx,%ebp,1) |
40 + rw | incw r16 | |
Increment word register by 1 | incw %bx |
40 + rd | incl r32 | |
Increment dword register by 1 | incl %ebx |
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
INS/INSB/INSW/INSD -- Input from Port to String
Opcode | Instruction | Clocks |
Description | Example |
6C | insb | 15,pm=9*/29** |
Input byte from port DX into ES:(E)DI | insb |
6D | insw | 15,pm=9*/29** |
Input word from port DX into ES:(E)DI | insw |
6D | insl | 15,pm=9*/29** |
Input dword from port DX into ES:(E)DI | insl |
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
INT/INTO -- Call to Interrupt Procedure
Opcode | Instruction | Clocks |
Description | Example |
CC | | 33 |
Interrupt 3--trap to debugger | |
CC | | pm=59 |
Interrupt 3--Protected Mode, same privilege | |
CC | | pm=99 |
Interrupt 3--Protected Mode, more privilege | |
CC | | pm=119 |
Interrupt 3--from V86 mode to PL 0 | |
CC | | ts |
Interrupt 3--Protected Mode, via task gate | |
CD ib | int imm8 | 37 |
Interrupt numbered by immediate byte | int $0x7f |
CD ib | int imm8 | pm=59 |
Interrupt--Protected Mode, same privilege | int $0x7f |
CD ib | int imm8 | pm=99 |
Interrupt--Protected Mode, more privilege | int $0x7f |
CD ib | int imm8 | pm=119 |
Interrupt--from V86 mode to PL 0 | int $0x7f |
CD ib | int imm8 | ts |
Interrupt--Protected Mode, via task gate | int $0x7f |
CE | into | Fail:3,pm=3 |
| into |
CE | into | pm=59 |
Interrupt 4--Protected Mode, same privilege | into |
CE | into | pm=99 |
Interrupt 4--Protected Mode, more privilege | into |
CE | into | pm=119 |
Interrupt 4--from V86 mode to PL 0 | into |
CE | into | ts |
Interrupt 4--Protected Mode, via task gate | into |
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);
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
IRET/IRETD -- Interrupt Return
Opcode | Instruction | Clocks |
Description | Example |
CF | iret | 22,pm=38 |
Interrupt return (far return and pop flags) | iret |
CF | iret | pm=82 |
Interrupt return to lesser privilege | iret |
CF | iret | ts |
Interrupt return, different task (NT = 1) | iret |
CF | iretl | 22,pm=38 |
Interrupt return (far return and pop flags) | iretl |
CF | iretl | pm=82 |
Interrupt return to lesser privilege | iretl |
CF | iretl | pm=60 |
Interrupt return to V86 mode | iretl |
CF | iretl | ts |
Interrupt return, different task (NT = 1) | iretl |
NoteValues 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 >= 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
Jcc -- Jump if Condition is Met
Opcode | Instruction | Clocks |
Description | Example |
77 cb | ja rel8 | 7+m,3 |
Jump short if above (CF=0 and ZF=0) | ja rel8_0 |
73 cb | jae rel8 | 7+m,3 |
Jump short if above or equal (CF=0) | jae rel8_1 |
72 cb | jb rel8 | 7+m,3 |
Jump short if below (CF=1) | jb rel8_2 |
76 cb | jbe rel8 | 7+m,3 |
Jump short if below or equal (CF=1 or ZF=1) | jbe rel8_3 |
72 cb | jc rel8 | 7+m,3 |
Jump short if carry (CF=1) | jc rel8_4 |
E3 cb | jcxz rel8 | 9+m,5 |
Jump short if CX register is 0 | jcxz rel8_5 |
E3 cb | jecxz rel8 | 9+m,5 |
Jump short if ECX register is 0 | jecxz rel8_6 |
74 cb | je rel8 | 7+m,3 |
Jump short if equal (ZF=1) | je rel8_7 |
74 cb | jz rel8 | 7+m,3 |
Jump short if 0 (ZF=1) | jz rel8_8 |
7F cb | jg rel8 | 7+m,3 |
Jump short if greater (ZF=0 and SF=OF) | jg rel8_9 |
7D cb | jge rel8 | 7+m,3 |
Jump short if greater or equal (SF=OF) | jge rel8_10 |
7C cb | jl rel8 | 7+m,3 |
Jump short if less (SF< | jl rel8_11 |
7E cb | jle rel8 | 7+m,3 |
Jump short if less or equal (ZF=1 and SF< | jle rel8_12 |
76 cb | jna rel8 | 7+m,3 |
Jump short if not above (CF=1 or ZF=1) | jna rel8_13 |
72 cb | jnae rel8 | 7+m,3 |
Jump short if not above or equal (CF=1) | jnae rel8_14 |
73 cb | jnb rel8 | 7+m,3 |
Jump short if not below (CF=0) | jnb rel8_15 |
77 cb | jnbe rel8 | 7+m,3 |
Jump short if not below or equal (CF=0 and ZF=0) | jnbe rel8_16 |
73 cb | jnc rel8 | 7+m,3 |
Jump short if not carry (CF=0) | jnc rel8_17 |
75 cb | jne rel8 | 7+m,3 |
Jump short if not equal (ZF=0) | jne rel8_18 |
7E cb | jng rel8 | 7+m,3 |
Jump short if not greater (ZF=1 or SF< | jng rel8_19 |
7C cb | jnge rel8 | 7+m,3 |
Jump short if not greater or equal (SF< | jnge rel8_20 |
7D cb | jnl rel8 | 7+m,3 |
Jump short if not less (SF=OF) | jnl rel8_21 |
7F cb | jnle rel8 | 7+m,3 |
Jump short if not less or equal (ZF=0 and SF=OF) | jnle rel8_22 |
71 cb | jno rel8 | 7+m,3 |
Jump short if not overflow (OF=0) | jno rel8_23 |
7B cb | jnp rel8 | 7+m,3 |
Jump short if not parity (PF=0) | jnp rel8_24 |
79 cb | jns rel8 | 7+m,3 |
Jump short if not sign (SF=0) | jns rel8_25 |
75 cb | jnz rel8 | 7+m,3 |
Jump short if not zero (ZF=0) | jnz rel8_26 |
70 cb | jo rel8 | 7+m,3 |
Jump short if overflow (OF=1) | jo rel8_27 |
7A cb | jp rel8 | 7+m,3 |
Jump short if parity (PF=1) | jp rel8_28 |
7A cb | jpe rel8 | 7+m,3 |
Jump short if parity even (PF=1) | jpe rel8_29 |
7B cb | jpo rel8 | 7+m,3 |
Jump short if parity odd (PF=0) | jpo rel8_30 |
78 cb | js rel8 | 7+m,3 |
Jump short if sign (SF=1) | js rel8_31 |
74 cb | jz rel8 | 7+m,3 |
Jump short if zero (ZF = 1) | jz rel8_32 |
0F 87 cw/cd | ja rel16/32 | 7+m,3 |
Jump near if above (CF=0 and ZF=0) | ja rel16 |
0F 83 cw/cd | jae rel16/32 | 7+m,3 |
Jump near if above or equal (CF=0) | jae rel16 |
0F 82 cw/cd | jb rel16/32 | 7+m,3 |
Jump near if below (CF=1) | jb rel16 |
0F 86 cw/cd | jbe rel16/32 | 7+m,3 |
Jump near if below or equal (CF=1 or ZF=1) | jbe rel16 |
0F 82 cw/cd | jc rel16/32 | 7+m,3 |
Jump near if carry (CF=1) | jc rel16 |
0F 84 cw/cd | je rel16/32 | 7+m,3 |
Jump near if equal (ZF=1) | je rel16 |
0F 84 cw/cd | jz rel16/32 | 7+m,3 |
Jump near if 0 (ZF=1) | jz rel16 |
0F 8F cw/cd | jg rel16/32 | 7+m,3 |
Jump near if greater (ZF=0 and SF=OF) | jg rel16 |
0F 8D cw/cd | jge rel16/32 | 7+m,3 |
Jump near if greater or equal (SF=OF) | jge rel16 |
0F 8C cw/cd | jl rel16/32 | 7+m,3 |
Jump near if less (SF< | jl rel16 |
0F 8E cw/cd | jle rel16/32 | 7+m,3 |
Jump near if less or equal (ZF=1 and SF< | jle rel16 |
0F 86 cw/cd | jna rel16/32 | 7+m,3 |
Jump near if not above (CF=1 or ZF=1) | jna rel16 |
0F 82 cw/cd | jnae rel16/32 | 7+m,3 |
Jump near if not above or equal (CF=1) | jnae rel16 |
0F 83 cw/cd | jnb rel16/32 | 7+m,3 |
Jump near if not below (CF=0) | jnb rel16 |
0F 87 cw/cd | jnbe rel16/32 | 7+m,3 |
Jump near if not below or equal (CF=0 and ZF=0) | jnbe rel16 |
0F 83 cw/cd | jnc rel16/32 | 7+m,3 |
Jump near if not carry (CF=0) | jnc rel16 |
0F 85 cw/cd | jne rel16/32 | 7+m,3 |
Jump near if not equal (ZF=0) | jne rel16 |
0F 8E cw/cd | jng rel16/32 | 7+m,3 |
Jump near if not greater (ZF=1 or SF< | jng rel16 |
0F 8C cw/cd | jnge rel16/32 | 7+m,3 |
Jump near if not greater or equal (SF< | jnge rel16 |
0F 8D cw/cd | jnl rel16/32 | 7+m,3 |
Jump near if not less (SF=OF) | jnl rel16 |
0F 8F cw/cd | jnle rel16/32 | 7+m,3 |
Jump near if not less or equal (ZF=0 and SF=OF) | jnle rel16 |
0F 81 cw/cd | jno rel16/32 | 7+m,3 |
Jump near if not overflow (OF=0) | jno rel16 |
0F 8B cw/cd | jnp rel16/32 | 7+m,3 |
Jump near if not parity (PF=0) | jnp rel16 |
0F 89 cw/cd | jns rel16/32 | 7+m,3 |
Jump near if not sign (SF=0) | jns rel16 |
0F 85 cw/cd | jnz rel16/32 | 7+m,3 |
Jump near if not zero (ZF=0) | jnz rel16 |
0F 80 cw/cd | jo rel16/32 | 7+m,3 |
Jump near if overflow (OF=1) | jo rel16 |
0F 8A cw/cd | jp rel16/32 | 7+m,3 |
Jump near if parity (PF=1) | jp rel16 |
0F 8A cw/cd | jpe rel16/32 | 7+m,3 |
Jump near if parity even (PF=1) | jpe rel16 |
0F 8B cw/cd | jpo rel16/32 | 7+m,3 |
Jump near if parity odd (PF=0) | jpo rel16 |
0F 88 cw/cd | js rel16/32 | 7+m,3 |
Jump near if sign (SF=1) | js rel16 |
0F 84 cw/cd | jz rel16/32 | 7+m,3 |
Jump near if 0 (ZF=1) | jz rel16 |
Notes The first clock count is for
the true condition (branch taken); the second clock count is for the
false condition (branch not taken). rel16/32 indicates that these
instructions map to two; one with a 16-bit relative displacement, the
other with a 32-bit relative displacement, depending on the
operand-size attribute of the instruction.
Operation
IF condition
THEN
EIP := EIP + SignExtend(rel8/16/32);
IF OperandSize = 16
THEN EIP := EIP AND 0000FFFFH;
FI;
FI;
Description Conditional jumps (except JCXZ) test the
flags which have been set by a previous instruction. The conditions for
each mnemonic are given in parentheses after each description above.
The terms "less" and "greater" are used for comparisons of signed
integers; "above" and "below" are used for unsigned integers. If the given condition is true, a jump is made to the location
provided as the operand. Instruction coding is most efficient when the
target for the conditional jump is in the current code segment and
within -128 to +127 bytes of the next instruction's first byte. The
jump can also target -32768 thru +32767 (segment size attribute 16) or
-2^(31) thru +2^(31) -1 (segment size attribute 32) relative to the
next instruction's first byte. When the target for the conditional jump
is in a different segment, use the opposite case of the jump
instruction (i.e., JE and JNE), and then access the target with an
unconditional far jump to the other segment. For example, you cannot
code--
JZ FARLABEL;
You must instead code--
JNZ BEYOND;
JMP FARLABEL;
BEYOND:
Because there can be several ways to interpret a particular
state of the flags, ASM386 provides more than one mnemonic for most of
the conditional jump opcodes. For example, if you compared two
characters in AX and want to jump if they are equal, use JE; or, if you
ANDed AX with a bit field mask and only want to jump if the result is
0, use JZ, a synonym for JE. JCXZ differs from other conditional jumps because it tests the
contents of the CX or ECX register for 0, not the flags. JCXZ is useful
at the beginning of a conditional loop that terminates with a
conditional loop instruction (such as LOOPNE
TARGET LABEL). The JCXZ prevents entering the loop with CX or ECX equal
to zero, which would cause the loop to execute 64K or 32G times instead
of zero times. Flags Affected
None
Protected Mode Exceptions
#GP(0) if the offset jumped to is beyond the limits of the code segment
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
JMP -- Jump
Opcode | Instruction | Clocks |
Description | Example |
EB cb | jmp rel8 | 7+m |
Jump short | jmp rel8_33 |
E9 cw | jmp rel16 | 7+m |
Jump near, displacement relative to next instruction | jmp rel16 |
FF /4 | jmpw r/m16 | 7+m/10+m |
Jump near indirect | jmpw *%cx
jmpw *(%ebx,1)
jmpw (%ebx,2)
jmpw (%ebx,%ebp,1) |
EA cd | jmpw ptr16:16 | 12+m,pm=27+m |
Jump intersegment, 4-byte immediate address | jmpw *(%ebx,1) |
EA cd | jmpw ptr16:16 | pm=45+m |
Jump to call gate, same privilege | jmpw *(%ebx,1) |
EA cd | jmpw ptr16:16 | ts |
Jump via task state segment | jmpw *(%ebx,1) |
EA cd | jmpw ptr16:16 | ts |
Jump via task gate | jmpw *(%ebx,1) |
FF /5 | jmpw m16:16 | 43+m,pm=31+m |
Jump r/m16:16 indirect and intersegment | jmp tocall |
FF /5 | jmpw m16:16 | pm=49+m |
Jump to call gate, same privilege | jmp tocall |
FF /5 | jmpw m16:16 | 5 + ts |
Jump via task state segment | jmp tocall |
FF /5 | jmpw m16:16 | 5 + ts |
Jump via task gate | jmp tocall |
E9 cd | jmp rel32 | 7+m |
Jump near, displacement relative to next instruction | jmp rel32 |
FF /4 | jmpl r/m32 | 7+m,10+m |
Jump near, indirect | jmpl *%ecx
jmpl *(%ebx,2)
jmpl (%ebx,4)
jmpl (%ebx,%ebp,1) |
EA cp | jmpw ptr16:32 | 12+m,pm=27+m |
Jump intersegment, 6-byte immediate address | jmpw *(%ebx,1) |
EA cp | jmpw ptr16:32 | pm=45+m |
Jump to call gate, same privilege | jmpw *(%ebx,1) |
EA cp | jmpw ptr16:32 | ts |
Jump via task state segment | jmpw *(%ebx,1) |
EA cp | jmpw ptr16:32 | ts |
Jump via task gate | jmpw *(%ebx,1) |
FF /5 | jmpw m16:32 | 43+m,pm=31+m |
Jump intersegment, address at r/m dword | jmp tocall |
FF /5 | jmpw m16:32 | pm=49+m |
Jump to call gate, same privilege | jmp tocall |
FF /5 | jmpw m16:32 | 5 + ts |
Jump via task state segment | jmp tocall |
FF /5 | jmpw m16:32 | 5 + ts |
Jump via task gate | jmp tocall |
Note
Values of ts are given by the following table:
New Task
386 TSS 386 TASK 286 TSS
VM = 0 VM = 1
Old Task Via Task Gate?
N Y N Y N Y
386
TSS VM=0 303 312 220 229 276 285
286
TSS 301 310 218 227 274 283
Operation
IF instruction = relative JMP
(* i.e. operand is rel8, rel16, or rel32 *)
THEN
EIP := EIP + rel8/16/32;
IF OperandSize = 16
THEN EIP := EIP AND 0000FFFFH;
FI;
FI;
IF instruction = near indirect JMP
(* i.e. operand is r/m16 or r/m32 *)
THEN
IF OperandSize = 16
THEN
EIP := [r/m16] AND 0000FFFFH;
ELSE (* OperandSize = 32 *)
EIP := [r/m32];
FI;
FI;
IF (PE = 0 OR (PE = 1 AND VM = 1)) (* real mode or V86 mode *)
AND instruction = far JMP
(* i.e., operand type is m16:16, m16:32, ptr16:16, ptr16:32 *)
THEN GOTO REAL-OR-V86-MODE;
IF operand type = m16:16 or m16:32
THEN (* indirect *)
IF OperandSize = 16
THEN
CS:IP := [m16:16];
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := [m16:32];
FI;
FI;
IF operand type = ptr16:16 or ptr16:32
THEN
IF OperandSize = 16
THEN
CS:IP := ptr16:16;
EIP := EIP AND 0000FFFFH; (* clear upper 16 bits *)
ELSE (* OperandSize = 32 *)
CS:EIP := ptr16:32;
FI;
FI;
FI;
IF (PE = 1 AND VM = 0) (* Protected mode, not V86 mode *)
AND instruction = far JMP
THEN
IF operand type = m16:16 or m16:32
THEN (* indirect *)
check access of EA dword;
#GP(0) or #SS(0) IF limit violation;
FI;
Destination selector is not null ELSE #GP(0)
Destination selector index is within its descriptor table limits ELSE
#GP(selector)
Depending on AR byte of destination descriptor:
GOTO CONFORMING-CODE-SEGMENT;
GOTO NONCONFORMING-CODE-SEGMENT;
GOTO CALL-GATE;
GOTO TASK-GATE;
GOTO TASK-STATE-SEGMENT;
ELSE #GP(selector); (* illegal AR byte in descriptor *)
FI;
CONFORMING-CODE-SEGMENT:
Descriptor DPL must be <= CPL ELSE #GP(selector);
Segment must be present ELSE #NP(selector);
Instruction pointer must be within code-segment limit ELSE #GP(0);
IF OperandSize = 32
THEN Load CS:EIP from destination pointer;
ELSE Load CS:IP from destination pointer;
FI;
Load CS register with new segment descriptor;
NONCONFORMING-CODE-SEGMENT:
RPL of destination selector must be <= CPL ELSE #GP(selector);
Descriptor DPL must be = CPL ELSE #GP(selector);
Segment must be present ELSE # NP(selector);
Instruction pointer must be within code-segment limit ELSE #GP(0);
IF OperandSize = 32
THEN Load CS:EIP from destination pointer;
ELSE Load CS:IP from destination pointer;
FI;
Load CS register with new segment descriptor;
Set RPL field of CS register to CPL;
CALL-GATE:
Descriptor DPL must be >= CPL ELSE #GP(gate selector);
Descriptor DPL must be >= gate selector RPL ELSE #GP(gate selector);
Gate must be present ELSE #NP(gate selector);
Examine selector to code segment given in call gate descriptor:
Selector must not be null ELSE #GP(0);
Selector must be within its descriptor table limits ELSE
#GP(CS selector);
Descriptor AR byte must indicate code segment
ELSE #GP(CS selector);
IF non-conforming
THEN code-segment descriptor, DPL must = CPL
ELSE #GP(CS selector);
FI;
IF conforming
THEN code-segment descriptor DPL must be <= CPL;
ELSE #GP(CS selector);
Code segment must be present ELSE #NP(CS selector);
Instruction pointer must be within code-segment limit ELSE #GP(0);
IF OperandSize = 32
THEN Load CS:EIP from call gate;
ELSE Load CS:IP from call gate;
FI;
Load CS register with new code-segment descriptor;
Set RPL of CS to CPL
TASK-GATE:
Gate descriptor DPL must be >= CPL ELSE #GP(gate selector);
Gate descriptor DPL must be >= gate selector RPL ELSE #GP(gate
selector);
Task Gate must be present ELSE #NP(gate selector);
Examine selector to TSS, given in Task Gate descriptor:
Must specify global in the local/global bit ELSE #GP(TSS selector);
Index must be within GDT limits ELSE #GP(TSS selector);
Descriptor AR byte must specify available TSS (bottom bits 00001);
ELSE #GP(TSS selector);
Task State Segment must be present ELSE #NP(TSS selector);
SWITCH-TASKS (without nesting) to TSS;
Instruction pointer must be within code-segment limit ELSE #GP(0);
TASK-STATE-SEGMENT:
TSS DPL must be >= CPL ELSE #GP(TSS selector);
TSS DPL must be >= TSS selector RPL ELSE #GP(TSS selector);
Descriptor AR byte must specify available TSS (bottom bits 00001)
ELSE #GP(TSS selector);
Task State Segment must be present ELSE #NP(TSS selector);
SWITCH-TASKS (without nesting) to TSS;
Instruction pointer must be within code-segment limit ELSE #GP(0);
Description
The JMP instruction transfers control to a different point in the instruction stream without recording return information.
The action of the various forms of the instruction are shown below.
Jumps
with destinations of type r/m16, r/m32, rel16, and rel32 are near jumps
and do not involve changing the segment register value. The JMP rel16 and JMP rel32 forms of the instruction add an
offset to the address of the instruction following the JMP to determine
the destination. The rel16 form is used when the instruction's
operand-size attribute is 16 bits (segment size attribute 16 only);
rel32 is used when the operand-size attribute is 32 bits (segment size
attribute 32 only). The result is stored in the 32-bit EIP register.
With rel16, the upper 16 bits of EIP are cleared, which results in an
offset whose value does not exceed 16 bits. JMP r/m16 and JMP r/m32 specifies a register or memory
location from which the absolute offset from the procedure is fetched.
The offset fetched from r/m is 32 bits for an operand-size attribute of
32 bits (r/m32), or 16 bits for an operand-size attribute of 16 bits
(r/m16). The JMP ptr16:16 and ptr16:32 forms of the instruction use a
four-byte or six-byte operand as a long pointer to the destination. The
JMP and forms fetch the long pointer from the memory location specified
(indirection). In Real Address Mode or Virtual 8086 Mode, the long
pointer provides 16 bits for the CS register and 16 or 32 bits for the
EIP register (depending on the operand-size attribute). In Protected
Mode, both long pointer forms consult the Access Rights (AR) byte in
the descriptor indexed by the selector part of the long pointer. Depending on the value of the AR byte, the jump will perform one of the following types of control transfers:
- A jump to a code segment at the same privilege level
- A task switch
For more information on protected mode control transfers, refer to Chapter 6 and Chapter 7.
Flags Affected
All if a task switch takes place; none if no task switch occurs
Protected Mode Exceptions
Far jumps: #GP, #NP, #SS, and #TS, as indicated in the list above.
Near direct jumps: #GP(0) if procedure location is beyond the code segment limits.
Near
indirect jumps: #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; #GP if the indirect offset obtained is beyond the code
segment limits; #PF(fault-code) for a page fault. Real Address Mode Exceptions
Interrupt 13 if any part of the operand would be outside of the effective address space from 0 to 0FFFFH
Virtual 8086 Mode Exceptions
Same exceptions as under Real Address Mode; #PF(fault-code) for a page fault
LAHF -- Load Flags into AH Register
Opcode | Instruction | Clocks |
Description | Example |
9F | lahf | 2 |
Load: AH := flags SF ZF xx AF xx PF xx CF | lahf |
Operation
AH := SF:ZF:xx:AF:xx:PF:xx:CF;
Description LAHF transfers the low byte of the flags
word to AH. The bits, from MSB to LSB, are sign, zero, indeterminate,
auxiliary, carry, indeterminate, parity, indeterminate, and carry. Flags Affected
None
LAR -- Load Access Rights Byte
Opcode | Instruction | Clocks |
Description | Example |
0F 02 /r | larw r/m16,r16 | pm=15/16 |
r16 := r/m16 masked by FF00 | larw %cx,%bx
larw (%ebx,1),%bx
larw (%ebx,2),%bx
larw (%ebx,%ebp,1),%bx |
0F 02 /r | larl r/m32,r32 | pm=15/16 |
r32 := r/m32 masked by 00FxFF00 | larl %ecx,%ebx
larl (%ebx,2),%ebx
larl (%ebx,4),%ebx
larl (%ebx,%ebp,1),%ebx |
Description The LAR instruction stores a
marked form of the second doubleword of the descriptor for the source
selector if the selector is visible at the CPL (modified by the
selector's RPL) and is a valid descriptor type. The destination
register is loaded with the high-order doubleword of the descriptor
masked by 00FxFF00, and ZF is set to 1. The x indicates that the four
bits corresponding to the upper four bits of the limit are undefined in
the value loaded by LAR. If the selector is invisible or of the wrong
type, ZF is cleared. If the 32-bit operand size is specified, the entire 32-bit value
is loaded into the 32-bit destination register. If the 16-bit operand
size is specified, the lower 16-bits of this value are stored in the
16-bit destination register. All code and data segment descriptors are valid for LAR.
The valid special segment and gate descriptor types for LAR are given in the following table:
Type Name Valid/Invalid
0 Invalid Invalid
1 Available 80286 TSS Valid
2 LDT Valid
3 Busy 80286 TSS Valid
4 80286 call gate Valid
5 80286/80386 task gate Valid
6 80286 trap gate Valid
7 80286 interrupt gate Valid
8 Invalid Invalid
9 Available 80386 TSS Valid
A Invalid Invalid
B Busy 80386 TSS Valid
C 80386 call gate Valid
D Invalid Invalid
E 80386 trap gate Valid
F 80386 interrupt gate Valid
Flags Affected
ZF as described above
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 6; LAR is unrecognized in Real Address Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode
LEA -- Load Effective Address
Opcode | Instruction | Clocks |
Description | Example |
8D /r | leaw m,r16 | 2 |
Store effective address for m in register r16 | leaw m,%bx |
8D /r | leal m,r32 | 2 |
Store effective address for m in register r32 | leal m,%ebx |
8D /r | leaw m,r16 | 2 |
Store effective address for m in register r16 | leaw m,%bx |
8D /r | leal m,r32 | 2 |
Store effective address for m in register r32 | leal m,%ebx |
Operation
IF OperandSize = 16 AND AddressSize = 16
THEN r16 := Addr(m);
ELSE
IF OperandSize = 16 AND AddressSize = 32
THEN
r16 := Truncate_to_16bits(Addr(m)); (* 32-bit address *)
ELSE
IF OperandSize = 32 AND AddressSize = 16
THEN
r32 := Truncate_to_16bits(Addr(m));
ELSE
IF OperandSize = 32 AND AddressSize = 32
THEN r32 := Addr(m);
FI;
FI;
FI;
FI;
Description LEA calculates the effective address
(offset part) and stores it in the specified register. The operand-size
attribute of the instruction (represented by OperandSize in the
algorithm under "Operation" above) is determined by the chosen
register. The address-size attribute (represented by AddressSize) is
determined by the USE attribute of the segment containing the second
operand. The address-size and operand-size attributes affect the action
performed by LEA, as follows:
Operand Size Address Size Action Performed
16 16 16-bit effective address is calculated and
stored in requested 16-bit register
destination.
16 32 32-bit effective address is calculated. The
lower 16 bits of the address are stored in
the requested 16-bit register destination.
32 16 16-bit effective address is calculated. The
16-bit address is zero-extended and stored
in the requested 32-bit register destination.
32 32 32-bit effective address is calculated and
stored in the requested 32-bit register
destination.
Flags Affected
None
Protected Mode Exceptions
#UD if the second operand is a register
Real Address Mode Exceptions
Interrupt 6 if the second operand is a register
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode
LEAVE -- High Level Procedure Exit
Opcode | Instruction | Clocks |
Description | Example |
C9 | leave | 4 |
Set SP to BP, then pop BP | leave |
C9 | leave | 4 |
Set ESP to EBP, then pop EBP | leave |
Operation
IF StackAddrSize = 16
THEN
SP := BP;
ELSE (* StackAddrSize = 32 *)
ESP := EBP;
FI;
IF OperandSize = 16
THEN
BP := Pop();
ELSE (* OperandSize = 32 *)
EBP := Pop();
FI;
Description
LEAVE reverses the actions of the ENTER
instruction. By copying the frame pointer to the stack pointer, LEAVE
releases the stack space used by a procedure for its local variables.
The old frame pointer is popped into BP or EBP, restoring the caller's
frame. A subsequent RET instruction removes any arguments pushed onto the stack of the exiting procedure.
Flags Affected
None
Protected Mode Exceptions
#SS(0) if BP does not point to a location within the limits of the current stack segment
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
LGDT/LIDT -- Load Global/Interrupt Descriptor Table Register
Opcode | Instruction | Clocks |
Description | Example |
0F 01 /2 | lgdtw m16&32 | 11 |
Load m into GDTR | lgdtw m32 |
0F 01 /3 | lidtw m16&32 | 11 |
Load m into IDTR | lidtw m32 |
Operation
IF instruction = LIDT
THEN
IF OperandSize = 16
THEN IDTR.Limit:Base := m16:24 (* 24 bits of base loaded *)
ELSE IDTR.Limit:Base := m16:32
FI;
ELSE (* instruction = LGDT *)
IF OperandSize = 16
THEN GDTR.Limit:Base := m16:24 (* 24 bits of base loaded *)
ELSE GDTR.Limit:Base := m16:32;
FI;
FI;
Description The LGDT and LIDT instructions load a
linear base address and limit value from a six-byte data operand in
memory into the GDTR or IDTR, respectively. If a 16-bit operand is used
with LGDT or LIDT, the register is loaded with a 16-bit limit and a
24-bit base, and the high-order eight bits of the six-byte data operand
are not used. If a 32-bit operand is used, a 16-bit limit and a 32-bit
base is loaded; the high-order eight bits of the six-byte operand are
used as high-order base address bits. The SGDT and SIDT
instructions always store into all 48 bits of the six-byte data
operand. With the 80286, the upper eight bits are undefined after SGDT or SIDT
is executed. With the 80386, the upper eight bits are written with the
high-order eight address bits, for both a 16-bit operand and a 32-bit
operand. If LGDT or LIDT is used with a 16-bit operand to load the
register stored by SGDT or SIDT, the upper eight bits are stored as
zeros. LGDT and LIDT appear in operating system software; they are
not used in application programs. They are the only instructions that
directly load a linear address (i.e., not a segment relative address)
in 80386 Protected Mode. Flags Affected
None
Protected Mode Exceptions
#GP(0) if the current privilege level is not 0; #UD if the source
operand is a register; #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; Interrupt 6 if the source operand is a register
Note
These instructions are valid in Real Address Mode to allow power-up initialization for Protected Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode; #PF(fault-code) for a page fault
LGS/LSS/LDS/LES/LFS -- Load Full Pointer
Opcode | Instruction | Clocks |
Description | Example |
C5 /r | ldsw m16:16,r16 | 7,p=22 |
Load DS:r16 with pointer from memory | lds tocall,%bx |
C5 /r | ldsl m16:32,r32 | 7,p=22 |
Load DS:r32 with pointer from memory | ldsl tocall,%ebx |
0F B2 /r | lssw m16:16,r16 | 7,p=22 |
Load SS:r16 with pointer from memory | lss tocall,%bx |
0F B2 /r | lssl m16:32,r32 | 7,p=22 |
Load SS:r32 with pointer from memory | lssl tocall,%ebx |
C4 /r | lesw m16:16,r16 | 7,p=22 |
Load ES:r16 with pointer from memory | les tocall,%bx |
C4 /r | lesl m16:32,r32 | 7,p=22 |
Load ES:r32 with pointer from memory | lesl tocall,%ebx |
0F B4 /r | lfsw m16:16,r16 | 7,p=25 |
Load FS:r16 with pointer from memory | lfs tocall,%bx |
0F B4 /r | lfsl m16:32,r32 | 7,p=25 |
Load FS:r32 with pointer from memory | lfsl tocall,%ebx |
0F B5 /r | lgsw m16:16,r16 | 7,p=25 |
Load GS:r16 with pointer from memory | lgs tocall,%bx |
0F B5 /r | lgsl m16:32,r32 | 7,p=25 |
Load GS:r32 with pointer from memory | lgsl tocall,%ebx |
Operation
CASE instruction OF
LSS: Sreg is SS; (* Load SS register *)
LDS: Sreg is DS; (* Load DS register *)
LES: Sreg is ES; (* Load ES register *)
LFS: Sreg is FS; (* Load FS register *)
LGS: Sreg is DS; (* Load GS register *)
ESAC;
IF (OperandSize = 16)
THEN
r16 := [Effective Address]; (* 16-bit transfer *)
Sreg := [Effective Address + 2]; (* 16-bit transfer *)
(* In Protected Mode, load the descriptor into the segment register *)
ELSE (* OperandSize = 32 *)
r32 := [Effective Address]; (* 32-bit transfer *)
Sreg := [Effective Address + 4]; (* 16-bit transfer *)
(* In Protected Mode, load the descriptor into the segment register *)
FI;
Description These instructions read a full pointer
from memory and store it in the selected segment register:register
pair. The full pointer loads 16 bits into the segment register SS, DS,
ES, FS, or GS. The other register loads 32 bits if the operand-size
attribute is 32 bits, or loads 16 bits if the operand-size attribute is
16 bits. The other 16- or 32-bit register to be loaded is determined by
the r16 or r32 register operand specified. When an assignment is made to one of the segment registers, the
descriptor is also loaded into the segment register. The data for the
register is obtained from the descriptor table entry for the selector
given. A null selector (values 0000-0003) can be loaded into DS,
ES, FS, or GS registers without causing a protection exception. (Any
subsequent reference to a segment whose corresponding segment register
is loaded with a null selector to address memory causes a #GP(0)
exception. No memory reference to the segment occurs.) The following is a listing of the Protected Mode checks and actions taken in the loading of a segment register:
IF SS is loaded:
IF selector is null THEN #GP(0); FI;
Selector index must be within its descriptor table limits ELSE
#GP(selector);
Selector's RPL must equal CPL ELSE #GP(selector);
AR byte must indicate a writable data segment ELSE #GP(selector);
DPL in the AR byte must equal CPL ELSE #GP(selector);
Segment must be marked present ELSE #SS(selector);
Load SS with selector;
Load SS with descriptor;
IF DS, ES, FS, or GS is loaded with non-null selector:
Selector index must be within its descriptor table limits ELSE
#GP(selector);
AR byte must indicate data or readable code segment ELSE
#GP(selector);
IF data or nonconforming code
THEN both the RPL and the CPL must be less than or equal to DPL in
AR byte;
ELSE #GP(selector);
Segment must be marked present ELSE #NP(selector);
Load segment register with selector and RPL bits;
Load segment register with descriptor;
IF DS, ES, FS or GS is loaded with a null selector:
Clear descriptor valid bit;
Flags Affected
None
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; the second operand must be a memory operand, not a register;
#GP(0) if a null selector is loaded into SS; #PF(fault-code) for a page
fault Real Address Mode Exceptions The second operand must be a
memory operand, not a register; 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
LLDT -- Load Local Descriptor Table Register
Opcode | Instruction | Clocks |
Description | Example |
0F 00 /2 | lldtw r/m16 | 20 |
Load selector r/m16 into LDTR | lldtw %cx
lldtw (%ebx,1)
lldtw (%ebx,2)
lldtw (%ebx,%ebp,1) |
Operation
LDTR := SRC;
Description LLDT loads the Local Descriptor Table
register (LDTR). The word operand (memory or register) to LLDT should
contain a selector to the Global Descriptor Table (GDT). The GDT entry
should be a Local Descriptor Table. If so, then the LDTR is loaded from
the entry. The descriptor registers DS, ES, SS, FS, GS, and CS are not
affected. The LDT field in the task state segment does not change. The selector operand can be 0; if so, the LDTR is marked
invalid. All descriptor references (except by the LAR, VERR, VERW or
LSL instructions) cause a #GP fault. LLDT is used in operating system software; it is not used in application programs.
Flags Affected
None
Protected Mode Exceptions
#GP(0) if the current privilege level is not 0; #GP(selector) if the
selector operand does not point into the Global Descriptor Table, or if
the entry in the GDT is not a Local Descriptor Table; #NP(selector) if
the LDT descriptor is not present; #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 6; LLDT is not recognized in Real Address Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode (because the instruction is not
recognized, it will not execute or perform a memory reference)
Note
The operand-size attribute has no effect on this instruction.
LMSW -- Load Machine Status Word
Opcode | Instruction | Clocks |
Description | Example |
0F 01 /6 | lmsww r/m16 | 10/13 |
Load r/m16 in machine status word | lmsww %cx
lmsww (%ebx,1)
lmsww (%ebx,2)
lmsww (%ebx,%ebp,1) |
Operation
MSW := r/m16; (* 16 bits is stored in the machine status word *)
Description LMSW loads the machine status word (part
of CR0) from the source operand. This instruction can be used to switch
to Protected Mode; if so, it must be followed by an intrasegment jump
to flush the instruction queue. LMSW will not switch back to Real
Address Mode. LMSW is used only in operating system software. It is not used in application programs.
Flags Affected
None
Protected Mode Exceptions
#GP(0) if the current privilege level is not 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 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
Notes
The operand-size attribute has no effect on this instruction. This
instruction is provided for compatibility with the 80286; 80386
programs should use MOV CR0, ... instead.
LOCK -- Assert LOCK# Signal Prefix
Opcode | Instruction | Clocks |
Description | Example |
F0 | lock | 0 |
Assert LOCK# signal for the next instruction | lock |
Description The LOCK prefix causes the
LOCK# signal of the 80386 to be asserted during execution of the
instruction that follows it. In a multiprocessor environment, this
signal can be used to ensure that the 80386 has exclusive use of any
shared memory while LOCK# is asserted. The read-modify-write sequence
typically used to implement test-and-set on the 80386 is the BTS instruction.
The LOCK prefix functions only with the following instructions:
BT, BTS, BTR, BTC mem, reg/imm
XCHG reg, mem
XCHG mem, reg
ADD, OR, ADC, SBB, AND, SUB, XOR mem, reg/imm
NOT, NEG, INC, DEC mem
An undefined opcode trap will be generated if a LOCK prefix is used with any instruction not listed above.
XCHG always asserts LOCK# regardless of the presence or absence of the LOCK prefix.
The
integrity of the LOCK is not affected by the alignment of the memory
field. Memory locking is observed for arbitrarily misaligned fields. Locked access is not assured if another 80386 processor is
executing an instruction concurrently that has one of the following
characteristics:
- Is not preceded by a LOCK prefix
- Is not one of the instructions in the preceding list
- Specifies
a memory operand that does not exactly overlap the destination operand.
Locking is not guaranteed for partial overlap, even if one memory
operand is wholly contained within another.
Flags Affected
None
Protected Mode Exceptions
#UD if LOCK is used with an instruction not listed in the "Description"
section above; other exceptions can be generated by the subsequent
(locked) instruction Real Address Mode Exceptions Interrupt 6 if LOCK is used
with an instruction not listed in the "Description" section above;
exceptions can still be generated by the subsequent (locked)
instruction Virtual 8086 Mode Exceptions #UD if LOCK is used with an
instruction not listed in the "Description" section above; exceptions
can still be generated by the subsequent (locked) instruction
LODS/LODSB/LODSW/LODSD -- Load String Operand
Opcode | Instruction | Clocks |
Description | Example |
AC | lodsb | 5 |
Load byte DS:[(E)SI] into AL | lodsb |
AD | lodsw | 5 |
Load word DS:[(E)SI] into AX | lodsw |
AD | lodsl | 5 |
Load dword DS:[(E)SI] into EAX | lodsl |
Operation
IF AddressSize = 16
THEN use SI for source-index
ELSE (* AddressSize = 32 *)
use ESI for source-index;
FI;
IF byte type of instruction
THEN
AL := [source-index]; (* byte load *)
IF DF = 0 THEN IncDec := 1 ELSE IncDec := -1; FI;
ELSE
IF OperandSize = 16
THEN
AX := [source-index]; (* word load *)
IF DF = 0 THEN IncDec := 2 ELSE IncDec := -2; FI;
ELSE (* OperandSize = 32 *)
EAX := [source-index]; (* dword load *)
IF DF = 0 THEN IncDec := 4 ELSE IncDec := -4; FI;
FI;
FI;
source-index := source-index + IncDec
Description LODS loads the AL, AX, or EAX register
with the memory byte, word, or doubleword at the location pointed to by
the source-index register. After the transfer is made, the source-index
register is automatically advanced. If the direction flag is 0 (CLD was executed), the source index increments; if the direction flag is 1 (STD
was executed), it decrements. The increment or decrement is 1 if a byte
is loaded, 2 if a word is loaded, or 4 if a doubleword is loaded. If the address-size attribute for this instruction is 16 bits,
SI is used for the source-index register; otherwise the address-size
attribute is 32 bits, and the ESI register is used. The address of the
source data is determined solely by the contents of ESI/SI. Load the
correct index value into SI before executing the LODS instruction.
LODSB, LODSW, LODSD are synonyms for the byte, word, and doubleword
LODS instructions. LODS can be preceded by the REP prefix; however, LODS is used more typically within a LOOP construct, because further processing of the data moved into EAX, AX, or AL is usually necessary.
Flags Affected
None
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 exceptions as in Real Address Mode; #PF(fault-code) for a page fault
LOOP/LOOPcond -- Loop Control with CX Counter
Opcode | Instruction | Clocks |
Description | Example |
E2 cb | loop rel8 | 11+m |
DEC count | loop rel8_34 |
E1 cb | loope rel8 | 11+m |
DEC count | loope rel8_35 |
E1 cb | loopz rel8 | 11+m |
DEC count | loopz rel8_36 |
E0 cb | loopne rel8 | 11+m |
DEC count | loopne rel8_37 |
E0 cb | loopnz rel8 | 11+m |
DEC count | loopnz rel8_38 |
Operation
IF AddressSize = 16 THEN CountReg is CX ELSE CountReg is ECX; FI;
CountReg := CountReg - 1;
IF instruction <> LOOP
THEN
IF (instruction = LOOPE) OR (instruction = LOOPZ)
THEN BranchCond := (ZF = 1) AND (CountReg <> 0);
FI;
IF (instruction = LOOPNE) OR (instruction = LOOPNZ)
THEN BranchCond := (ZF = 0) AND (CountReg <> 0);
FI;
FI;
IF BranchCond
THEN
IF OperandSize = 16
THEN
IP := IP + SignExtend(rel8);
ELSE (* OperandSize = 32 *)
EIP := EIP + SignExtend(rel8);
FI;
FI;
Description LOOP decrements the count register
without changing any of the flags. Conditions are then checked for the
form of LOOP being used. If the conditions are met, a short jump is
made to the label given by the operand to LOOP. If the address-size
attribute is 16 bits, the CX register is used as the count register;
otherwise the ECX register is used. The operand of LOOP must be in the
range from 128 (decimal) bytes before the instruction to 127 bytes
ahead of the instruction. The LOOP instructions provide iteration control and combine loop
index management with conditional branching. Use the LOOP instruction
by loading an unsigned iteration count into the count register, then
code the LOOP at the end of a series of instructions to be iterated.
The destination of LOOP is a label that points to the beginning of the
iteration. Flags Affected
None
Protected Mode Exceptions
#GP(0) if the offset jumped to is beyond the limits of the current code segment
Real Address Mode Exceptions
None
Virtual 8086 Mode Exceptions
None
LSL -- Load Segment Limit
Opcode | Instruction | Clocks |
Description | Example |
0F 03 /r | lslw r/m16,r16 | pm=20/21 |
Load: r16 := segment limit, selector r/m16 (byte granular) | lslw %cx,%bx
lslw (%ebx,1),%bx
lslw (%ebx,2),%bx
lslw (%ebx,%ebp,1),%bx |
0F 03 /r | lsll r/m32,r32 | pm=20/21 |
Load: r32 := segment limit, selector r/m32 (byte granular) | lsll %ecx,%ebx
lsll (%ebx,2),%ebx
lsll (%ebx,4),%ebx
lsll (%ebx,%ebp,1),%ebx |
0F 03 /r | lslw r/m16,r16 | pm=25/26 |
Load: r16 := segment limit, selector r/m16 (page granular) | lslw %cx,%bx
lslw (%ebx,1),%bx
lslw (%ebx,2),%bx
lslw (%ebx,%ebp,1),%bx |
0F 03 /r | lsll r/m32,r32 | pm=25/26 |
Load: r32 := segment limit, selector r/m32 (page granular) | lsll %ecx,%ebx
lsll (%ebx,2),%ebx
lsll (%ebx,4),%ebx
lsll (%ebx,%ebp,1),%ebx |
Description The LSL instruction loads a
register with an unscrambled segment limit, and sets ZF to 1, provided
that the source selector is visible at the CPL weakened by RPL, and
that the descriptor is a type accepted by LSL. Otherwise, ZF is cleared
to 0, and the destination register is unchanged. The segment limit is
loaded as a byte granular value. If the descriptor has a page granular
segment limit, LSL will translate it to a byte limit before loading it
in the destination register (shift left 12 the 20-bit "raw" limit from
descriptor, then OR with 00000FFFH). The 32-bit forms of this instruction store the 32-bit byte granular limit in the 16-bit destination register.
Code and data segment descriptors are valid for LSL.
The valid special segment and gate descriptor types for LSL are given in the following table:
Type Name Valid/Invalid
0 Invalid Invalid
1 Available 80286 TSS Valid
2 LDT Valid
3 Busy 80286 TSS Valid
4 80286 call gate Invalid
5 80286/80386 task gate Invalid
6 80286 trap gate Invalid
7 80286 interrupt gate Invalid
8 Invalid Valid
9 Available 80386 TSS Valid
A Invalid Invalid
B Busy 80386 TSS Valid
C 80386 call gate Invalid
D Invalid Invalid
E 80386 trap gate Invalid
F 80386 interrupt gate Invalid
Flags Affected
ZF as described above
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 6; LSL is not recognized in Real Address Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode
LTR -- Load Task Register
Opcode | Instruction | Clocks |
Description | Example |
0F 00 /3 | ltrw r/m16 | pm=23/27 |
Load EA word into task register | ltrw %cx
ltrw (%ebx,1)
ltrw (%ebx,2)
ltrw (%ebx,%ebp,1) |
Description LTR loads the task register
from the source register or memory location specified by the operand.
The loaded task state segment is marked busy. A task switch does not
occur. LTR is used only in operating system software; it is not used in application programs.
Flags Affected
None
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; #GP(0) if the current privilege level is not 0; #GP(selector)
if the object named by the source selector is not a TSS or is already
busy; #NP(selector) if the TSS is marked "not present"; #PF(fault-code)
for a page fault Real Address Mode Exceptions
Interrupt 6; LTR is not recognized in Real Address Mode
Virtual 8086 Mode Exceptions
Same exceptions as in Real Address Mode
Notes
The operand-size attribute has no effect on this instruction.
|