changeset 652:7fb3d02e04b0

Appendix C is finished
author roug
date Mon, 16 Dec 2002 17:08:16 +0000
parents ac4142f99b21
children 06e11c941478
files docs/ccguide/basic09.appendix
diffstat 1 files changed, 371 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/docs/ccguide/basic09.appendix	Mon Dec 16 17:08:02 2002 +0000
+++ b/docs/ccguide/basic09.appendix	Mon Dec 16 17:08:16 2002 +0000
@@ -16,6 +16,47 @@
 127.
 </para>
 <para>
+BASIC09 strings are terminated by 0xff (255). C strings are
+terminated by 0x00 (0). If the BASIC09 string is of maximum length,
+the terminator is not present. Therefore, string length as well as
+terminator checks must be performed on BASIC09 strings when
+processing them with C functions.
+</para>
+<para>
+The floating point format used by C and BASIC09 are not directly
+compatible. Since both use a binary floating point format it is
+possible to convert BASIC09 reals to C doubles and vice-versa.
+</para>
+<para>
+Multi-dimensional arrays are stored by BASIC09 in a different manner
+than C. Multi-dimensional arrays are stored by BASIC09 in a column-wise
+manner; C stores them row-wise. Consider the following example:
+</para>
+<screen>
+BASIC09 matrix:  DIM array(5,3):INTEGER
+The elements in consecutive memory locations (read left to
+right, line by line) are stored as:
+(1,1),(2,1),(3,1),(4,1),(5,1)
+(1,2),(2,2),(3,2),(4,2),(5,2)
+(1,3),(2,3),(3,3),(4,3),(5,3)
+
+C matrix:  int array[5][3];
+(1,1),(1,2),(1,3)
+(2,1),(2,2),(2,3)
+(3,1),(3,2),(3,3)
+(4,1),(4,2),(4,3)
+(5,1),(5,2),(5,3)
+</screen>
+<para>
+Therefore to access BASIC09 matrix elements in C, the subscripts
+must be transposed. To access element array(4,2) in BASIC09 use
+array[2][4] in C.
+</para>
+<para>
+The details on interfacing BASIC09 to C are best described by
+example. The remainder of this appendix is a mini tutorial
+demonstrating the process starting with simple examples and working
+up to more complex ones.
 </para>
 
 <section>
@@ -69,7 +110,7 @@
 cc2 bt1.c -rs
 </para>
 </informalexample>
-CC2 uses the Level-Two compiler. Replace cc2 with cc1 if you are
+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
@@ -123,12 +164,179 @@
 <section>
 <title>Example 2 - More Complex Integer Aritmetic Case</title>
 <para>
