Intel 253668-032US User Manual

Page of 806
Vol. 3   18-7
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.
18.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 infor-
mation stored on the stack to be stored in 32-bit format. If the call is to a 32-bit code 
segment, the instructions in that code segment will be able to read the stack coher-
ently. Also, a RET instruction from the 32-bit code segment without an operand-size 
prefix will maintain stack coherency with the 16-bit code segment being returned to.
When a CALL instruction references a call-gate descriptor, the type of call is deter-
mined by the type of call gate (16-bit or 32-bit). The offset to the destination in the 
code segment being called is taken from the gate descriptor; therefore, if a 32-bit call 
gate is used, a procedure in a 16-bit code segment can call a procedure located more 
than 64 KBytes from the base of a 32-bit code segment, because a 32-bit call gate 
uses a 32-bit offset.
Note that regardless of the operand size of the call and how it is determined, the size 
of the stack pointer used (SP or ESP) is always controlled by the B flag in the stack-
segment descriptor currently in use (that is, when B is clear, SP is used, and when B 
is set, ESP is used).
An unmodified 16-bit code segment that has run successfully on an 8086 processor 
or in real-mode on a later IA-32 architecture processor will have its D flag clear and 
will not use operand-size override prefixes. As a result, all CALL instructions in this 
code segment will use the 16-bit operand-size attribute. Procedures in these code