11.2 Stack call functions
--------------------------
Stack functions are by default declared using an identifier which
contains at least one lower-case letter. Stack functions can thus easily be
distinguished from register functions, since lower-case letters are not
allowed in the names of register functions.
Parameters for stack functions, if there are any, can be of any type -
byte, char, word, int, dword, long or float.
Parameters are transferred according to the rules for each type of
function. If the function has no declaration, the compiler will not keep
track of the number and type of parameters being transferred. In this case
there is more freedom in how they are used, but be sure to avoid
incorrectly using them.
The list of parameters indicates the type for each parameter.
Parameters of the same type listed in a row are separated by commas. Formal
parameters of different types in a function declaration are separated by a
semicolon.
In the following example a stack function returns the sum of all of its
parameters (of different types) as a value of type word:
word add_them_all (int a,b,c; byte d,e; word x,y)
{
return( a+b+c+d+e+x+y );
}
C-- originally used only Pascal type calls to stack functions. This has
the advantage of greater compactness and a simpler method of code
generation. Drawbacks of this call type, which are conversely advantages of
the C call type, are rigid adherence to the number and type of transferred
parameters (if you call a function using the pascal method but use the
wrong number of parameters the stack will be corrupted.) I list below some
technical details of both types of function call.
Frame of C-- stack for close stack functions in pascal style:
ADDRESS
...
BP + FFFE second to last byte of local variables
BP + FFFF last byte of local variable
BP + 0000 Saved BP
BP + 0002 RET address
BP + 0004 last word of parameters transferred to functions
(if they exist)
BP + 0006 second to last word of parameters transferred to functions
...
BP + nnnn first word of parameters transferred to functions
The stack is freed of transferred functions directly in the function by
the command 'RET nnnn', where nnnn is the size of the functions transferred
to the stack.
Frame of a C-- stack for close stack functions in C style:
ADDRESS
...
BP + FFFE second to last byte of local variables
BP + FFFF last byte of local variables
BP + 0000 Saved BP
BP + 0002 RET address
BP + 0004 first word of parameters transferred to functions (if they
exist)
BP + 0006 second word of parameters transferred to functions
...
BP + nnnn last word of parameters transferred to functions
Functions in C style end with the command 'RET'. The stack is freed of
parameters at the same place where the function was called. Usually this is
done using the command 'ADD SP,nnnn', i. e., the compiler can know
precisely how many and what types of parameters are being transferred to
the function in this case, and correspondingly it frees the stack after
completing the function. This is very convenient for functions which can
process a variable number of parameters (for instance printf functions).
A function is declared as follows:
rettype modif procname();
First comes the obligatory type of return from the function. By
default, for 16-bit programs this is equal to word, and for 32-bit programs
dword. Then comes the equally obligatory modifier. By default all stack
functions in C-- are in pascal style (except when compiling a Windows
program, where by default the style of calling functions is stdcall). Next
comes the name of the function with parentheses which indicate that a
function and not a variable is being declared. The declaration ends with a
semicolon.
When declaring functions in C-- the function parameters need not be
registered (in which case the compiler does not control the number of type
of transferred parameters) but if they are included, this switches on the
mechanism for monitoring the number and type of parameters.