21-2 Vol. 3B
MIXING 16-BIT AND 32-BIT CODE
The B flag in the stack-segment descriptor specifies the size of stack pointer (the 32-bit ESP register or the 16-bit
SP register) used by the processor for implicit stack references. The B flag for all data descriptors also controls
upper address range for expand down segments.
When transferring program control to another code segment through a call gate, interrupt gate, or trap gate, the
operand size used during the transfer is determined by the type of gate used (16-bit or 32-bit), (not by the D-flag
or prefix of the transfer instruction). The gate type determines how return information is saved on the stack (or
stacks).
For most efficient and trouble-free operation of the processor, 32-bit programs or tasks should have the D flag in
the code-segment descriptor and the B flag in the stack-segment descriptor set, and 16-bit programs or tasks
should have these flags clear. Program control transfers from 16-bit segments to 32-bit segments (and vice versa)
are handled most efficiently through call, interrupt, or trap gates.
Instruction prefixes can be used to override the default operand size and address size of a code segment. These
prefixes can be used in real-address mode as well as in protected mode and virtual-8086 mode. An operand-size or
address-size prefix only changes the size for the duration of the instruction.
21.2
MIXING 16-BIT AND 32-BIT OPERATIONS WITHIN A CODE SEGMENT
The following two instruction prefixes allow mixing of 32-bit and 16-bit operations within one segment:
•
The operand-size prefix (66H)
•
The address-size prefix (67H)
These prefixes reverse the default size selected by the D flag in the code-segment descriptor. For example, the
processor can interpret the (MOV mem, reg) instruction in any of four ways:
•
In a 32-bit code segment:
— Moves 32 bits from a 32-bit register to memory using a 32-bit effective address.
— If preceded by an operand-size prefix, moves 16 bits from a 16-bit register to memory using a 32-bit
effective address.
— If preceded by an address-size prefix, moves 32 bits from a 32-bit register to memory using a 16-bit
effective address.
— If preceded by both an address-size prefix and an operand-size prefix, moves 16 bits from a 16-bit register
to memory using a 16-bit effective address.
•
In a 16-bit code segment:
— Moves 16 bits from a 16-bit register to memory using a 16-bit effective address.
— If preceded by an operand-size prefix, moves 32 bits from a 32-bit register to memory using a 16-bit
effective address.
— If preceded by an address-size prefix, moves 16 bits from a 16-bit register to memory using a 32-bit
effective address.
— If preceded by both an address-size prefix and an operand-size prefix, moves 32 bits from a 32-bit register
to memory using a 32-bit effective address.
The previous examples show that any instruction can generate any combination of operand size and address size
regardless of whether the instruction is in a 16- or 32-bit segment. The choice of the 16- or 32-bit default for a code
segment is normally based on the following criteria:
•
Performance — Always use 32-bit code segments when possible. They run much faster than 16-bit code
segments on P6 family processors, and somewhat faster on earlier IA-32 processors.
•
The operating system the code segment will be running on — If the operating system is a 16-bit
operating system, it may not support 32-bit program modules.
•
Mode of operation — If the code segment is being designed to run in real-address mode, virtual-8086 mode,
or SMM, it must be a 16-bit code segment.