<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <!--Converted with LaTeX2HTML 2008 (1.71) original version by: Nikos Drakos, CBLU, University of Leeds * revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan * with significant contributions from: Jens Lippmann, Marek Rouchal, Martin Wilck and others --> <HTML> <HEAD> <TITLE>3.13.1 A Step by Step Introduction</TITLE> <META NAME="description" CONTENT="3.13.1 A Step by Step Introduction"> <META NAME="keywords" CONTENT="sdccman"> <META NAME="resource-type" CONTENT="document"> <META NAME="distribution" CONTENT="global"> <META NAME="Generator" CONTENT="LaTeX2HTML v2008"> <META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> <LINK REL="STYLESHEET" HREF="sdccman.css"> <LINK REL="next" HREF="node83.html"> <LINK REL="previous" HREF="node81.html"> <LINK REL="up" HREF="node81.html"> <LINK REL="next" HREF="node83.html"> </HEAD> <BODY > <!--Navigation Panel--> <A NAME="tex2html1907" HREF="node83.html"> <IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" SRC="next.png"></A> <A NAME="tex2html1901" HREF="node81.html"> <IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" SRC="up.png"></A> <A NAME="tex2html1895" HREF="node81.html"> <IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" SRC="prev.png"></A> <A NAME="tex2html1903" HREF="node1.html"> <IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" SRC="contents.png"></A> <A NAME="tex2html1905" HREF="node191.html"> <IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index" SRC="index.png"></A> <BR> <B> Next:</B> <A NAME="tex2html1908" HREF="node83.html">3.13.2 Naked Functions</A> <B> Up:</B> <A NAME="tex2html1902" HREF="node81.html">3.13 Inline Assembler Code</A> <B> Previous:</B> <A NAME="tex2html1896" HREF="node81.html">3.13 Inline Assembler Code</A> <B> <A NAME="tex2html1904" HREF="node1.html">Contents</A></B> <B> <A NAME="tex2html1906" HREF="node191.html">Index</A></B> <BR> <BR> <!--End of Navigation Panel--> <H2><A NAME="SECTION004131000000000000000"></A><A NAME="sub:A-Step-by_Assembler_Introduction"></A> <BR> 3.13.1 A Step by Step Introduction </H2> <P> Starting from a small snippet of c-code this example shows for the MCS51 how to use inline assembly, access variables, a function parameter and an array in xdata memory. The example uses an MCS51 here but is easily adapted for other architectures. This is a buffer routine which should be optimized: <BLOCKQUOTE> <TT><FONT SIZE="-1">unsigned char __far<A NAME="2110"></A><A NAME="2111"></A> __at<A NAME="2112"></A><A NAME="2113"></A>(0x7f00) buf[0x100];<A NAME="2116"></A></FONT></TT> <BR><TT><FONT SIZE="-1">unsigned char head, tail; /* if interrupts<A NAME="2118"></A> are involved see</FONT></TT> <BR><TT><FONT SIZE="-1"> section <A HREF="node68.html#sub:Common-interrupt-pitfall-volatile">3.9.1.1</A> about</FONT></TT><TT><B><FONT SIZE="-1">volatile</FONT></B></TT><FONT SIZE="-1"> </FONT><TT><FONT SIZE="-1">*/</FONT></TT> <BR><TT></TT> <BR><TT><FONT SIZE="-1">void to_buffer( unsigned char c ) </FONT></TT> <BR><TT><FONT SIZE="-1">{</FONT></TT> <BR><TT><FONT SIZE="-1"> if( head != (unsigned char)(tail-1) ) /* cast</FONT></TT><FONT SIZE="-1"> </FONT><TT><B><FONT SIZE="-1">needed</FONT></B></TT><TT><FONT SIZE="-1">to avoid promotion<A NAME="2131"></A><A NAME="2132"></A> to integer */</FONT></TT> <BR><TT><FONT SIZE="-1"> buf[ head++ ] = c; /* access to a 256 byte aligned array */</FONT></TT> <BR><TT><FONT SIZE="-1">} </FONT></TT></BLOCKQUOTE> <P> <BLOCKQUOTE> </BLOCKQUOTE> If the code snippet (assume it is saved in buffer.c) is compiled with SDCC then a corresponding buffer.asm file is generated. We define a new function <TT>to_buffer_asm()</TT> in file buffer.c in which we cut and paste the generated code, removing unwanted comments and some ':'. Then add ''<B>__asm</B>'' and ''<B>__endasm;</B>''<A NAME="tex2html37" HREF="footnode.html#foot2146"><SUP>3.6</SUP></A> to the beginning and the end of the function body: <BLOCKQUOTE> <TT><FONT SIZE="-1">/* With a cut and paste from the .asm file, we have something to start with.</FONT></TT> <BR><TT><FONT SIZE="-1"> The function is not yet OK! (registers aren't saved) */ </FONT></TT> <BR><TT><FONT SIZE="-1">void to_buffer_asm( unsigned char c ) </FONT></TT> <BR><TT><FONT SIZE="-1">{ </FONT></TT> <BR><TT><FONT SIZE="-1"> __asm<A NAME="2152"></A><A NAME="2153"></A></FONT></TT> <BR><TT><FONT SIZE="-1"> mov r2,dpl </FONT></TT> <BR><TT><FONT SIZE="-1">;buffer.c if( head != (unsigned char)(tail-1) ) /* cast</FONT></TT><FONT SIZE="-1"> </FONT><TT><B><FONT SIZE="-1">needed</FONT></B></TT><TT><FONT SIZE="-1">to avoid promotion<A NAME="2159"></A><A NAME="2160"></A> to integer */</FONT></TT> <BR><TT><FONT SIZE="-1"> mov a,_tail </FONT></TT> <BR><TT><FONT SIZE="-1"> dec a </FONT></TT> <BR><TT><FONT SIZE="-1"> mov r3,a </FONT></TT> <BR><TT><FONT SIZE="-1"> mov a,_head </FONT></TT> <BR><TT><FONT SIZE="-1"> cjne a,ar3,00106$ </FONT></TT> <BR><TT><FONT SIZE="-1"> ret</FONT></TT> <BR><TT><FONT SIZE="-1">00106$: </FONT></TT> <BR><TT><FONT SIZE="-1">;buffer.c buf[ head++ ] = c; /* access to a 256 byte aligned array */<A NAME="2173"></A></FONT></TT> <BR><TT><FONT SIZE="-1"> mov r3,_head </FONT></TT> <BR><TT><FONT SIZE="-1"> inc _head </FONT></TT> <BR><TT><FONT SIZE="-1"> mov dpl,r3 </FONT></TT> <BR><TT><FONT SIZE="-1"> mov dph,#(_buf >> 8) </FONT></TT> <BR><TT><FONT SIZE="-1"> mov a,r2 </FONT></TT> <BR><TT><FONT SIZE="-1"> movx @dptr,a </FONT></TT> <BR><TT><FONT SIZE="-1">00103$: </FONT></TT> <BR><TT><FONT SIZE="-1"> ret</FONT></TT> <BR><TT><FONT SIZE="-1"> __endasm<A NAME="2182"></A><A NAME="2183"></A>;</FONT></TT> <BR><TT><FONT SIZE="-1">} </FONT></TT></BLOCKQUOTE> <P> <BLOCKQUOTE> </BLOCKQUOTE> The new file buffer.c should compile with only one warning about the unreferenced function argument 'c'. Now we hand-optimize the assembly code and insert an #define USE_ASSEMBLY (1) and finally have: <BLOCKQUOTE> <TT><FONT SIZE="-1">unsigned char __far __at(0x7f00) buf[0x100];</FONT></TT> <BR><TT><FONT SIZE="-1">unsigned char head, tail;</FONT></TT> <BR><TT><FONT SIZE="-1">#define USE_ASSEMBLY (1)</FONT></TT> <BR><TT></TT> <BR><TT><FONT SIZE="-1">#if !USE_ASSEMBLY</FONT></TT> <BR><TT></TT> <BR><TT><FONT SIZE="-1">void to_buffer( unsigned char c )</FONT></TT> <BR><TT><FONT SIZE="-1">{</FONT></TT> <BR><TT><FONT SIZE="-1"> if( head != (unsigned char)(tail-1) )</FONT></TT> <BR><TT><FONT SIZE="-1"> buf[ head++ ] = c;</FONT></TT> <BR><TT><FONT SIZE="-1">}</FONT></TT> <BR><TT></TT> <BR><TT><FONT SIZE="-1">#else</FONT></TT> <BR><TT></TT> <BR><TT><FONT SIZE="-1">void to_buffer( unsigned char c )</FONT></TT> <BR><TT><FONT SIZE="-1">{</FONT></TT> <BR><TT><FONT SIZE="-1"> c; // to avoid warning: unreferenced function argument</FONT></TT> <BR><TT><FONT SIZE="-1"> __asm<A NAME="2207"></A><A NAME="2208"></A></FONT></TT> <BR><TT><FONT SIZE="-1"> ; save used registers here. </FONT></TT> <BR><TT><FONT SIZE="-1"> ; If we were still using r2,r3 we would have to push them here. </FONT></TT> <BR><TT><FONT SIZE="-1">; if( head != (unsigned char)(tail-1) )</FONT></TT> <BR><TT><FONT SIZE="-1"> mov a,_tail</FONT></TT> <BR><TT><FONT SIZE="-1"> dec a</FONT></TT> <BR><TT><FONT SIZE="-1"> xrl a,_head</FONT></TT> <BR><TT><FONT SIZE="-1"> ; we could do an ANL a,#0x0f here to use a smaller buffer (see below)</FONT></TT> <BR><TT><FONT SIZE="-1"> jz t_b_end$</FONT></TT> <BR><TT><FONT SIZE="-1"> ;</FONT></TT> <BR><TT><FONT SIZE="-1">; buf[ head++ ] = c;</FONT></TT> <BR><TT><FONT SIZE="-1"> mov a,dpl ; dpl holds lower byte of function argument</FONT></TT> <BR><TT><FONT SIZE="-1"> mov dpl,_head ; buf is 0x100 byte aligned so head can be used directly</FONT></TT> <BR><TT><FONT SIZE="-1"> mov dph,#(_buf>>8)</FONT></TT> <BR><TT><FONT SIZE="-1"> movx @dptr,a</FONT></TT> <BR><TT><FONT SIZE="-1"> inc _head</FONT></TT> <BR><TT><FONT SIZE="-1"> ; we could do an ANL _head,#0x0f here to use a smaller buffer (see above)</FONT></TT> <BR><TT><FONT SIZE="-1">t_b_end$:</FONT></TT> <BR><TT><FONT SIZE="-1"> ; restore used registers here </FONT></TT> <BR><TT><FONT SIZE="-1"> _endasm<A NAME="2228"></A><A NAME="2229"></A>;</FONT></TT> <BR><TT><FONT SIZE="-1">}</FONT></TT> <BR><TT><FONT SIZE="-1">#endif</FONT></TT></BLOCKQUOTE> <P> <BLOCKQUOTE> </BLOCKQUOTE> The inline assembler code can contain any valid code understood by the assembler, this includes any assembler directives and comment lines. The assembler does not like some characters like ':' or ''' in comments. You'll find an 100+ pages assembler manual in sdcc/sdas/doc/asxhtm.html<A NAME="2234"></A><A NAME="2235"></A> or online at <TT><A NAME="tex2html38" HREF="http://sdcc.svn.sourceforge.net/viewvc/*checkout*/sdcc/trunk/sdcc/sdas/doc/asxhtm.html">http://sdcc.svn.sourceforge.net/viewvc/*checkout*/sdcc/trunk/sdcc/sdas/doc/asxhtm.html</A></TT>. <P> The compiler does not do any validation of the code within the <TT>__asm<A NAME="2237"></A><A NAME="2238"></A> ... __endasm<FONT SIZE="-1"><A NAME="2239"></A><A NAME="2240"></A></FONT>;</TT> keyword pair. Specifically it will not know which registers are used and thus register pushing/popping<A NAME="2242"></A> has to be done manually. <P> It is recommended that each assembly instruction (including labels) be placed in a separate line (as the example shows). When the --<I>peep-asm<A NAME="2243"></A></I> command line option is used, the inline assembler code will be passed through the peephole optimizer<A NAME="2244"></A>. There are only a few (if any) cases where this option makes sense, it might cause some unexpected changes in the inline assembler code. Please go through the peephole optimizer rules defined in file <I>SDCCpeeph.def</I> before using this option. <P> <HR> <!--Navigation Panel--> <A NAME="tex2html1907" HREF="node83.html"> <IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" SRC="next.png"></A> <A NAME="tex2html1901" HREF="node81.html"> <IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" SRC="up.png"></A> <A NAME="tex2html1895" HREF="node81.html"> <IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" SRC="prev.png"></A> <A NAME="tex2html1903" HREF="node1.html"> <IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" SRC="contents.png"></A> <A NAME="tex2html1905" HREF="node191.html"> <IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index" SRC="index.png"></A> <BR> <B> Next:</B> <A NAME="tex2html1908" HREF="node83.html">3.13.2 Naked Functions</A> <B> Up:</B> <A NAME="tex2html1902" HREF="node81.html">3.13 Inline Assembler Code</A> <B> Previous:</B> <A NAME="tex2html1896" HREF="node81.html">3.13 Inline Assembler Code</A> <B> <A NAME="tex2html1904" HREF="node1.html">Contents</A></B> <B> <A NAME="tex2html1906" HREF="node191.html">Index</A></B> <!--End of Navigation Panel--> <ADDRESS> 2011-03-20 </ADDRESS> </BODY> </HTML>