Mercurial > hg > Members > kono > nitros9-code
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-- > 0 && *str!=0xff; ++i) +? if(smatch(str++,pat,patlen)) +? return i; +? } +? +? static smatch(str,pat,patlen) +? register char *str,*pat; +? int patlen; +? { +? while(patlen-- > 0 && *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-- >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(&number,realarg); /* get the BASIC09 real */ + number *= 2.; /* number times two*/ + putbreal(realarg,&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<5; ++i) + for(j=1; j<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: