background image

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