Mercurial > hg > Members > kono > nitros9-code
view docs/ccguide/basic09.appendix @ 636:94ff9d15614f
Convert to Docbook XML format
author | roug |
---|---|
date | Sun, 08 Dec 2002 11:09:09 +0000 |
parents | 594a34d027f8 |
children | 7fb3d02e04b0 |
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> <para> C type "int" and BASIC09 type "INTEGER" are identical; both are two byte two's complement integers. C type "char" and BASIC09 type "BYTE" and "BOOLEAN" are also identical. Keep in mind that C will sign-extend characters for comparisons yielding the range -128 to 127. </para> <para> </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 < n) { i = m; j = n + 1; x = a[m]; for(;;) { do i += 1; while(a[i] < x); /* left partition */ do j -= 1; while(a[j] > x); /* right partition */ if(i < 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> <para> C string quicksort program: </para> <programlisting> /* qsort to be called by BASIC09: dim cmemory:STRING[10] This should be at least as large as the linker says the data size should be. dim d(100):INTERGER Any size INTEGER array. run cqsort(cmemory,d,100) calling qsort. Note that the pro- cedure name run in the linked OS-9 subroutine module. The module name need not be the name of the C func- tion. */ int maxstr; /* string maximum length */ static strbcmp(str1,str2) /* basic09 string compare */ register char *str1,*str2; { int maxlen; for (maxlen = maxstr; *str1 == *str2 ;++str1) if (maxlen-- >0 || *str2++ == 0xff) return 0; return (*str1 - *str2); } cssort(argcnt,stor,storsiz,iaarray,iasize,elemlen,elsiz, icount,icsiz) int argcnt; /* BASIC09 argument count */ char *stor; /* Pointer to string (C data storage) */ char iarray[]; /* Pointer to BASIC09 integer array */ int iasize, /* and it's size */ *elemlen, /* Pointer integer value (string length) */ elsiz, /* Size of integer */ *icount, /* Pointer to integer (sort count) */ icsiz; /* Size of integer */ { /* The following assembly code loads Y with the first arg provided by BASIC09. This code MUST be the first code in the function after the declarations. This code assumes the address of the data area is the first parameter in the BASIC09 RUN command. */ #asm ldy 6,s get addr for C storage #endasm /* Use the C library qsort function to do the sort. Our own BASIC09 string compare function will compare the strings. */ qsort(iarray,*icount,maxstr=*elemlen,strbcmp); } /* define stuff cstart.r normally defines */ #asm _stkcheck: rts dummy stack check function vsect errno: rmb 2 C function system error number _flacc: rmb 8 C library float/long accumulator endsect #endasm </programlisting> <para> The BASIC09 calling programs: (words file contains strings to sort) </para> <programlisting> PROCEDURE ssorter DIM a(200):STRING[20] DIM cmemory:STRING[20] DIM i,n:INTEGER DIM path:INTEGER OPEN #path,"words":READ n=100 FOR i=1 to n INPUT #path,a(i) NEXT i CLOSE #path RUN prin(a,n) RUN cssort(cmemory,a,20,n) RUN prin(a,n) END PROCEDURE prin PARAM a(100):STRING[20]; n:INTEGER DIM i:INTEGER FOR i=1 TO n PRINT i; " "; a(i) NEXT i PRINT i END </programlisting> </section> <section> <title>Example 5 - Floating Point</title> <para> The next example shows how to access BASIC09 reals from C functions: </para> <programlisting> flmult(cnt,cmemory,cmemsiz,realarg,realsize) </programlisting> </section> <section> <title>Example 6 - Matrix Elements</title> <para> The last program is an example of accessing BASIC09 matrix elements. The C program: </para> <programlisting> matmult(cnt,cmemory,cmemsiz,matxaddr,matxsize,scalar,scalsize) </programlisting> <para> BASIC09 calling program: </para> <programlisting> PROCEDURE btest DIM im(5,3):INTEGER DIM i,j:INTEGER DIM cmem:STRING[32] FOR i=1 TO 5 FOR j=1 TO 3 READ im(i,j) NEXT j NEXT i DATA 11,13,7,3,4,0,5,7,2,8,15,0,0,14,4 FOR i=1 TO 5 PRINT im(i,1),im(i,2),im(i,3) NEXT i PRINT RUN matmult(cmem,im,64) FOR i=1 TO 5 PRINT im(i,1),im(i,2),im(i,3) NEXT i END </programlisting> </section> </appendix>