view docs/ccguide/basic09.appendix @ 565:0e84dcd81835

Several functions ready.
author roug
date Thu, 31 Oct 2002 22:05:32 +0000
parents 7d803625ead8
children 594a34d027f8
line wrap: on
line source

<appendix>
<title>Interfacing to Basic09</title>
<para>
The object code generated by the Microware C Compiler can be made
callable from the BASIC09 "RUN" statement. Certain portions of a
BASIC09 program written in C can have a drmatic effect on execution
speed. To effectively utilize this feature, one must be familiar
with both C and BASIC09 internal data representation and procedure
calling protocol.
</para>

<section>
<title>Example 1 - Simple Integer Aritmetic Case</title>
<para>
This first example illustrates a simple case. Write a C function to
add an integer value to three integer variables.
<screen>
build bt1.c
? addints(cnt,value,s1,arg1,s2,arg2,s2,arg3,s4)
? int *value,*arg1,*arg2,*arg3;
? {
?     *arg1 += *value;
?     *arg2 += *value;
?     *arg3 += *value;
? }
?
</screen>
</para>
<para>
That's the C function. The name of the function is "addints". The
name is information for C and c.link; BASIC09 will not know anything
about the name. Page 9-13 of the BASIC09 Reference manual describes
how BASIC09 passes parameters to machine language modules. Since
BASIC09 and C pass parameters in a similar fashion, it is easy to
access BASIC09 values. The first parameter on the BASIC09 stack is
a two-byte count of the number of following parameter pairs. Each
pair consists of an address and size of value. For most C
functions, the parameter count and pair size is not used. The
address, however, is the useful piece of information. The address
is declared in the C function to always be a "pointer to..." type.
BASIC09 always passes addresses to procedures, even for constant
values. The arguments cnt, s1, s2, s3 and s4 are just place holders
to indicate the presence of the parameter count and argument sizes
on the stack. These can be used to check validity of the passed
arguments if desired.
</para>
<para>
The line "int *value,*arg1,*arg2,*arg3" declares the parameters (in
this case all "pointers to int"), so the compiler will generate the
correct code to access the BASIC09 values. The remaining lines
increment each arg by the passed value. Notice that a simple
arithmetic operation is performed here (addition), so C will not
have to call a library function to do the operation.
</para>
<para>
To compile this function, the following C compiler command line is
used:
<informalexample>
<para>
cc2 bt1.c -rs
</para>
</informalexample>
CC2 uses the Level-Two compiler. Replace cc2 with cc1 if you are
using the Level-One compiler. The -r option causes the compiler to
leave bt1.r as output, ready to be linked. The -s option suppresses
the call to the stack-checking function. Since we will be making a
module for BASIC09, cstart.r will not be used. Therefore, no
initialized data, static data, or stack checking is allowed. More
on this later.
</para>
<para>
The bt1.r file must now be converted to a loadable module that
BASIC09 can link to by using a special linking technique as follows:
<informalexample>
<para>
c.link bt1.r -b=addints -o=addints
</para>
</informalexample>
This command tells the linker to read bt1.r as input. The option
"-b=addints" tells the linker to make the output file a module that
BASIC09 can link to and that the function "addints" is to be the
entrypoint in the module. You may give many input files to c.link
in this mode. It resolves references in the normal fashion. The
name given to the "-b=" option indicates which of the functions is
to be entered directly by the BASIC09 RUN command. The option
"-o=addints" says what the name of the output file is to be, in this
case "addints". This name should be the name used in the BASIC09
RUN command to call the C procedure. The name given in "-o="
option is the name of the procedure to RUN. The "-b=" option is
merely information to the linker so it can fill in the correct
module entrypoint offset.
</para>

<para>
Enter the following BASIC09 program:
<programlisting>
PROCEDURE btest
DIM i,j,k:INTEGER
i=1
j=132
k=-1033
RUN addints(4,i,j,k)
PRINT i,j,k
END
</programlisting>
When this procedure is RUN, it should print:
<screen>
5       136     -1029
</screen>
indicating that our C function worked!
</para>
</section>

<section>
<title>Example 2 - More Complex Integer Aritmetic Case</title>
<para>
</para>
</section>

<section>
<title>Example 3 - Simple String Manipulation</title>
<para>
</para>
</section>

<section>
<title>Example 4 - Quicksort</title>
<para>
The next example programs demonstrate how one might implement a
quicksort written in C to sort some BASIC09 data.
</para>
<para>
C integer quicksort program:
</para>
<programlisting>
#define swap(a,b) { int t; t=a; a=b; b=t; }

/* qsort to be called by BASIC09:
     dim d(100):INTEGER  any size INTEGER array
     run cqsort(d,100)   calling qsort.
*/

qsort(argcnt,iarray,iasize,icount,icsiz)
int  argcnt,     /* BASIC09 argument count */
     iarrary[],  /* Pointer to BASIC09 integer array */
     iasize,     /* and it's size */
     *icount,    /* Pointer to BASIC09 (sort count) */
     icsiz;      /* Size of integer */
{
     sort(iarray,0,*icount);  /* initial qsort partition */
}

/* standard quicksort algorithm from Horowitz-Sahni */
static sort(a,m,n)
register int *a,m,n;
{
     register i,j,x;
     
     if(m &lt; n) {
          i = m;
	  j = n + 1;
	  x = a[m];
	  for(;;) {
	       do i += 1; while(a[i] &lt; x);  /* left partition */
	       do j -= 1; while(a[j] &gt; x);  /* right partition */
	       if(i &lt; j)
	            swap(a[i],a[j])          /* swap */
		    else break;
	  }
	  swap(a[m],a[j]);
	  sort(a,m,j-1);                     /* sort left */
	  sort(a,j+1,n);                     /* sort right */
     }
}
</programlisting>
<para>
The BASIC09 program is:
</para>
<programlisting>
PROCEDURE sorter
DIM i,n,d(1000):INTEGER
n=1000
i=RND(-(PI))
FOR i=1 to n
d(i):=INT(RND(1000))
NEXT i
PRINT "Before:"
RUN prin(1,n,d)
RUN qsortb(d,n)
PRINT "After:"
RUN prin(1,n,d)
END

PROCEDURE prin
PARAM n,m,d(1000):INTEGER
DIM i:INTEGER
FOR i=n TO m
PRINT d(i); " ";
NEXT i
PRINT
END
</programlisting>
</section>
</appendix>