The compiler always uses the global registers DPL, DPH, B and ACC to pass the first parameter to a routine. The second parameter onwards is either allocated on the stack (for reentrant routines or if --stack-auto is used) or in data / xdata memory (depending on the memory model).
In the following example the function c_func calls an assembler routine asm_func, which takes two parameters.
extern int asm_func(unsigned char, unsigned char);The corresponding assembler function is:
int c_func (unsigned char i, unsigned char j)
{
return asm_func(i,j);
}
int main()
{
return c_func(10,9);
}
.globl _asm_func_PARM_2Note here that the return values are placed in 'dpl' - One byte return value, 'dpl' LSB & 'dph' MSB for two byte values. 'dpl', 'dph' and 'b' for three byte values (generic pointers) and 'dpl','dph','b' & 'acc' for four byte values.
.globl _asm_func
.area OSEG
_asm_func_PARM_2:
.ds 1
.area CSEG
_asm_func:
mov a,dpl
add a,_asm_func_PARM_2
mov dpl,a
mov dpl,#0x00
ret
The parameter naming convention is _<function_name>_PARM_<n>,
where n is the parameter number starting from 1, and counting from
the left. The first parameter is passed in ``dpl'' for One bye
parameter, ``dptr'' if two bytes, ``b,dptr'' for three bytes
and ``acc,b,dptr'' for four bytes, the variable name for the second
parameter will be _<function_name>_PARM_2.
Assemble the assembler routine with the following command:
asx8051 -losg asmfunc.asm
Then compile and link the assembler routine to the C source file with
the following command:
sdcc cfunc.c asmfunc.rel
In this case the second parameter onwards will be passed on the stack, the parameters are pushed from right to left i.e. after the call the left most parameter will be on the top of the stack. Here is an example:
extern int asm_func(unsigned char, unsigned char);The corresponding assembler routine is:
int c_func (unsigned char i, unsigned char j) reentrant
{
return asm_func(i,j);
}
int main()
{
return c_func(10,9);
}
.globl _asm_funcThe compiling and linking procedure remains the same, however note the extra entry & exit linkage required for the assembler code, _bp is the stack frame pointer and is used to compute the offset into the stack for parameters and local variables.
_asm_func:
push _bp
mov _bp,sp
mov r2,dpl
mov a,_bp
clr c
add a,#0xfd
mov r0,a
add a,#0xfc
mov r1,a
mov a,@r0
add a,r2
mov dpl,a
mov dph,#0x00
mov sp,_bp
pop _bp
ret