466
|
1 <appendix>
|
|
2 <title>Interfacing to Basic09</title>
|
|
3 <para>
|
468
|
4 The object code generated by the Microware C Compiler can be made
|
|
5 callable from the BASIC09 "RUN" statement. Certain portions of a
|
|
6 BASIC09 program written in C can have a drmatic effect on execution
|
|
7 speed. To effectively utilize this feature, one must be familiar
|
|
8 with both C and BASIC09 internal data representation and procedure
|
|
9 calling protocol.
|
466
|
10 </para>
|
631
|
11 <para>
|
|
12 C type "int" and BASIC09 type "INTEGER" are identical; both are two
|
|
13 byte two's complement integers. C type "char" and BASIC09 type
|
|
14 "BYTE" and "BOOLEAN" are also identical. Keep in mind that C will
|
|
15 sign-extend characters for comparisons yielding the range -128 to
|
|
16 127.
|
|
17 </para>
|
|
18 <para>
|
652
|
19 BASIC09 strings are terminated by 0xff (255). C strings are
|
|
20 terminated by 0x00 (0). If the BASIC09 string is of maximum length,
|
|
21 the terminator is not present. Therefore, string length as well as
|
|
22 terminator checks must be performed on BASIC09 strings when
|
|
23 processing them with C functions.
|
|
24 </para>
|
|
25 <para>
|
|
26 The floating point format used by C and BASIC09 are not directly
|
|
27 compatible. Since both use a binary floating point format it is
|
|
28 possible to convert BASIC09 reals to C doubles and vice-versa.
|
|
29 </para>
|
|
30 <para>
|
|
31 Multi-dimensional arrays are stored by BASIC09 in a different manner
|
|
32 than C. Multi-dimensional arrays are stored by BASIC09 in a column-wise
|
|
33 manner; C stores them row-wise. Consider the following example:
|
|
34 </para>
|
|
35 <screen>
|
|
36 BASIC09 matrix: DIM array(5,3):INTEGER
|
|
37 The elements in consecutive memory locations (read left to
|
|
38 right, line by line) are stored as:
|
|
39 (1,1),(2,1),(3,1),(4,1),(5,1)
|
|
40 (1,2),(2,2),(3,2),(4,2),(5,2)
|
|
41 (1,3),(2,3),(3,3),(4,3),(5,3)
|
|
42
|
|
43 C matrix: int array[5][3];
|
|
44 (1,1),(1,2),(1,3)
|
|
45 (2,1),(2,2),(2,3)
|
|
46 (3,1),(3,2),(3,3)
|
|
47 (4,1),(4,2),(4,3)
|
|
48 (5,1),(5,2),(5,3)
|
|
49 </screen>
|
|
50 <para>
|
|
51 Therefore to access BASIC09 matrix elements in C, the subscripts
|
|
52 must be transposed. To access element array(4,2) in BASIC09 use
|
|
53 array[2][4] in C.
|
|
54 </para>
|
|
55 <para>
|
|
56 The details on interfacing BASIC09 to C are best described by
|
|
57 example. The remainder of this appendix is a mini tutorial
|
|
58 demonstrating the process starting with simple examples and working
|
|
59 up to more complex ones.
|
631
|
60 </para>
|
466
|
61
|
554
|
62 <section>
|
|
63 <title>Example 1 - Simple Integer Aritmetic Case</title>
|
|
64 <para>
|
|
65 This first example illustrates a simple case. Write a C function to
|
|
66 add an integer value to three integer variables.
|
|
67 <screen>
|
|
68 build bt1.c
|
|
69 ? addints(cnt,value,s1,arg1,s2,arg2,s2,arg3,s4)
|
|
70 ? int *value,*arg1,*arg2,*arg3;
|
|
71 ? {
|
|
72 ? *arg1 += *value;
|
|
73 ? *arg2 += *value;
|
|
74 ? *arg3 += *value;
|
|
75 ? }
|
|
76 ?
|
|
77 </screen>
|
|
78 </para>
|
|
79 <para>
|
|
80 That's the C function. The name of the function is "addints". The
|
|
81 name is information for C and c.link; BASIC09 will not know anything
|
|
82 about the name. Page 9-13 of the BASIC09 Reference manual describes
|
|
83 how BASIC09 passes parameters to machine language modules. Since
|
|
84 BASIC09 and C pass parameters in a similar fashion, it is easy to
|
|
85 access BASIC09 values. The first parameter on the BASIC09 stack is
|
|
86 a two-byte count of the number of following parameter pairs. Each
|
|
87 pair consists of an address and size of value. For most C
|
|
88 functions, the parameter count and pair size is not used. The
|
|
89 address, however, is the useful piece of information. The address
|
|
90 is declared in the C function to always be a "pointer to..." type.
|
|
91 BASIC09 always passes addresses to procedures, even for constant
|
|
92 values. The arguments cnt, s1, s2, s3 and s4 are just place holders
|
|
93 to indicate the presence of the parameter count and argument sizes
|
|
94 on the stack. These can be used to check validity of the passed
|
|
95 arguments if desired.
|
|
96 </para>
|
|
97 <para>
|
|
98 The line "int *value,*arg1,*arg2,*arg3" declares the parameters (in
|
|
99 this case all "pointers to int"), so the compiler will generate the
|
|
100 correct code to access the BASIC09 values. The remaining lines
|
|
101 increment each arg by the passed value. Notice that a simple
|
|
102 arithmetic operation is performed here (addition), so C will not
|
|
103 have to call a library function to do the operation.
|
|
104 </para>
|
|
105 <para>
|
|
106 To compile this function, the following C compiler command line is
|
|
107 used:
|
|
108 <informalexample>
|
|
109 <para>
|
|
110 cc2 bt1.c -rs
|
|
111 </para>
|
|
112 </informalexample>
|
652
|
113 Cc2 uses the Level-Two compiler. Replace cc2 with cc1 if you are
|
554
|
114 using the Level-One compiler. The -r option causes the compiler to
|
|
115 leave bt1.r as output, ready to be linked. The -s option suppresses
|
|
116 the call to the stack-checking function. Since we will be making a
|
|
117 module for BASIC09, cstart.r will not be used. Therefore, no
|
|
118 initialized data, static data, or stack checking is allowed. More
|
|
119 on this later.
|
|
120 </para>
|
|
121 <para>
|
|
122 The bt1.r file must now be converted to a loadable module that
|
|
123 BASIC09 can link to by using a special linking technique as follows:
|
|
124 <informalexample>
|
|
125 <para>
|
|
126 c.link bt1.r -b=addints -o=addints
|
|
127 </para>
|
|
128 </informalexample>
|
|
129 This command tells the linker to read bt1.r as input. The option
|
|
130 "-b=addints" tells the linker to make the output file a module that
|
|
131 BASIC09 can link to and that the function "addints" is to be the
|
|
132 entrypoint in the module. You may give many input files to c.link
|
|
133 in this mode. It resolves references in the normal fashion. The
|
|
134 name given to the "-b=" option indicates which of the functions is
|
|
135 to be entered directly by the BASIC09 RUN command. The option
|
|
136 "-o=addints" says what the name of the output file is to be, in this
|
|
137 case "addints". This name should be the name used in the BASIC09
|
|
138 RUN command to call the C procedure. The name given in "-o="
|
|
139 option is the name of the procedure to RUN. The "-b=" option is
|
|
140 merely information to the linker so it can fill in the correct
|
|
141 module entrypoint offset.
|
|
142 </para>
|
|
143
|
|
144 <para>
|
|
145 Enter the following BASIC09 program:
|
|
146 <programlisting>
|
|
147 PROCEDURE btest
|
|
148 DIM i,j,k:INTEGER
|
|
149 i=1
|
|
150 j=132
|
|
151 k=-1033
|
|
152 RUN addints(4,i,j,k)
|
|
153 PRINT i,j,k
|
|
154 END
|
|
155 </programlisting>
|
|
156 When this procedure is RUN, it should print:
|
|
157 <screen>
|
|
158 5 136 -1029
|
|
159 </screen>
|
|
160 indicating that our C function worked!
|
|
161 </para>
|
557
|
162 </section>
|
565
|
163
|
|
164 <section>
|
|
165 <title>Example 2 - More Complex Integer Aritmetic Case</title>
|
|
166 <para>
|
652
|
167 The next example shows how static memeory can be used. Take the
|
|
168 C function from the previous example and modify it to add the number
|
|
169 of times it has been entered to the increment:
|
|
170 </para>
|
|
171 <screen>
|
|
172 buld bt2.c
|
|
173 ? static int entcnt;
|
|
174 ?
|
|
175 ? addints(cnt,cmem,cmemsiz,value,s1,arg1,s2,arg2,s2,arg3,s4)
|
|
176 ? char *cmem;
|
|
177 ? int *value,*arg1,*arg2,*arg3;
|
|
178 ? {
|
|
179 ? #asm
|
|
180 ? ldy 6,s base of static area
|
|
181 ? #endasm
|
|
182 ? int j = *value + entcnt++;
|
|
183 ?
|
|
184 ? *arg1 += j;
|
|
185 ? *arg2 += j;
|
|
186 ? *arg3 += j;
|
|
187 ? }
|
|
188 ?
|
|
189 </screen>
|
|
190 <para>
|
|
191 This example differs from the first in a number of ways. The line
|
|
192 "static in entcnt" defines an integer value name entcnt global to
|
|
193 bt2.c. The parameter cmem and the line "char *cmen" indicate a
|
|
194 character array. The array will be used in the C function for
|
|
195 global/static storage. C accesses non-auto and non-register
|
|
196 variables indexed off the Y register. cstart.r normally takes care
|
|
197 of setting this up. Since cstart.r will not be used for this
|
|
198 BASIC09-callable function, we have to take measures to make sure the
|
|
199 Y register points to a valid and sufficiently large area of memory.
|
|
200 The line "ldy 6,s" is assembly language code embedded in C source
|
|
201 that loads the Y register with the first parameter passed by
|
|
202 BASIC09. If the first parameter in the BASIC09 RUN statement is an
|
|
203 array, and the "ldy 6,s" is placed <emphasis>immediately</emphasis> after the
|
|
204 "{" opening the function body, the offset will always be "6,s". Note the line
|
|
205 beginning "int j = ...". This line uses an initializer which, in
|
|
206 this case, is allowed because <varname>j</varname> is of class "auto".
|
|
207 No classes but "auto" and "register" can be initialized in BASIC09-callable C
|
|
208 functions.
|
|
209 </para>
|
|
210 <para>
|
|
211 To compile this function, the following C compiler command line is
|
|
212 used:
|
|
213 <screen>
|
|
214 cc2 bt2.c -rs
|
|
215 </screen>
|
|
216 Again, the -r option leaves bt2.r as output and the -s option
|
|
217 suppresses stack checking.
|
|
218 </para>
|
|
219 <para>
|
|
220 Normally, the linker considers it to be an error if the "-b=" option
|
|
221 appears and the final linked module requires a data memory
|
|
222 allocation. In our case here, we require a data memory allocation
|
|
223 and we will provide the code to make sure everything is set up
|
|
224 correctly. The "-t" linker option causes the linker to print the
|
|
225 total data memory requirement so we can allow for it rather than
|
|
226 complaining about it. Our linker command line is:
|
|
227 <screen>
|
|
228 c.link bt2.r -o=addints -b=addints -r
|
|
229 </screen>
|
|
230 </para>
|
|
231 <para>
|
|
232 The linker will respond with "BASIC09 static data size is 2 bytes".
|
|
233 We must make sure <varname>cmem</varname> points to at least 2 bytes of memory. The
|
|
234 memory should be zeroed to conform to C specifications.
|
|
235 </para>
|
|
236 <para>
|
|
237 Enter the following BASIC09 program:
|
|
238 </para>
|
|
239 <screen>
|
|
240 PROCEDURE btest
|
|
241 DIM i,j,k,n;INTEGER
|
|
242 DIM cmem(10):INTEGER
|
|
243 FOR i=1 TO 10
|
|
244 cmem(i)=0
|
|
245 NEXT i
|
|
246 FOR n=1 TO 5
|
|
247 i=1
|
|
248 j=132
|
|
249 k=-1033
|
|
250 RUN addints(cmem,4,i,j,k)
|
|
251 PRINT i,j,k
|
|
252 NEXT n
|
|
253 END
|
|
254 </screen>
|
|
255 <para>
|
|
256 This program is similar to the previous example. Our area for data
|
|
257 memory is a 10-integer array (20 bytes) which is way more than the 2
|
|
258 bytes for this example. It is better to err on the generous side.
|
|
259 Cmem is an integer array for convenience in initializing it to zero
|
|
260 (per C data memory specifications). When the program is run, it
|
|
261 calls addints 5 times with the same data values. Because addints
|
|
262 add the number of times it was called to the value, the i,j,k
|
|
263 values should be 4+number of times called. When run, the program prints:
|
|
264 <screen>
|
|
265 5 136 -1029
|
|
266 6 137 -1028
|
|
267 7 138 -1027
|
|
268 8 139 -1026
|
|
269 9 140 -1025
|
|
270 </screen>
|
|
271 Works again!
|
565
|
272 </para>
|
|
273 </section>
|
|
274
|
|
275 <section>
|
|
276 <title>Example 3 - Simple String Manipulation</title>
|
|
277 <para>
|
652
|
278 This example shows how to access BASIC09 strings through C
|
|
279 functions. For this example, write the C version of SUBSTR.
|
|
280 </para>
|
|
281 <screen>
|
|
282 build bt3.c
|
|
283 ? /* Find substring from BASIC09 string:
|
|
284 ? RUN findstr(A$,B$,findpos)
|
|
285 ? returns in fndpos the position in A$ that B$ was found or
|
|
286 ? 0 if not found. A$ and B$ must be strings, fndpos must be
|
|
287 ? INTEGER.
|
|
288 ? */
|
|
289 ? findstr(cnt,string,strcnt,srchstr,srchcnt,result);
|
|
290 ? char *string,*srchstr;
|
|
291 ? int strcnt, srchcnt, *result;
|
|
292 ? {
|
|
293 ? *result = finder(string,strcnt,srchstr,srchcnt);
|
|
294 ? }
|
|
295 ?
|
|
296 ? static finder(str,strlen,pat,patlen)
|
|
297 ? char *str,*pat;
|
|
298 ? int strlen,patlen;
|
|
299 ? {
|
|
300 ? int i;
|
|
301 ? for(i=1;strlen-- > 0 && *str!=0xff; ++i)
|
|
302 ? if(smatch(str++,pat,patlen))
|
|
303 ? return i;
|
|
304 ? }
|
|
305 ?
|
|
306 ? static smatch(str,pat,patlen)
|
|
307 ? register char *str,*pat;
|
|
308 ? int patlen;
|
|
309 ? {
|
|
310 ? while(patlen-- > 0 && *pat != 0xff)
|
|
311 ? if(*str++ != *pat++)
|
|
312 ? return 0;
|
|
313 ? return 1;
|
|
314 ? }
|
|
315 ?
|
|
316 </screen>
|
|
317 <para>
|
|
318 Compile this program:
|
|
319 <screen>
|
|
320 cc2 bt3.c -rs
|
|
321 </screen>
|
|
322 And link it:
|
|
323 <screen>
|
|
324 c.link bt3.r -o=findstr -b=findstr
|
|
325 </screen>
|
|
326 The BASIC09 test program is:
|
|
327 <screen>
|
|
328 PROCEDURE btest
|
|
329 DIM a,b:STRING[20]
|
|
330 DIM matchpos:INTEGER
|
|
331 LOOP
|
|
332 INPUT "String ",a
|
|
333 INPUT "Match ",b
|
|
334 RUN findstr(a,b,matchpos)
|
|
335 PRINT "Matched at position ",matchpos
|
|
336 ENDLOOP
|
|
337 </screen>
|
|
338 When this program is run, it should print the position where the
|
|
339 matched string was found in the source string.
|
565
|
340 </para>
|
|
341 </section>
|
|
342
|
|
343 <section>
|
|
344 <title>Example 4 - Quicksort</title>
|
|
345 <para>
|
|
346 The next example programs demonstrate how one might implement a
|
|
347 quicksort written in C to sort some BASIC09 data.
|
|
348 </para>
|
|
349 <para>
|
|
350 C integer quicksort program:
|
|
351 </para>
|
|
352 <programlisting>
|
|
353 #define swap(a,b) { int t; t=a; a=b; b=t; }
|
|
354
|
|
355 /* qsort to be called by BASIC09:
|
|
356 dim d(100):INTEGER any size INTEGER array
|
|
357 run cqsort(d,100) calling qsort.
|
|
358 */
|
|
359
|
|
360 qsort(argcnt,iarray,iasize,icount,icsiz)
|
|
361 int argcnt, /* BASIC09 argument count */
|
|
362 iarrary[], /* Pointer to BASIC09 integer array */
|
|
363 iasize, /* and it's size */
|
|
364 *icount, /* Pointer to BASIC09 (sort count) */
|
|
365 icsiz; /* Size of integer */
|
|
366 {
|
|
367 sort(iarray,0,*icount); /* initial qsort partition */
|
|
368 }
|
|
369
|
|
370 /* standard quicksort algorithm from Horowitz-Sahni */
|
|
371 static sort(a,m,n)
|
|
372 register int *a,m,n;
|
|
373 {
|
|
374 register i,j,x;
|
|
375
|
|
376 if(m < n) {
|
|
377 i = m;
|
|
378 j = n + 1;
|
|
379 x = a[m];
|
|
380 for(;;) {
|
|
381 do i += 1; while(a[i] < x); /* left partition */
|
|
382 do j -= 1; while(a[j] > x); /* right partition */
|
|
383 if(i < j)
|
|
384 swap(a[i],a[j]) /* swap */
|
|
385 else break;
|
|
386 }
|
|
387 swap(a[m],a[j]);
|
|
388 sort(a,m,j-1); /* sort left */
|
|
389 sort(a,j+1,n); /* sort right */
|
|
390 }
|
|
391 }
|
|
392 </programlisting>
|
|
393 <para>
|
|
394 The BASIC09 program is:
|
|
395 </para>
|
|
396 <programlisting>
|
|
397 PROCEDURE sorter
|
|
398 DIM i,n,d(1000):INTEGER
|
|
399 n=1000
|
|
400 i=RND(-(PI))
|
|
401 FOR i=1 to n
|
|
402 d(i):=INT(RND(1000))
|
|
403 NEXT i
|
|
404 PRINT "Before:"
|
|
405 RUN prin(1,n,d)
|
|
406 RUN qsortb(d,n)
|
|
407 PRINT "After:"
|
|
408 RUN prin(1,n,d)
|
|
409 END
|
|
410
|
|
411 PROCEDURE prin
|
|
412 PARAM n,m,d(1000):INTEGER
|
|
413 DIM i:INTEGER
|
|
414 FOR i=n TO m
|
|
415 PRINT d(i); " ";
|
|
416 NEXT i
|
|
417 PRINT
|
|
418 END
|
|
419 </programlisting>
|
631
|
420 <para>
|
|
421 C string quicksort program:
|
|
422 </para>
|
|
423 <programlisting>
|
|
424 /* qsort to be called by BASIC09:
|
|
425 dim cmemory:STRING[10] This should be at least as large as
|
|
426 the linker says the data size should
|
|
427 be.
|
|
428 dim d(100):INTERGER Any size INTEGER array.
|
|
429
|
|
430 run cqsort(cmemory,d,100) calling qsort. Note that the pro-
|
|
431 cedure name run in the linked OS-9
|
|
432 subroutine module. The module name
|
|
433 need not be the name of the C func-
|
|
434 tion.
|
|
435 */
|
|
436
|
|
437 int maxstr; /* string maximum length */
|
|
438
|
|
439 static strbcmp(str1,str2) /* basic09 string compare */
|
|
440 register char *str1,*str2;
|
|
441 {
|
|
442 int maxlen;
|
|
443
|
|
444 for (maxlen = maxstr; *str1 == *str2 ;++str1)
|
652
|
445 if (maxlen-- >0 || *str2++ == 0xff)
|
631
|
446 return 0;
|
|
447 return (*str1 - *str2);
|
|
448 }
|
|
449
|
|
450 cssort(argcnt,stor,storsiz,iaarray,iasize,elemlen,elsiz,
|
|
451 icount,icsiz)
|
|
452 int argcnt; /* BASIC09 argument count */
|
|
453 char *stor; /* Pointer to string (C data storage) */
|
|
454 char iarray[]; /* Pointer to BASIC09 integer array */
|
|
455 int iasize, /* and it's size */
|
|
456 *elemlen, /* Pointer integer value (string length) */
|
|
457 elsiz, /* Size of integer */
|
|
458 *icount, /* Pointer to integer (sort count) */
|
|
459 icsiz; /* Size of integer */
|
|
460 {
|
|
461 /* The following assembly code loads Y with the first
|
|
462 arg provided by BASIC09. This code MUST be the first code
|
|
463 in the function after the declarations. This code assumes the
|
|
464 address of the data area is the first parameter in the BASIC09
|
|
465 RUN command. */
|
|
466 #asm
|
|
467 ldy 6,s get addr for C storage
|
|
468 #endasm
|
|
469
|
|
470 /* Use the C library qsort function to do the sort. Our
|
|
471 own BASIC09 string compare function will compare the strings.
|
|
472 */
|
|
473
|
|
474 qsort(iarray,*icount,maxstr=*elemlen,strbcmp);
|
|
475 }
|
|
476
|
|
477 /* define stuff cstart.r normally defines */
|
|
478 #asm
|
|
479 _stkcheck:
|
|
480 rts dummy stack check function
|
|
481
|
|
482 vsect
|
|
483 errno: rmb 2 C function system error number
|
|
484 _flacc: rmb 8 C library float/long accumulator
|
|
485 endsect
|
|
486 #endasm
|
|
487 </programlisting>
|
|
488 <para>
|
|
489 The BASIC09 calling programs: (words file contains strings to sort)
|
|
490 </para>
|
|
491 <programlisting>
|
|
492 PROCEDURE ssorter
|
|
493 DIM a(200):STRING[20]
|
|
494 DIM cmemory:STRING[20]
|
|
495 DIM i,n:INTEGER
|
|
496 DIM path:INTEGER
|
|
497 OPEN #path,"words":READ
|
|
498
|
|
499 n=100
|
|
500 FOR i=1 to n
|
|
501 INPUT #path,a(i)
|
|
502 NEXT i
|
|
503 CLOSE #path
|
|
504 RUN prin(a,n)
|
|
505 RUN cssort(cmemory,a,20,n)
|
|
506 RUN prin(a,n)
|
|
507 END
|
|
508
|
|
509 PROCEDURE prin
|
|
510 PARAM a(100):STRING[20]; n:INTEGER
|
|
511 DIM i:INTEGER
|
|
512 FOR i=1 TO n
|
|
513 PRINT i; " "; a(i)
|
|
514 NEXT i
|
|
515 PRINT i
|
|
516 END
|
|
517 </programlisting>
|
|
518 </section>
|
|
519
|
|
520 <section>
|
|
521 <title>Example 5 - Floating Point</title>
|
|
522 <para>
|
|
523 The next example shows how to access BASIC09 reals from C functions:
|
|
524 </para>
|
|
525 <programlisting>
|
|
526 flmult(cnt,cmemory,cmemsiz,realarg,realsize)
|
652
|
527 int cnt; /* number of arguments */
|
|
528 char *cmemory; /* pointer to some memory for C use */
|
|
529 double *realarg; /* pointer to real */
|
|
530 {
|
|
531 #asm
|
|
532 ldy 6,s get static memory address
|
|
533 #endasm
|
|
534
|
|
535 double number;
|
|
536
|
|
537 getbreal(&number,realarg); /* get the BASIC09 real */
|
|
538 number *= 2.; /* number times two*/
|
|
539 putbreal(realarg,&number); /* give back to BASIC09 */
|
|
540
|
|
541 }
|
|
542
|
|
543 /* getreal(creal,breal)
|
|
544 get a 5-byte real from BASIC09 format to C format */
|
|
545
|
|
546 getbreal(creal,breal)
|
|
547 double *creal,*breal;
|
|
548 {
|
|
549 register char *cr,*br; /* setup some char pointers */
|
|
550
|
|
551 cr = creal;
|
|
552 br = breal;
|
|
553 #asm
|
|
554 * At this point U reg contains address of C double
|
|
555 * 0,s contains address of BASIC09 real
|
|
556 ldx 0,s get address of B real
|
|
557
|
|
558 clra clear the C double
|
|
559 clrb
|
|
560 std 0,u
|
|
561 std 2,u
|
|
562 std 4,u
|
|
563 stb 6,u
|
|
564 ldd 0,x
|
|
565 beq g3 BASIC09 real is zero
|
|
566
|
|
567 ldd 1,x get hi B mantissa
|
|
568 and a #$7f clear place for sign
|
|
569 std 0,u put hi C matissa
|
|
570 ldd 3,x get lo B mantissa
|
|
571 andb #$fe mask off sign
|
|
572 std 2,u put lo C mantissa
|
|
573 lda 4,x get B sign byte
|
|
574 lsra shift out sign
|
|
575 bcc g1
|
|
576 lda 0,u get C sign byte
|
|
577 ora #$80 tun on sign
|
|
578 sta 0,u put C sign byte
|
|
579 g1 lda 0,x get B exponent
|
|
580 suba #128 excess 128
|
|
581 sta 7,u put C exponent
|
|
582 g3 clra clear carry
|
|
583 #endasm
|
|
584
|
|
585 }
|
|
586
|
|
587 /* putbreal(breal,creal)
|
|
588 put C format double into a 5-byte real from BASIC09 */
|
|
589
|
|
590 putbreal(breal,creal)
|
|
591 double *breal,*creal;
|
|
592 {
|
|
593 register char *cr,*br; /* setup some pointers */
|
|
594
|
|
595 cr = creal;
|
|
596 br = breal;
|
|
597 #asm
|
|
598 * At this point U reg contains address of C double
|
|
599 * 0,s contains address of BASIC09 real
|
|
600 ldx 0,s get address of B real
|
|
601
|
|
602 lda 7,u get C exponent
|
|
603 bne p0 not zero?
|
|
604 clra clear the BASIC09
|
|
605 clrb real
|
|
606 std 0,x
|
|
607 std 2,x
|
|
608 std 4,x
|
|
609 bra p3 and exit
|
|
610
|
|
611 p0 ldd 0,u get hi C mantissa
|
|
612 ora #$80 this bit always on for normalized real
|
|
613 std 1,x put hi B mantissa
|
|
614 ldd 2,u get lo C mantissa
|
|
615 std 3,x put lo B mantissa
|
|
616 incb round mantissa
|
|
617 bne p1
|
|
618 inc 3,x
|
|
619 bne p1
|
|
620 inc 2,x
|
|
621 bne p1
|
|
622 inc 1,x
|
|
623 p1 andb #$fe turn off sign
|
|
624 stb 4,x put B sign byte
|
|
625 lda 0,u get C sign byte
|
|
626 lsla shift out sign
|
|
627 bcc p2 bra if positive
|
|
628 orb #$01 turn on sign
|
|
629 stb 4,x put B sign byte
|
|
630 p2 lda 7,u get C exponent
|
|
631 adda #128 less 128
|
|
632 sta 0,x put B exponent
|
|
633 p3 clra clear carry
|
|
634 #endasm
|
|
635 }
|
|
636
|
|
637
|
|
638 /* replace cstart.r definitions for BASIC09 */
|
|
639 #asm
|
|
640 _stkcheck:
|
|
641 _stkchec:
|
|
642 rts
|
|
643
|
|
644 vsect
|
|
645 _flacc: rmb 8
|
|
646 errno: rmb 2
|
|
647 endsect
|
|
648 #endasm
|
|
649 </programlisting>
|
|
650 <para>
|
|
651 BASIC09 calling program:
|
|
652 </para>
|
|
653 <programlisting>
|
|
654 PROCEDURE btest
|
|
655 DIM a:REAL
|
|
656 DIM i:INTEGER
|
|
657 DIM cmemory:STRING[32]
|
|
658 a=1.
|
|
659 FOR i=1 TO 10
|
|
660 RUN flmult(cmemory,a)
|
|
661 PRINT a
|
|
662 NEXT i
|
|
663 END
|
631
|
664 </programlisting>
|
|
665 </section>
|
|
666
|
|
667 <section>
|
|
668 <title>Example 6 - Matrix Elements</title>
|
|
669 <para>
|
|
670 The last program is an example of accessing BASIC09 matrix elements.
|
|
671 The C program:
|
|
672 </para>
|
|
673 <programlisting>
|
|
674 matmult(cnt,cmemory,cmemsiz,matxaddr,matxsize,scalar,scalsize)
|
652
|
675 char *cmemory; /* pointer to some memory for C use */
|
|
676 int matxaddr[5][3]; /* pointer a double dim integer array */
|
|
677 int *scalar; /* pointer to integer */
|
|
678 {
|
|
679 #asm
|
|
680 ldy 6,s get static memory address
|
|
681 #endasm
|
|
682
|
|
683 int i,j;
|
|
684
|
|
685 for(i=0; i<5; ++i)
|
|
686 for(j=1; j<3; ++j)
|
|
687 matxaddr[j][i] *= *scalar; /* multiply by value */
|
|
688 }
|
|
689 #asm
|
|
690 _stkcheck:
|
|
691 _stkchec:
|
|
692 rts
|
|
693
|
|
694 vsect
|
|
695 _flacc: rmb 8
|
|
696 errno: rmb 2
|
|
697 endsect
|
|
698 #endasm
|
631
|
699 </programlisting>
|
|
700 <para>
|
|
701 BASIC09 calling program:
|
|
702 </para>
|
|
703 <programlisting>
|
|
704 PROCEDURE btest
|
|
705 DIM im(5,3):INTEGER
|
|
706 DIM i,j:INTEGER
|
|
707 DIM cmem:STRING[32]
|
|
708 FOR i=1 TO 5
|
|
709 FOR j=1 TO 3
|
|
710 READ im(i,j)
|
|
711 NEXT j
|
|
712 NEXT i
|
|
713 DATA 11,13,7,3,4,0,5,7,2,8,15,0,0,14,4
|
|
714 FOR i=1 TO 5
|
|
715 PRINT im(i,1),im(i,2),im(i,3)
|
|
716 NEXT i
|
|
717 PRINT
|
|
718 RUN matmult(cmem,im,64)
|
|
719 FOR i=1 TO 5
|
|
720 PRINT im(i,1),im(i,2),im(i,3)
|
|
721 NEXT i
|
|
722 END
|
|
723 </programlisting>
|
565
|
724 </section>
|
466
|
725 </appendix>
|