User's Manual

Vol. 3 18-5
MIXING 16-BIT AND 32-BIT CODE
Likewise, there are three ways for procedure in a 32-bit code segment to safely make
a call to a 16-bit code segment:
Make the call through a 16-bit call gate. Here, the EIP value at the CALL
instruction cannot exceed FFFFH.
Make a 32-bit call to a 16-bit interface procedure. The interface procedure then
makes a 16-bit call to the intended destination.
Modify the 32-bit procedure, inserting an operand-size prefix before the call,
changing it to a 16-bit call. Be certain that the return offset does not exceed
FFFFH.
These methods of transferring program control overcome the following architectural
limitations imposed on calls between 16-bit and 32-bit code segments:
Pointers from 16-bit code segments (which by default can only be 16 bits) cannot
be used to address data or code located beyond FFFFH in a 32-bit segment.
The operand-size attributes for a CALL and its companion RETURN instruction
must be the same to maintain stack coherency. This is also true for implicit calls
to interrupt and exception handlers and their companion IRET instructions.
A 32-bit parameters (particularly a pointer parameter) greater than FFFFH
cannot be squeezed into a 16-bit parameter location on a stack.
The size of the stack pointer (SP or ESP) changes when switching between 16-bit
and 32-bit code segments.
These limitations are discussed in greater detail in the following sections.
18.4.1 Code-Segment Pointer Size
For control-transfer instructions that use a pointer to identify the next instruction
(that is, those that do not use gates), the operand-size attribute determines the size
of the offset portion of the pointer. The implications of this rule are as follows:
A JMP, CALL, or RET instruction from a 32-bit segment to a 16-bit segment is
always possible using a 32-bit operand size, providing the 32-bit pointer does not
exceed FFFFH.
A JMP, CALL, or RET instruction from a 16-bit segment to a 32-bit segment
cannot address a destination greater than FFFFH, unless the instruction is given
an operand-size prefix.
See Section 18.4.5, “Writing Interface Procedures,” for an interface procedure that
can transfer program control from 16-bit segments to destinations in 32-bit
segments beyond FFFFH.
18.4.2 Stack Management for Control Transfer
Because the stack is managed differently for 16-bit procedure calls than for 32-bit
calls, the operand-size attribute of the RET instruction must match that of the CALL