1 code-segment pointer size, 2 stack management for control transfer – Intel IA-32 User Manual
Page 585
Vol. 3A 16-5
MIXING 16-BIT AND 32-BIT CODE
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.
16.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 16.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.
16.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 instruction (see
Figure 16-1). On a 16-bit call, the processor pushes the contents of the 16-bit IP register and (for
calls between privilege levels) the 16-bit SP register. The matching RET instruction must also
use a 16-bit operand size to pop these 16-bit values from the stack into the 16-bit registers.
A 32-bit CALL instruction pushes the contents of the 32-bit EIP register and (for inter-privilege-
level calls) the 32-bit ESP register. Here, the matching RET instruction must use a 32-bit
operand size to pop these 32-bit values from the stack into the 32-bit registers. If the two parts
of a CALL/RET instruction pair do not have matching operand sizes, the stack will not be
managed correctly and the values of the instruction pointer and stack pointer will not be restored
to correct values.