background image

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 memreg) 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.