Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Watcom C/C++ User's Guide - the following form of the auxiliary pragma can be used to specify the http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
The following form of the auxiliary pragma can be used to specify the
registers that are to be used to pass arguments to a particular function.

+--------------------------------------------------------------------------+
|      #pragma aux sym parm {reg_set} [;]                                  |
|                                                                          |
+--------------------------------------------------------------------------+

where
    description

sym
    is a function name.

reg_set
    is called a register set.  The register sets specify the registers that
    are to be used for argument passing.  A register set is a list of
    registers separated by spaces and enclosed in square brackets.

Register sets establish a priority for register allocation during argument
list processing.  Register sets are processed from left to right.  However,
within a register set, registers are chosen in any order.  Once all register
sets have been processed, any remaining arguments are pushed on the stack.

Note that regardless of the register sets specified, only certain
combinations of registers will be selected for arguments of a particular
type.

Note that arguments of type float and double are always pushed on the stack
when the "fpi" or "fpi87" option is used.

double
    Arguments of type double can only be passed in one of the following
    register pairs:  EDX:EAX, ECX:EBX, ECX:EAX, ECX:ESI, EDX:EBX, EDI:EAX,
    ECX:EDI, EDX:ESI, EDI:EBX, ESI:EAX, ECX:EDX, EDX:EDI, EDI:ESI, ESI:EBX
    or EBX:EAX.  For example, if the following register set was specified
    for a routine having an argument of type double,


         [EBP EBX]

    the argument would be pushed on the stack since a valid register
    combination for 8-byte arguments is not contained in the register set.
     Note that this method for passing arguments of type double is supported
    only when the "fpc" option is used.  Note that this argument passing
    method does not include the passing of 8-byte structures.

far pointer
    A far pointer can only be passed in one of the following register pairs:
     DX:EAX, CX:EBX, CX:EAX, CX:ESI, DX:EBX, DI:EAX, CX:EDI, DX:ESI, DI:EBX,
    SI:EAX, CX:EDX, DX:EDI, DI:ESI, SI:EBX, BX:EAX, FS:ECX, FS:EDX, FS:EDI,
    FS:ESI, FS:EBX, FS:EAX, GS:ECX, GS:EDX, GS:EDI, GS:ESI, GS:EBX, GS:EAX,
    DS:ECX, DS:EDX, DS:EDI, DS:ESI, DS:EBX, DS:EAX, ES:ECX, ES:EDX, ES:EDI,
    ES:ESI, ES:EBX or ES:EAX.  For example, if a far pointer is passed to a
    function with the following register set,


         [ES EBP]

    the argument would be pushed on the stack since a valid register
    combination for a far pointer is not contained in the register set.

int
    The only registers that will be assigned to 4-byte arguments (e.g.,
    arguments of type int) are:  EAX, EBX, ECX, EDX, ESI and EDI.  For
    example, if the following register set was specified for a routine with
    one argument of type int,


         [EBP]

    the argument would be pushed on the stack since a valid register
    combination for 4-byte arguments is not contained in the register set.
     Note that this argument passing method includes 4-byte structures.
     Note that this argument passing method also includes arguments of type
    float but only when the "fpc" option is used.

char, short int
    Arguments whose size is 1 byte or 2 bytes (e.g., arguments of type char
    and short int as well as 2-byte structures) are promoted to 4 bytes and
    are then assigned registers as if they were 4-byte arguments.

others
    Arguments that do not fall into one of the above categories cannot be
    passed in registers and are pushed on the stack.  Once an argument has
    been assigned a position on the stack, all remaining arguments will be
    assigned a position on the stack even if all register sets have not yet
    been exhausted.

Notes:

 1. The default register set is [EAX EBX ECX EDX].

 2. Specifying registers AH and AL is equivalent to specifying register AX.
    Specifying registers DH and DL is equivalent to specifying register DX.
     Specifying registers CH and CL is equivalent to specifying register CX.
     Specifying registers BH and BL is equivalent to specifying register BX.
     Specifying register EAX implies that register AX has been specified.
     Specifying register EBX implies that register BX has been specified.
     Specifying register ECX implies that register CX has been specified.
     Specifying register EDX implies that register DX has been specified.
     Specifying register EDI implies that register DI has been specified.
     Specifying register ESI implies that register SI has been specified.
     Specifying register EBP implies that register BP has been specified.
     Specifying register ESP implies that register SP has been specified.

 3. If you are compiling for a memory model with a small data model, or the
    "zdp" compiler option is specified, any register combination containing
    register DS becomes illegal.  In a small data model, segment register DS
    must remain unchanged as it points to the program's data segment.  Note
    that the "zdf" compiler option can be used to specify that register DS
    does not contain that segment address of the program's data segment.  In
    this case, register combinations containing register DS are legal.

 4. If you are compiling for the flat memory model, any register combination
    containing DS or ES becomes illegal.  In a flat memory model, code and
    data reside in the same segment.  Segment registers DS and ES point to
    this segment and must remain unchanged.

Consider the following example.


     #pragma aux myrtn parm [eax ebx ecx edx] [ebp esi];

Suppose myrtn is a routine with 3 arguments each of type double.

 1. The first argument will be passed in the register pair EDX:EAX.

 2. The second argument will be passed in the register pair ECX:EBX.

 3. The third argument will be pushed on the stack since EBP:ESI is not a
    valid register pair for arguments of type double.

It is possible for registers from the second register set to be used before
registers from the first register set are used.  Consider the following
example.


     #pragma aux myrtn parm [eax ebx ecx edx] [esi edi];

Suppose myrtn is a routine with 3 arguments, the first of type int and the
second and third of type double.

 1. The first argument will be passed in the register EAX.

 2. The second argument will be passed in the register pair ECX:EBX.

 3. The third argument will be passed in the register set EDI:ESI.

Note that registers are no longer selected from a register set after
registers are selected from subsequent register sets, even if all registers
from the original register set have not been exhausted.

An empty register set is permitted.  All subsequent register sets appearing
after an empty register set are ignored; all remaining arguments are pushed
on the stack.

Notes:

 1. If a single empty register set is specified, all arguments are passed on
    the stack.

 2. If no register set is specified, the default register set [EAX EBX ECX
    EDX] is used.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson