Vol. 3B 21-5
MIXING 16-BIT AND 32-BIT CODE
While executing 32-bit code, if a call is made to a 16-bit code segment which is at the same or a more privileged
level (that is, the DPL of the called code segment is less than or equal to the CPL of the calling code segment)
through a 16-bit call gate, then the upper 16-bits of the ESP register may be unreliable upon returning to the 32-
bit code segment (that is, after executing a RET in the 16-bit code segment).
When the CALL instruction and its matching RET instruction are in code segments that have D flags with the same
values (that is, both are 32-bit code segments or both are 16-bit code segments), the default settings may be
used. When the CALL instruction and its matching RET instruction are in segments which have different D-flag
settings, an operand-size prefix must be used.
21.4.2.1 Controlling the Operand-Size Attribute For a Call
Three things can determine the operand-size of a call:
•
The D flag in the segment descriptor for the calling code segment.
•
An operand-size instruction prefix.
•
The type of call gate (16-bit or 32-bit), if a call is made through a call gate.
When a call is made with a pointer (rather than a call gate), the D flag for the calling code segment determines the
operand-size for the CALL instruction. This operand-size attribute can be overridden by prepending an operand-
size prefix to the CALL instruction. So, for example, if the D flag for a code segment is set for 16 bits and the
operand-size prefix is used with a CALL instruction, the processor will cause the information stored on the stack to
Figure 21-1. Stack after Far 16- and 32-Bit Calls
SP
After 16-bit Call
PARM 1
IP
SP
SS
PARM 2
CS
0
31
SS
EIP
After 32-bit Call
CS
ESP
ESP
PARM 2
PARM 1
0
31
With Privilege Transition
Stack
Growth
After 16-bit Call
PARM 1
IP
SP
PARM 2
CS
0
31
Without Privilege Transition
Stack
Growth
After 32-bit Call
PARM 1
ESP
PARM 2
CS
0
31
EIP
Undefined