2 passing parameters with a gate – Intel IA-32 User Manual
Page 587
Vol. 3A 16-7
MIXING 16-BIT AND 32-BIT CODE
16.4.2.1
Controlling the Operand-Size Attribute For a Call
Three things can determine the operand-size of a call:
•
The D flag in the segment descriptor for the calling code segment.
•
An operand-size instruction prefix.
•
The type of call gate (16-bit or 32-bit), if a call is made through a call gate.
When a call is made with a pointer (rather than a call gate), the D flag for the calling code
segment determines the operand-size for the CALL instruction. This operand-size attribute can
be overridden by prepending an operand-size prefix to the CALL instruction. So, for example,
if the D flag for a code segment is set for 16 bits and the operand-size prefix is used with a
CALL instruction, the processor will cause the information stored on the stack to be stored in
32-bit format. If the call is to a 32-bit code segment, the instructions in that code segment will
be able to read the stack coherently. Also, a RET instruction from the 32-bit code segment
without an operand-size prefix will maintain stack coherency with the 16-bit code segment
being returned to.
When a CALL instruction references a call-gate descriptor, the type of call is determined by the
type of call gate (16-bit or 32-bit). The offset to the destination in the code segment being called
is taken from the gate descriptor; therefore, if a 32-bit call gate is used, a procedure in a 16-bit
code segment can call a procedure located more than 64 KBytes from the base of a 32-bit code
segment, because a 32-bit call gate uses a 32-bit offset.
Note that regardless of the operand size of the call and how it is determined, the size of the stack
pointer used (SP or ESP) is always controlled by the B flag in the stack-segment descriptor
currently in use (that is, when B is clear, SP is used, and when B is set, ESP is used).
An unmodified 16-bit code segment that has run successfully on an 8086 processor or in
real-mode on a later IA-32 architecture processor will have its D flag clear and will not use
operand-size override prefixes. As a result, all CALL instructions in this code segment will use
the 16-bit operand-size attribute. Procedures in these code segments can be modified to safely
call procedures to 32-bit code segments in either of two ways:
•
Relink the CALL instruction to point to 32-bit call gates (see Section 16.4.2.2, “Passing
Parameters With a Gate”).
•
Add a 32-bit operand-size prefix to each CALL instruction.
16.4.2.2
Passing Parameters With a Gate
When referencing 32-bit gates with 16-bit procedures, it is important to consider the number of
parameters passed in each procedure call. The count field of the gate descriptor specifies the size
of the parameter string to copy from the current stack to the stack of a more privileged (numer-
ically lower privilege level) procedure. The count field of a 16-bit gate specifies the number of
16-bit words to be copied, whereas the count field of a 32-bit gate specifies the number of 32-bit
doublewords to be copied. The count field for a 32-bit gate must thus be half the size of the
number of words being placed on the stack by a 16-bit procedure. Also, the 16-bit procedure
must use an even number of words as parameters.