Intel IA-32 User Manual
Page 584
16-4 Vol. 3A
MIXING 16-BIT AND 32-BIT CODE
A stack that spans less than 64 KBytes can be shared by both 16- and 32-bit code segments. This
class of stacks includes:
•
Stacks in expand-up segments with the G (granularity) and B (big) flags in the stack-
segment descriptor clear.
•
Stacks in expand-down segments with the G and B flags clear.
•
Stacks in expand-up segments with the G flag set and the B flag clear and where the stack
is contained completely within the lower 64 KBytes. (Offsets greater than FFFFH can be
used for data, other than the stack, which is not shared.)
See Section 3.4.5, “Segment Descriptors,” for a description of the G and B flags and the expand-
down stack type.
The B flag cannot, in general, be used to change the size of stack used by a 16-bit code segment.
This flag controls the size of the stack pointer only for implicit stack references such as those
caused by interrupts, exceptions, and the PUSH, POP, CALL, and RET instructions. It does not
control explicit stack references, such as accesses to parameters or local variables. A 16-bit code
segment can use a 32-bit stack only if the code is modified so that all explicit references to the
stack are preceded by the 32-bit address-size prefix, causing those references to use 32-bit
addressing and explicit writes to the stack pointer are preceded by a 32-bit operand-size prefix.
In 32-bit, expand-down segments, all offsets may be greater than 64 KBytes; therefore, 16-bit
code cannot use this kind of stack segment unless the code segment is modified to use 32-bit
addressing.
16.4
TRANSFERRING CONTROL AMONG MIXED-SIZE CODE
SEGMENTS
There are three ways for a procedure in a 16-bit code segment to safely make a call to a 32-bit
code segment:
•
Make the call through a 32-bit call gate.
•
Make a 16-bit call to a 32-bit interface procedure. The interface procedure then makes a
32-bit call to the intended destination.
•
Modify the 16-bit procedure, inserting an operand-size prefix before the call, to change it
to a 32-bit call.
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.