Chapter Contents |
Previous |
Next |
Communication with Assembler Programs |
The following sections discuss calling conventions for C functions.
C Parameter Lists |
Generally, C passes arguments by value rather than by reference.
This means that the parameter list contains the actual argument values instead
of pointers to the arguments. Suppose that the extern function
f
is called with the following
arguments:
int i; char c; short s; double d; char *p; f(i, c, s, d, p);
Typical C Parameter List
PARMBLOK DS 0D DS F value of i DS F value of c (promoted to int) DS F value of s (promoted to int) DS F uninitialized padding bytes DS D value of d DS A value of p
Note that
c
has been placed in byte 3 of a word,
s
has been placed in the
second halfword of a word, and
d
is aligned on a doubleword boundary. The parameter
list itself is always aligned on a doubleword boundary.
Many assembler routines expect their arguments to be passed by
reference instead of by value. In some cases, this type of parameter list
can be generated by simply applying the ampersand (
&
) operator to each
argument. However, this solution is insufficient for function calls using
arguments that are not lvalues, such as constants or expressions. To support
such function arguments, the compiler accepts the (nonstandard) at-sign (
@
)
operator. The
@
operator can be applied only to function arguments. When applied
to an lvalue, the
@
operator has the same effect as the
&
operator. When applied to a
function argument that is not an lvalue (such as a constant), the
@
operator returns a pointer
to a temporary copy of the value. (See The @ operator. Note that the
@
operator can be used
only in conjunction with the
at
compiler option.)
Also, many assembler routines accept varying-length
parameter lists. These routines typically expect that the last parameter has
the high-order bit (the VL-bit) set to indicate that it is the final parameter.
The compiler can be made to create this sort of parameter list by using the
_ _asm
keyword in the function declaration.
To show how the
@
operator and the
_ _asm
keyword can
be used, suppose the function
f
in the previous example is called as follows:
_ _asm void f(); char c; short s; char *p; f(@(2+3), @c, @s, @1.0, @p);
Then the compiler creates a parameter list, as shown in C Parameter List Using Keyword _ _asm and the @ Operator.
C Parameter List Using Keyword _ _asm and the @ Operator
PARMBLOK DS 0D DS A pointer to a temporary 5 DS A pointer to c DS A pointer to s DS A pointer to a temporary 1.0 DS A pointer, with VL-bit set, to p
An OMD listing may be extremely helpful in determining the exact format of any parameter block.
_ _asm, _ _ref, and _ _ibmos Keywords |
The
_ _asm
,
_ _ref
, and
_ _ibmos
keywords are used
to declare functions and pointers to functions written in assembler language
that expect a parameter list in OS format.
If the
_ _asm
keyword is used in a declaration of
a function or function pointer, the compiler creates a VL-format parameter
list for the function. The compiler uses the following conditions to create
a VL-format parameter list:
The following declaration causes the compiler to create
a VL-format parameter list for
asm_func
:
_ _asm int asm_func(void *, void *);
If the
_ _asm
keyword is used in the declaration
of a function pointer, the function pointer is assumed to be local unless
the
_ _remote
keyword is explicitly used. The following declaration
causes the compiler to create a VL-format parameter list for the function
called via
asm_fp
:
_ _asm int (*asm_fp)(void *, void *);
The
_ _asm
keyword does not cause the compiler
to generate a call-by-reference parameter list; that is done by the
_ _ref
keyword, described below. You can also use the
@
(at sign) operator to
pass individual parameters by reference. Refer to The @ operator for more information on this operator.
The
_ _ref
keyword can be used in function declarations
and function pointer declarations. This keyword specifies that the called
function is an assembler language function expecting a call-by-reference parameter
list in VL format. The effect of using the
_ _ref
keyword is similar to
using the
_ _asm
keyword and the
@
operator together, with the
@
operator implied for all non-pointer arguments.
The parameter list created for functions declared with
the
_ _ref
keyword, or called via a function pointer declared with
the
_ _ref
keyword, contains only pointers. In general, if the
argument is already a pointer type, such as
char *
, the argument is used directly
without further indirection. If the argument is not a pointer type, the compiler
places a pointer to the argument in the parameter list. The parameter list
is in VL format as described above.
_ _ref void myfunc(short); int i; i = 2; myfunc(i);
The compiler creates a temporary
short
variable, assigns
it the value of
i
, and places a pointer to the temporary variable in the parameter
list.
If the argument already has the type specified in the
prototype, or if the argument is an
int
or
long
type and the prototype
specifies a type that differs only in sign, no conversion is performed. For
example, if the prototype specifies
unsigned int
and the argument is
signed int
, no conversion is performed and a pointer to the argument is placed
in the parameter list.
Like
_ _asm
, if the
_ _ref
keyword is
used in the declaration of a function pointer, the function pointer is assumed
to be local unless the
_ _remote
keyword is explicitly used. See Remote Function Pointers for
more information.
Using the
_ _ibmos
keyword in a declaration is the same
as specifying the name of the function or function pointer in a
#pragma linkage (,OS)
statement.
Refer to The #pragma linkage statement for more information. You may find it easier to use the
_ _ibmos
keyword
to declare function pointers in certain situations, such as in the declaration
of aggregate types. For example:
struct XYZ { /* other structure members */ _ _ibmos int (*fp)(int, int); /* other structure members */ };
Function pointers declared with the
_ _ibmos
keyword
are always local. Specification of both
_ _ibmos
and
_ _remote
results
in an error.
The
_ _asm
,
_ _ref
, and
_ _ibmos
keywords
may not be used in a declaration with any ILC function keywords, such as
_ _pascal
. Unless there is an attempt to convert a local function pointer to
a remote function pointer,
_ _asm
,
_ _ref
, and
_ _ibmos
function
pointers may be freely converted to each other.
Linkage Conventions |
The compiler uses standard linkage when calling a function.
For example, the function
f
is called with the following instructions:
L 15,=V(F) R15 addresses the function. LA 1,PARMBLOK R1 addresses the function arguments. BALR 14,15 R14 contains the return address.
Also, R13 points to an 18-word save area.
The register conventions illustrated above are summarized in Register Conventions for Function Calls.
General Register | Contents on Entry to the Function |
---|---|
1 | addresses parameter list |
13 | 18-word save area |
14 | return address |
15 | entry point address |
Note:
armode
is not supported for C++ code in Release 7.00
Returning Values from Assembler Routines |
If
f
returns a scalar value, the compiler
expects the value to be in general register 15 unless the value is a
double
,
long double
, or
float
, in which case the
value is expected to be in floating-point register 0. For example, suppose
f
is declared as a function returning
int
; given the call
val = f(i, c, s, d, p);
the compiler may then generate the following code sequence:
L 15,=V(F) LA 1,PARMBLOK BALR 14,15 Call f. ST 15,VAL Store return value in val.
Or, if
f
is declared as returning
double
,
the compiler may generate the following:
L 15,=V(F) LA 1,PARMBLOK BALR 14,15 Call f. STD 0,VAL Store return value in val.
If function
f
returns a structure or
union value, the linkage is a little more complicated. In this case, a pointer
to an area in which the return value should be stored is located 4 bytes before
the parameter list. This pointer may be 0 if the function result is discarded
as the result of being cast to
void
. In addition to
copying the return value to the area addressed by the return value pointer,
the function must also clear the pointer before returning, or a later call
whose return value is discarded may cause overlay of the previous return value.
This is an example of generated code for a call to a
function
S
returning a structure:
LA 2,SRET Address return code. ST 2,PARMBLOK-4 Store before parameter list. L 15,=V(S) LA 1,PARMBLOK BALR 14,15
This is an example of generated code in
S
to return a structure value:
L 2,DSAPARMS Locate incoming parameter list. S 2,=F'4' Back up one word. ICM 3,B'1111',0(2) Test for void return. BZ NOVAL MVC 0(slen,3),SRET Copy return value. MVC 0(4,2),CRABZERO Zero return value address. NOVAL DS 0H
L 15,=V(F) LA 1,PARMBLOK BALR 14,15 Call f. STAM 15,15,VAL Store returned ALET in val word 1. ST 15,VAL+4 Store returned pointer in val word 2.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.