+The next example shows how static memeory can be used. Take the
+C function from the previous example and modify it to add the number
+of times it has been entered to the increment:
+</para>
+<screen>
+buld bt2.c
+? static int entcnt;
+?
+? addints(cnt,cmem,cmemsiz,value,s1,arg1,s2,arg2,s2,arg3,s4)
+? char *cmem;
+? int *value,*arg1,*arg2,*arg3;
+? {
+? #asm
+?  ldy 6,s base of static area
+? #endasm
+?     int j = *value + entcnt++;
+?
+?     *arg1 += j;
+?     *arg2 += j;
+?     *arg3 += j;
+? }
+?
+</screen>
+<para>
+This example differs from the first in a number of ways. The line
+"static in entcnt" defines an integer value name entcnt global to
+bt2.c. The parameter cmem and the line "char *cmen" indicate a
+character array. The array will be used in the C function for
+global/static storage. C accesses non-auto and non-register
+variables indexed off the Y register. cstart.r normally takes care
+of setting this up. Since cstart.r will not be used for this
+BASIC09-callable function, we have to take measures to make sure the
+Y register points to a valid and sufficiently large area of memory.
+The line "ldy 6,s" is assembly language code embedded in C source
+that loads the Y register with the first parameter passed by
+BASIC09. If the first parameter in the BASIC09 RUN statement is an
+array, and the "ldy 6,s" is placed <emphasis>immediately</emphasis> after the
+"{" opening the function body, the offset will always be "6,s". Note the line
+beginning "int j = ...". This line uses an initializer which, in
+this case, is allowed because <varname>j</varname> is of class "auto".
+No classes but "auto" and "register" can be initialized in BASIC09-callable C
+functions.
+</para>
+<para>
+To compile this function, the following C compiler command line is
+used:
+<screen>
+cc2 bt2.c -rs
+</screen>
+Again, the -r option leaves bt2.r as output and the -s option
+suppresses stack checking.
+</para>
+<para>
+Normally, the linker considers it to be an error if the "-b=" option
+appears and the final linked module requires a data memory
+allocation. In our case here, we require a data memory allocation
+and we will provide the code to make sure everything is set up
+correctly. The "-t" linker option causes the linker to print the
+total data memory requirement so we can allow for it rather than
+complaining about it. Our linker command line is:
+<screen>
+c.link bt2.r -o=addints -b=addints -r
+</screen>
+</para>
+<para>
+The linker will respond with "BASIC09 static data size is 2 bytes".
+We must make sure <varname>cmem</varname> points to at least 2 bytes of memory. The
+memory should be zeroed to conform to C specifications.
+</para>
+<para>
+Enter the following BASIC09 program:
+</para>
+<screen>
+PROCEDURE btest
+DIM i,j,k,n;INTEGER
+DIM cmem(10):INTEGER
+FOR i=1 TO 10
+     cmem(i)=0
+NEXT i
+FOR n=1 TO 5
+     i=1
+     j=132
+     k=-1033
+     RUN addints(cmem,4,i,j,k)
+     PRINT i,j,k
+NEXT n
+END
+</screen>
+<para>
+This program is similar to the previous example. Our area for data
+memory is a 10-integer array (20 bytes) which is way more than the 2
+bytes for this example. It is better to err on the generous side.
+Cmem is an integer array for convenience in initializing it to zero
+(per C data memory specifications). When the program is run, it
+calls addints 5 times with the same data values. Because addints
+add the number of times it was called to the value, the i,j,k
+values should be 4+number of times called. When run, the program prints:
+<screen>
+     5       136     -1029
+     6       137     -1028
+     7       138     -1027
+     8       139     -1026
+     9       140     -1025
+</screen>
+Works again!
 </para>
 </section>
 
 <section>
 <title>Example 3 - Simple String Manipulation</title>
 <para>
+This example shows how to access BASIC09 strings through C
+functions. For this example, write the C version of SUBSTR.
+</para>
+<screen>
+build bt3.c
+? /* Find substring from BASIC09 string:
+?         RUN findstr(A$,B$,findpos)
+?    returns in fndpos the position in A$ that B$ was found or
+?    0 if not found.  A$ and B$ must be strings, fndpos must be
+?    INTEGER.
+? */
+? findstr(cnt,string,strcnt,srchstr,srchcnt,result);
+? char *string,*srchstr;
+? int strcnt, srchcnt, *result;
+? {
+?     *result = finder(string,strcnt,srchstr,srchcnt);
+? }
+?
+? static finder(str,strlen,pat,patlen)
+? char *str,*pat;
+? int strlen,patlen;
+? {
+?     int i;
+?     for(i=1;strlen-- &gt; 0 &amp;&amp; *str!=0xff; ++i)
+?         if(smatch(str++,pat,patlen))
+?             return i;
+? }
+?
+? static smatch(str,pat,patlen)
+? register char *str,*pat;
+? int patlen;
+? {
+?     while(patlen-- &gt; 0 &amp;&amp; *pat != 0xff)
+?         if(*str++ != *pat++)
+?             return 0;
+?     return 1;
+? }
+?
+</screen>
+<para>
+Compile this program:
+<screen>
+    cc2 bt3.c -rs
+</screen>
+And link it:
+<screen>
+    c.link bt3.r -o=findstr -b=findstr
+</screen>
+The BASIC09 test program is:
+<screen>
+PROCEDURE btest
+DIM a,b:STRING[20]
+DIM matchpos:INTEGER
+LOOP
+INPUT "String ",a
+INPUT "Match  ",b
+RUN findstr(a,b,matchpos)
+PRINT "Matched at position ",matchpos
+ENDLOOP
+</screen>
+When this program is run, it should print the position where the
+matched string was found in the source string.
 </para>
 </section>
 
@@ -234,7 +442,7 @@
      int maxlen;
 
      for (maxlen = maxstr; *str1 == *str2 ;++str1)
-          if (maxlen-- >0 || *str2++ == 0xff)
+          if (maxlen-- &gt;0 || *str2++ == 0xff)
                return 0;
      return (*str1 - *str2);
 }
@@ -316,6 +524,143 @@
 </para>
 <programlisting>
 flmult(cnt,cmemory,cmemsiz,realarg,realsize)
