<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
- <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
- <TITLE>SDCC Compiler User Guide: External Stack.</TITLE>
+ <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.7">
+ <TITLE>SDCC Compiler User Guide: Interfacing with assembly routines.</TITLE>
<LINK HREF="SDCCUdoc-22.html" REL=next>
<LINK HREF="SDCCUdoc-20.html" REL=previous>
<LINK HREF="SDCCUdoc.html#toc21" REL=contents>
<A HREF="SDCCUdoc-20.html">Previous</A>
<A HREF="SDCCUdoc.html#toc21">Contents</A>
<HR>
-<H2><A NAME="xstack"></A> <A NAME="s21">21. External Stack.</A> </H2>
+<H2><A NAME="Interface_asm"></A> <A NAME="s21">21. Interfacing with assembly routines.</A> </H2>
-<P>The external stack is located at the start of the external ram segment
-, and is 256 bytes in size. When --xstack option is used to compile the program
-, the parameters and local variables of all reentrant functions are allocated
-in this area. This option is provided for programs with large stack space requirements.
-When used with the --stack-auto option, all parameters and local variables
-are allocated on the external stack (note support libraries will need to be
-recompiled with the same options).
-<P>The compiler outputs the higher order address byte of the external ram
-segment into PORT P2, therefore when using the External Stack option, this
-port MAY NOT be used by the application program.
+<H2><A NAME="ss21.1">21.1 Global registers used for parameter passing.</A>
+ </H2>
+
+<P>By default the compiler uses the global registers "DPL,DPH,B,ACC" to pass
+the first parameter to a routine, the second parameter onwards is either allocated
+on the stack (for reentrant routines or --stack-auto is used) or in the internal
+/ external ram (depending on the memory model).
+<H3>Assembler routine non-reentrant </H3>
+
+<P>In the following example the function<B> cfunc</B> calls an assembler routine
+<B>asm_func</B>, which takes two parameters.
+<P>extern int asm_func( unsigned short, unsigned short);
+<P>
+<PRE>
+
+int c_func (unsigned short i, unsigned short j)
+{
+ return
+ asm_func(i,j);
+}
+int main()
+{
+ return c_func(10,9);
+}
+
+</PRE>
+<P>The corresponding assembler function is:-
+<P>
+<PRE>
+ .globl _asm_func_PARM_2
+ .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
+
+</PRE>
+<P>Note 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.
+<P>The parameter naming convention is <B>_<function_name>_PARM_<n>,</B>
+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 <CODE></CODE><CODE><B>varaible name for
+the second parameter will be _<function_name>_PARM_2.</B></CODE>
+<P>Assemble the assembler routine with the following command.
+<P>
+<PRE>
+asx8051 -losg asmfunc.asm
+
+</PRE>
+<P>Then compile and link the assembler routine to the C source file with the
+following command,
+<P>
+<PRE>
+sdcc cfunc.c asmfunc.rel
+
+</PRE>
+<H3>Assembler routine is reentrant </H3>
+
+<P>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.
+<P>extern int asm_func( unsigned short, unsigned short);
+<P>
+<PRE>
+ int c_func (unsigned short i, unsigned short j) reentrant
+{
+
+ return asm_func(i,j);
+}
+int main()
+{
+ return c_func(10,9);
+
+}
+
+</PRE>
+<P>The corresponding assembler routine is.
+<P>
+<PRE>
+ .globl _asm_func
+_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
+
+</PRE>
+<P>The 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.
+<H2><A NAME="ss21.2">21.2 With --noregparms option.</A>
+ </H2>
+
+<P>When the source is compiled with --noregparms option , space is allocated
+for each of the parameters passed to a routine.
+<H3>Assembler routine non-reentrant. </H3>
+
+<P>In the following example the function<B> cfunc</B> calls an assembler routine
+<B>asm_func</B>, which takes two parameters.
+<P>
+<PRE>
+extern int asm_func( unsigned short, unsigned short);
+int c_func (unsigned short i, unsigned short j)
+{
+ return
+ asm_func(i,j);
+}
+int main()
+{
+ return c_func(10,9);
+}
+
+</PRE>
+<P>The corresponding assembler function is:-
+<P>
+<PRE>
+ .globl _asm_func_PARM_1
+ .globl _asm_func_PARM_2
+
+ .globl _asm_func
+ .area OSEG
+_asm_func_PARM_1: .ds 1
+_asm_func_PARM_2:
+ .ds 1
+ .area CSEG
+_asm_func:
+ mov a,_asm_func_PARM_1
+
+ add a,_asm_func_PARM_2
+ mov dpl,a
+ mov
+ dpl,#0x00
+ ret
+
+</PRE>
+<P>Note 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.
+<P>The parameter naming convention is <B>_<function_name>_PARM_<n>,</B>
+where n is the parameter number starting from 1, and counting from the left.
+i.e. the <CODE></CODE><CODE><B>left-most parameter name will be _<function_name>_PARM_1.</B></CODE>
+<P>Assemble the assembler routine with the following command.
+<P>
+<PRE>
+asx8051 -losg asmfunc.asm
+
+</PRE>
+<P>Then compile and link the assembler routine to the C source file with the
+following command,
+<P>
+<PRE>
+sdcc cfunc.c asmfunc.rel
+
+</PRE>
+<H3>Assembler routine is reentrant. </H3>
+
+<P>In this case the parameters 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.
+<P>extern int asm_func( unsigned short, unsigned short);
+<P>
+<PRE>
+ int c_func (unsigned short i, unsigned short j) reentrant
+{
+
+ return asm_func(i,j);
+}
+int main()
+{
+ return c_func(10,9);
+
+}
+
+</PRE>
+<P>The corresponding assembler routine is.
+<P>
+<PRE>
+ .globl _asm_func
+_asm_func:
+ push _bp
+ mov _bp,sp
+
+ mov a,_bp
+ clr c
+ add a,#0xfd
+ mov
+ r0,a
+ mov a,_bp
+ clr c
+ add a,#0xfc
+
+ mov r1,a
+ mov a,@r0
+ add a,@r1
+ mov dpl,a
+
+ mov dph,#0x00
+ mov sp,_bp
+ pop _bp
+ ret
+
+</PRE>
+<P>The 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.
<HR>
<A HREF="SDCCUdoc-22.html">Next</A>
<A HREF="SDCCUdoc-20.html">Previous</A>