+int cnt;            /* number of arguments */
+char *cmemory;      /* pointer to some memory for C use */
+double *realarg;    /* pointer to real */
+{
+#asm
+ ldy 6,s get static memory address
+#endasm
+
+     double number;
+
+     getbreal(&amp;number,realarg);      /* get the BASIC09 real */
+     number *= 2.;                   /* number times two*/
+     putbreal(realarg,&amp;number);      /* give back to BASIC09 */
+
+}
+
+/* getreal(creal,breal)
+     get a 5-byte real from BASIC09 format to C format */
+
+getbreal(creal,breal)
+double *creal,*breal;
+{
+     register char *cr,*br;   /* setup some char pointers */
+
+     cr = creal;
+     br = breal;
+#asm
+*  At this point U reg contains address of C double
+*                  0,s contains address of BASIC09 real
+ ldx 0,s get address of B real
+
+ clra clear the C double
+ clrb
+ std 0,u
+ std 2,u
+ std 4,u
+ stb 6,u
+ ldd 0,x
+ beq g3 BASIC09 real is zero
+
+ ldd 1,x get hi B mantissa
+ and a #$7f clear place for sign
+ std 0,u put hi C matissa
+ ldd 3,x get lo B mantissa
+ andb #$fe mask off sign
+ std 2,u put lo C mantissa
+ lda 4,x get B sign byte
+ lsra shift out sign
+ bcc g1
+ lda 0,u get C sign byte
+ ora #$80 tun on sign
+ sta 0,u put C sign byte
+g1 lda 0,x get B exponent
+ suba #128 excess 128
+ sta 7,u put C exponent
+g3 clra clear carry
+#endasm
+
+}
+
+/* putbreal(breal,creal)
+     put C format double into a 5-byte real from BASIC09 */
+
+putbreal(breal,creal)
+double *breal,*creal;
+{
+     register char *cr,*br;   /* setup some pointers */
+
+     cr = creal;
+     br = breal;
+#asm
+*  At this point U reg contains address of C double
+*                  0,s contains address of BASIC09 real
+ ldx 0,s get address of B real
+
+ lda 7,u get C exponent
+ bne p0 not zero?
+ clra clear the BASIC09
+ clrb real
+ std 0,x
+ std 2,x
+ std 4,x
+ bra p3 and exit
+
+p0 ldd 0,u get hi C mantissa
+ ora #$80 this bit always on for normalized real
+ std 1,x put hi B mantissa
+ ldd 2,u get lo C mantissa
+ std 3,x put lo B mantissa
+ incb round mantissa
+ bne p1
+ inc 3,x
+ bne p1
+ inc 2,x
+ bne p1
+ inc 1,x
+p1 andb #$fe turn off sign
+ stb 4,x put B sign byte
+ lda 0,u get C sign byte
+ lsla shift out sign
+ bcc p2 bra if positive
+ orb #$01 turn on sign
+ stb 4,x put B sign byte
+p2 lda 7,u get C exponent
+ adda #128 less 128
+ sta 0,x put B exponent
+p3 clra clear carry
+#endasm
+}
+
+
+/* replace cstart.r definitions for BASIC09 */
+#asm
+_stkcheck:
+_stkchec:
+ rts
+
+ vsect
+_flacc: rmb 8
+errno: rmb 2
+ endsect
+#endasm
+</programlisting>
+<para>
+BASIC09 calling program:
+</para>
+<programlisting>
+PROCEDURE btest
+DIM a:REAL
+DIM i:INTEGER
+DIM cmemory:STRING[32]
+a=1.
+FOR i=1 TO 10
+  RUN flmult(cmemory,a)
+  PRINT a
+NEXT i
+END
 </programlisting>
 </section>
 
@@ -327,6 +672,30 @@
 </para>
 <programlisting>
 matmult(cnt,cmemory,cmemsiz,matxaddr,matxsize,scalar,scalsize)
+char *cmemory;       /* pointer to some memory for C use */
+int matxaddr[5][3];  /* pointer a double dim integer array */
+int *scalar;         /* pointer to integer */
+{
+#asm
+ ldy 6,s get static memory address
+#endasm
+
+     int i,j;
+
+     for(i=0; i&lt;5; ++i)
+          for(j=1; j&lt;3; ++j)
+               matxaddr[j][i]  *=  *scalar;  /* multiply by value */
+}
+#asm
+_stkcheck:
+_stkchec:
+ rts
+
+ vsect
+_flacc: rmb 8
+errno: rmb 2
+ endsect
+#endasm
 </programlisting>
 <para>
 BASIC09 calling program: