* remove "\r" nonsense
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / baremetal0.5.2 / programs / basic.asm
blob09dad44132775687e2887b709f3590a120a79ac8
1 ; ==================================================================
2 ; basic.asm - BASIC Interpreter for BareMetal OS
3 ; Ported by Ian Seyler
5 ; Based on the "OS-independent" version of MIBASIC by Neville Watkin
6 ; which is based on MIKEOS BASIC by Mike Saunders
7 ; ==================================================================
9 [BITS 64]
10 [ORG 0x0000000000200000]
12 %INCLUDE "bmdev.asm"
14 ; ------------------------------------------------------------------
15 ; Token types
16 VARIABLE equ 1
17 STRING_VAR equ 2
18 NUMBER equ 3
19 STRING equ 4
20 QUOTE equ 5
21 CHAR equ 6
22 UNKNOWN equ 7
23 LABEL equ 8
25 ; ------------------------------------------------------------------
26 ; The BASIC intepreter execution starts here...
28 os_run_basic:
29 mov dword [orig_stack], esp ; Save stack pointer -- we might jump to the
30 ; error printing code and quit in the middle
31 ; some nested loops, and we want to preserve
32 ; the stack
33 mov eax, basic_prog ;embedded test program for a quick DOS test
34 mov ebx, 8192 ;default size for test program (not critical)
35 mov dword [load_point], eax ; EAX was passed as starting location of code
36 mov dword [prog], eax ; prog = pointer to current execution point in code
37 add ebx, eax ; We were passed the .BAS byte size in BX
38 dec ebx
39 dec ebx
40 mov dword [prog_end], ebx ; Make note of program end point
41 call clear_ram ; Clear variables etc. from previous run
42 ; of a BASIC program
43 mainloop:
44 call get_token ; Get a token from the start of the line
45 cmp eax, STRING ; Is the type a string of characters?
46 je .keyword ; If so, let's see if it's a keyword to process
47 cmp eax, VARIABLE ; If it's a variable at the start of the line,
48 je near assign ; this is an assign (eg "X = Y + 5")
49 cmp eax, STRING_VAR ; Same for a string variable (eg $1)
50 je near assign
51 cmp eax, LABEL ; Don't need to do anything here - skip
52 je mainloop
53 mov esi, err_syntax ; Otherwise show an error and quit
54 jmp error
55 .keyword:
56 mov esi, token ; Start trying to match commands
57 mov edi, alert_cmd
58 call b_string_compare
59 jc near do_alert
60 mov edi, call_cmd
61 call b_string_compare
62 jc near do_call
63 mov edi, cls_cmd
64 call b_string_compare
65 jc near do_cls
66 mov edi, cursor_cmd
67 call b_string_compare
68 jc near do_cursor
69 mov edi, curschar_cmd
70 call b_string_compare
71 jc near do_curschar
72 mov edi, end_cmd
73 call b_string_compare
74 jc near do_end
75 mov edi, for_cmd
76 call b_string_compare
77 jc near do_for
78 mov edi, getkey_cmd
79 call b_string_compare
80 jc near do_getkey
81 mov edi, gosub_cmd
82 call b_string_compare
83 jc near do_gosub
84 mov edi, goto_cmd
85 call b_string_compare
86 jc near do_goto
87 mov edi, input_cmd
88 call b_string_compare
89 jc near do_input
90 mov edi, if_cmd
91 call b_string_compare
92 jc near do_if
93 ; mov edi, load_cmd
94 ; call b_string_compare
95 ; jc near do_load
96 mov edi, move_cmd
97 call b_string_compare
98 jc near do_move
99 mov edi, next_cmd
100 call b_string_compare
101 jc near do_next
102 mov edi, pause_cmd
103 call b_string_compare
104 jc near do_pause
105 mov edi, peek_cmd
106 call b_string_compare
107 jc near do_peek
108 mov edi, poke_cmd
109 call b_string_compare
110 jc near do_poke
111 mov edi, port_cmd
112 call b_string_compare
113 jc near do_port
114 mov edi, print_cmd
115 call b_string_compare
116 jc near do_print
117 mov edi, rand_cmd
118 call b_string_compare
119 jc near do_rand
120 mov edi, rem_cmd
121 call b_string_compare
122 jc near do_rem
123 mov edi, return_cmd
124 call b_string_compare
125 jc near do_return
126 ; mov edi, save_cmd
127 ; call b_string_compare
128 ; jc near do_save
129 mov edi, serial_cmd
130 call b_string_compare
131 jc near do_serial
132 mov edi, sound_cmd
133 call b_string_compare
134 jc near do_sound
135 mov edi, waitkey_cmd
136 call b_string_compare
137 jc near do_waitkey
138 mov esi, err_cmd_unknown ; Command not found?
139 jmp error
141 ; ------------------------------------------------------------------
142 ; CLEAR RAM
143 clear_ram:
144 mov al, 0
145 mov edi, variables
146 mov ecx, 52
147 rep stosb
148 mov edi, for_variables
149 mov ecx, 52
150 rep stosb
151 mov edi, for_code_points
152 mov ecx, 52
153 rep stosb
154 mov byte [gosub_depth], 0
155 mov edi, gosub_points
156 mov ecx, 20
157 rep stosb
158 mov edi, string_vars
159 mov ecx, 1024
160 rep stosb
162 ; ------------------------------------------------------------------
163 ; ASSIGNMENT
164 assign:
165 cmp eax, VARIABLE ; Are we starting with a number var?
166 je .do_num_var
167 mov edi, string_vars ; Otherwise it's a string var
168 mov eax, 128
169 mul ebx ; (EBX = string number, passed back from get_token)
170 add edi, eax
171 push rdi
172 call get_token
173 mov byte al, [token]
174 cmp al, '='
175 jne near .error
176 call get_token
177 cmp eax, QUOTE
178 je .second_is_quote
179 cmp eax, STRING_VAR
180 jne near .error
181 mov esi, string_vars ; Otherwise it's a string var
182 mov eax, 128
183 mul ebx ; (EBX = string number, passed back from get_token)
184 add esi, eax
185 pop rdi
186 call b_string_copy
187 jmp mainloop
188 .second_is_quote:
189 mov esi, token
190 pop rdi
191 call b_string_copy
192 jmp mainloop
193 .do_num_var:
194 mov eax, 0
195 mov byte al, [token]
196 mov byte [.tmp], al
197 call get_token
198 mov byte al, [token]
199 cmp al, '='
200 jne near .error
201 call get_token
202 cmp eax, NUMBER
203 je .second_is_num
204 cmp eax, VARIABLE
205 je .second_is_variable
206 cmp eax, STRING
207 je near .second_is_string
208 cmp eax, UNKNOWN
209 jne near .error
210 mov byte al, [token] ; Address of string var?
211 cmp al, '&'
212 jne near .error
213 call get_token ; Let's see if there's a string var
214 cmp eax, STRING_VAR
215 jne near .error
216 mov edi, string_vars
217 mov eax, 128
218 mul ebx
219 add edi, eax
220 mov ebx, edi
221 mov byte al, [.tmp]
222 call set_var
223 jmp mainloop
224 .second_is_variable:
225 mov eax, 0
226 mov byte al, [token]
227 call get_var
228 mov ebx, eax
229 mov byte al, [.tmp]
230 call set_var
231 jmp .check_for_more
232 .second_is_num:
233 mov esi, token
234 call b_string_to_int
235 mov ebx, eax ; Number to insert in variable table
236 mov eax, 0
237 mov byte al, [.tmp]
238 call set_var
239 ; The assignment could be simply "X = 5" etc. Or it could be
240 ; "X = Y + 5" -- ie more complicated. So here we check to see if
241 ; there's a delimiter...
242 .check_for_more:
243 mov dword eax, [prog] ; Save code location in case there's no delimiter
244 mov dword [.tmp_loc], eax
245 call get_token ; Any more to deal with in this assignment?
246 mov byte al, [token]
247 cmp al, '+'
248 je .theres_more
249 cmp al, '-'
250 je .theres_more
251 cmp al, '*'
252 je .theres_more
253 cmp al, '/'
254 je .theres_more
255 cmp al, '%'
256 je .theres_more
257 mov dword eax, [.tmp_loc] ; Not a delimiter, so step back before the token
258 mov dword [prog], eax ; that we just grabbed
259 jmp mainloop ; And go back to the code interpreter!
260 .theres_more:
261 mov byte [.delim], al
262 call get_token
263 cmp eax, VARIABLE
264 je .handle_variable
265 mov esi, token
266 call b_string_to_int
267 mov ebx, eax
268 mov eax, 0
269 mov byte al, [.tmp]
270 call get_var ; This also points ESI at right place in variable table
271 cmp byte [.delim], '+'
272 jne .not_plus
273 add eax, ebx
274 jmp .finish
275 .not_plus:
276 cmp byte [.delim], '-'
277 jne .not_minus
278 sub eax, ebx
279 jmp .finish
280 .not_minus:
281 cmp byte [.delim], '*'
282 jne .not_times
283 mul ebx
284 jmp .finish
285 .not_times:
286 cmp byte [.delim], '/'
287 jne .not_divide
288 mov edx, 0
289 div ebx
290 jmp .finish
291 .not_divide:
292 mov edx, 0
293 div ebx
294 mov eax, edx ; Get remainder
295 .finish:
296 mov ebx, eax
297 mov byte al, [.tmp]
298 call set_var
299 jmp .check_for_more
300 .handle_variable:
301 mov eax, 0
302 mov byte al, [token]
303 call get_var
304 mov ebx, eax
305 mov eax, 0
306 mov byte al, [.tmp]
307 call get_var
308 cmp byte [.delim], '+'
309 jne .vnot_plus
310 add eax, ebx
311 jmp .vfinish
312 .vnot_plus:
313 cmp byte [.delim], '-'
314 jne .vnot_minus
315 sub eax, ebx
316 jmp .vfinish
317 .vnot_minus:
318 cmp byte [.delim], '*'
319 jne .vnot_times
320 mul ebx
321 jmp .vfinish
322 .vnot_times:
323 cmp byte [.delim], '/'
324 jne .vnot_divide
325 mov edx, 0
326 div ebx
327 jmp .finish
328 .vnot_divide:
329 mov edx, 0
330 div ebx
331 mov eax, edx ; Get remainder
332 .vfinish:
333 mov ebx, eax
334 mov byte al, [.tmp]
335 call set_var
336 jmp .check_for_more
337 .second_is_string:
338 mov edi, token
339 mov esi, progstart_keyword
340 call b_string_compare
341 je .is_progstart
342 mov esi, ramstart_keyword
343 call b_string_compare
344 je .is_ramstart
345 jmp .error
346 .is_progstart:
347 mov eax, 0
348 mov byte al, [.tmp]
349 mov dword ebx, [load_point]
350 call set_var
351 jmp mainloop
352 .is_ramstart:
353 mov eax, 0
354 mov byte al, [.tmp]
355 mov dword ebx, [prog_end]
356 inc ebx
357 inc ebx
358 inc ebx
359 call set_var
360 jmp mainloop
361 .error:
362 mov esi, err_syntax
363 jmp error
364 .tmp db 0
365 .tmp_loc dd 0
366 .delim db 0
367 ; ==================================================================
368 ; SPECIFIC COMMAND CODE STARTS HERE
369 ; ------------------------------------------------------------------
370 ; ALERT
371 do_alert:
372 call get_token
373 cmp eax, QUOTE
374 je .is_quote
375 mov esi, err_syntax
376 jmp error
377 .is_quote:
378 mov eax, token ; First string for alert box
379 mov ebx, 0 ; Others are blank
380 mov ecx, 0
381 mov edx, 0 ; One-choice box
382 ; call b_dialog_box
383 jmp mainloop
384 ; ------------------------------------------------------------------
385 ; CALL
386 do_call:
387 call get_token
388 cmp eax, NUMBER
389 je .is_number
390 xor eax, eax
391 mov byte al, [token]
392 call get_var
393 jmp .execute_call
394 .is_number:
395 mov esi, token
396 call b_string_to_int
397 .execute_call:
398 mov ebx, 0
399 mov ecx, 0
400 mov edx, 0
401 mov edi, 0
402 mov esi, 0
403 call rax
404 jmp mainloop
405 ; ------------------------------------------------------------------
406 ; CLS
407 do_cls:
408 call b_screen_clear
409 jmp mainloop
410 ; ------------------------------------------------------------------
411 ; CURSOR
412 do_cursor:
413 call get_token
414 mov esi, token
415 mov edi, .on_str
416 call b_string_compare
417 jc .turn_on
418 mov esi, token
419 mov edi, .off_str
420 call b_string_compare
421 jc .turn_off
422 mov esi, err_syntax
423 jmp error
424 .turn_on:
425 call b_show_cursor
426 jmp mainloop
427 .turn_off:
428 call b_hide_cursor
429 jmp mainloop
430 .on_str db "ON", 0
431 .off_str db "OFF", 0
432 ; ------------------------------------------------------------------
433 ; CURSCHAR
434 do_curschar:
435 call get_token
436 cmp eax, VARIABLE
437 je .is_ok
438 mov esi, err_syntax
439 jmp error
440 .is_ok:
441 mov eax, 0
442 mov byte al, [token]
443 push rax ; Store variable we're going to use
444 mov ah, 08h
445 mov ebx, 0
446 ; int 10h ; Get char at current cursor location
447 mov ebx, 0 ; We only want the lower byte (the char, not attribute)
448 mov bl, al
449 pop rax ; Get the variable back
450 call set_var ; And store the value
451 jmp mainloop
452 ; ------------------------------------------------------------------
453 ; END
454 do_end:
455 mov dword esp, [orig_stack]
457 ; ------------------------------------------------------------------
458 ; FOR
459 do_for:
460 call get_token ; Get the variable we're using in this loop
461 cmp eax, VARIABLE
462 jne near .error
463 mov eax, 0
464 mov byte al, [token]
465 mov byte [.tmp_var], al ; Store it in a temporary location for now
466 call get_token
467 mov eax, 0 ; Check it's followed up with '='
468 mov byte al, [token]
469 cmp al, '='
470 jne .error
471 call get_token ; Next we want a number
472 cmp eax, NUMBER
473 jne .error
474 mov esi, token ; Convert it
475 call b_string_to_int
476 ; At this stage, we've read something like "FOR X = 1"
477 ; so let's store that 1 in the variable table
478 mov ebx, eax
479 mov eax, 0
480 mov byte al, [.tmp_var]
481 call set_var
482 call get_token ; Next we're looking for "TO"
483 cmp eax, STRING
484 jne .error
485 mov eax, token
486 call b_string_uppercase
487 mov esi, token
488 mov edi, .to_string
489 call b_string_compare
490 jnc .error
491 ; So now we're at "FOR X = 1 TO"
492 call get_token
493 cmp eax, NUMBER
494 jne .error
495 mov esi, token ; Get target number
496 call b_string_to_int
497 mov ebx, eax
498 mov eax, 0
499 mov byte al, [.tmp_var]
500 sub al, 65 ; Store target number in table
501 mov edi, for_variables
502 add edi, eax
503 add edi, eax
504 mov eax, ebx
505 stosw
506 ; So we've got the variable, assigned it the starting number, and put into
507 ; our table the limit it should reach. But we also need to store the point in
508 ; code after the FOR line we should return to if NEXT X doesn't complete the loop...
509 mov eax, 0
510 mov byte al, [.tmp_var]
511 sub al, 65 ; Store code position to return to in table
512 mov edi, for_code_points
513 add edi, eax
514 add edi, eax
515 mov dword eax, [prog]
516 stosw
517 jmp mainloop
518 .error:
519 mov esi, err_syntax
520 jmp error
521 .tmp_var db 0
522 .to_string db 'TO', 0
523 ; ------------------------------------------------------------------
524 ; GETKEY
525 do_getkey:
526 call get_token
527 cmp eax, VARIABLE
528 je .is_variable
529 mov esi, err_syntax
530 jmp error
531 .is_variable:
532 mov eax, 0
533 mov byte al, [token]
534 push rax
535 call b_input_key_check
536 mov ebx, 0
537 mov bl, al
538 pop rax
539 call set_var
540 jmp mainloop
541 ; ------------------------------------------------------------------
542 ; GOSUB
543 do_gosub:
544 call get_token ; Get the number (label)
545 cmp eax, STRING
546 je .is_ok
547 mov esi, err_goto_notlabel
548 jmp error
549 .is_ok:
550 mov esi, token ; Back up this label
551 mov edi, .tmp_token
552 call b_string_copy
553 mov eax, .tmp_token
554 call b_string_length
555 mov edi, .tmp_token ; Add ':' char to end for searching
556 add edi, eax
557 mov al, ':'
558 stosb
559 mov al, 0
560 stosb
561 inc byte [gosub_depth]
562 mov eax, 0
563 mov byte al, [gosub_depth] ; Get current GOSUB nest level
564 cmp al, 9
565 jle .within_limit
566 mov esi, err_nest_limit
567 jmp error
568 .within_limit:
569 mov edi, gosub_points ; Move into our table of pointers
570 add edi, eax ; Table is words (not bytes)
571 add edi, eax
572 mov dword eax, [prog]
573 stosw ; Store current location before jump
574 mov dword eax, [load_point]
575 mov dword [prog], eax ; Return to start of program to find label
576 .loop:
577 call get_token
578 cmp eax, LABEL
579 jne .line_loop
580 mov esi, token
581 mov edi, .tmp_token
582 call b_string_compare
583 jc mainloop
584 .line_loop: ; Go to end of line
585 mov dword esi, [prog]
586 mov byte al, [esi]
587 inc dword [prog]
588 cmp al, 10
589 jne .line_loop
590 mov dword eax, [prog]
591 mov dword ebx, [prog_end]
592 cmp eax, ebx
593 jg .past_end
594 jmp .loop
595 .past_end:
596 mov esi, err_label_notfound
597 jmp error
598 .tmp_token: times 30 db 0
599 ; ------------------------------------------------------------------
600 ; GOTO
601 do_goto:
602 call get_token ; Get the next token
603 cmp eax, STRING
604 je .is_ok
605 mov esi, err_goto_notlabel
606 jmp error
607 .is_ok:
608 mov esi, token ; Back up this label
609 mov edi, .tmp_token
610 call b_string_copy
611 mov eax, .tmp_token
612 call b_string_length
613 mov edi, .tmp_token ; Add ':' char to end for searching
614 add edi, eax
615 mov al, ':'
616 stosb
617 mov al, 0
618 stosb
619 mov dword eax, [load_point]
620 mov dword [prog], eax ; Return to start of program to find label
621 .loop:
622 call get_token
623 cmp eax, LABEL
624 jne .line_loop
625 mov esi, token
626 mov edi, .tmp_token
627 call b_string_compare
628 jc mainloop
629 .line_loop: ; Go to end of line
630 mov dword esi, [prog]
631 mov byte al, [esi]
632 inc dword [prog]
633 cmp al, 10
634 jne .line_loop
635 mov dword eax, [prog]
636 mov dword ebx, [prog_end]
637 cmp eax, ebx
638 jg .past_end
639 jmp .loop
640 .past_end:
641 mov esi, err_label_notfound
642 jmp error
643 .tmp_token: times 30 db 0
644 ; ------------------------------------------------------------------
645 ; IF
646 do_if:
647 call get_token
648 cmp eax, VARIABLE ; If can only be followed by a variable
649 je .num_var
650 cmp eax, STRING_VAR
651 je near .string_var
652 mov esi, err_syntax
653 jmp error
654 .num_var:
655 mov eax, 0
656 mov byte al, [token]
657 call get_var
658 mov edx, eax ; Store value of first part of comparison
659 call get_token ; Get the delimiter
660 mov byte al, [token]
661 cmp al, '='
662 je .equals
663 cmp al, '>'
664 je .greater
665 cmp al, '<'
666 je .less
667 mov esi, err_syntax ; If not one of the above, error out
668 jmp error
669 .equals:
670 call get_token ; Is this 'X = Y' (equals another variable?)
671 cmp eax, CHAR
672 je .equals_char
673 mov byte al, [token]
674 call is_letter
675 jc .equals_var
676 mov esi, token ; Otherwise it's, eg 'X = 1' (a number)
677 call b_string_to_int
678 cmp eax, edx ; On to the THEN bit if 'X = num' matches
679 je near .on_to_then
680 jmp .finish_line ; Otherwise skip the rest of the line
681 .equals_char:
682 mov eax, 0
683 mov byte al, [token]
684 cmp eax, edx
685 je near .on_to_then
686 jmp .finish_line
687 .equals_var:
688 mov eax, 0
689 mov byte al, [token]
690 call get_var
691 cmp eax, edx ; Do the variables match?
692 je near .on_to_then ; On to the THEN bit if so
693 jmp .finish_line ; Otherwise skip the rest of the line
694 .greater:
695 call get_token ; Greater than a variable or number?
696 mov byte al, [token]
697 call is_letter
698 jc .greater_var
699 mov esi, token ; Must be a number here...
700 call b_string_to_int
701 cmp eax, edx
702 jl near .on_to_then
703 jmp .finish_line
704 .greater_var: ; Variable in this case
705 mov eax, 0
706 mov byte al, [token]
707 call get_var
708 cmp eax, edx ; Make the comparison!
709 jl .on_to_then
710 jmp .finish_line
711 .less:
712 call get_token
713 mov byte al, [token]
714 call is_letter
715 jc .less_var
716 mov esi, token
717 call b_string_to_int
718 cmp eax, edx
719 jg .on_to_then
720 jmp .finish_line
721 .less_var:
722 mov eax, 0
723 mov byte al, [token]
724 call get_var
725 cmp eax, edx
726 jg .on_to_then
727 jmp .finish_line
728 .string_var:
729 mov byte [.tmp_string_var], bl
730 call get_token
731 mov byte al, [token]
732 cmp al, '='
733 jne .error
734 call get_token
735 cmp eax, STRING_VAR
736 je .second_is_string_var
737 cmp eax, QUOTE
738 jne .error
739 mov esi, string_vars
740 mov eax, 128
741 mul ebx
742 add esi, eax
743 mov edi, token
744 call b_string_compare
745 je .on_to_then
746 jmp .finish_line
747 .second_is_string_var:
748 mov esi, string_vars
749 mov eax, 128
750 mul ebx
751 add esi, eax
752 mov edi, string_vars
753 mov ebx, 0
754 mov byte bl, [.tmp_string_var]
755 mov eax, 128
756 mul ebx
757 add edi, eax
758 call b_string_compare
759 jc .on_to_then
760 jmp .finish_line
761 .on_to_then:
762 call get_token
763 mov esi, token
764 mov edi, then_keyword
765 call b_string_compare
766 jc .then_present
767 mov esi, err_syntax
768 jmp error
769 .then_present: ; Continue rest of line like any other command!
770 jmp mainloop
771 .finish_line: ; IF wasn't fulfilled, so skip rest of line
772 mov dword esi, [prog]
773 mov byte al, [esi]
774 inc dword [prog]
775 cmp al, 10
776 jne .finish_line
777 jmp mainloop
778 .error:
779 mov esi, err_syntax
780 jmp error
781 .tmp_string_var db 0
782 ; ------------------------------------------------------------------
783 ; INPUT
784 do_input:
785 mov al, 0 ; Clear string from previous usage
786 mov edi, .tmpstring
787 mov ecx, 128
788 rep stosb
789 call get_token
790 cmp eax, VARIABLE ; We can only INPUT to variables!
791 je .number_var
792 cmp eax, STRING_VAR
793 je .string_var
794 mov esi, err_syntax
795 jmp error
796 .number_var:
797 mov rdi, .tmpstring ; Get input from the user
798 call b_input_string
799 mov rsi, .tmpstring
800 call b_string_length
801 cmp rcx, 0
802 jne .char_entered
803 mov byte [.tmpstring], '0' ; If enter hit, fill variable with zero
804 mov byte [.tmpstring + 1], 0
805 .char_entered:
806 mov esi, .tmpstring ; Convert to integer format
807 call b_string_to_int
808 mov ebx, eax
809 mov eax, 0
810 mov byte al, [token] ; Get the variable where we're storing it...
811 call set_var ; ...and store it!
812 call b_print_newline
813 jmp mainloop
814 .string_var:
815 push rbx
816 mov rdi, .tmpstring
817 mov rcx, 120 ; Limit to max of 120 chars
818 call b_input_string
819 mov esi, .tmpstring
820 mov edi, string_vars
821 pop rbx
822 mov eax, 128
823 mul ebx
824 add edi, eax
825 call b_string_copy
826 call b_print_newline
827 jmp mainloop
828 .tmpstring: times 128 db 0
829 ; ------------------------------------------------------------------
830 ;; LOAD
831 ;do_load:
832 ; call get_token
833 ; cmp eax, QUOTE
834 ; je .is_quote
835 ; cmp eax, STRING_VAR
836 ; jne .error
837 ; mov esi, string_vars
838 ; mov eax, 128
839 ; mul ebx
840 ; add esi, eax
841 ; jmp .get_position
842 ;.is_quote:
843 ; mov esi, token
844 ;.get_position:
845 ; mov eax, esi
846 ; call b_file_exists
847 ; jc .file_not_exists
848 ; mov edx, eax ; Store for now
849 ; call get_token
850 ; cmp eax, VARIABLE
851 ; je .second_is_var
852 ; cmp eax, NUMBER
853 ; jne .error
854 ; mov esi, token
855 ; call b_string_to_int
856 ;.load_part:
857 ; mov ecx, eax
858 ; mov eax, edx
859 ; call b_load_file
860 ; mov eax, 0
861 ; mov byte al, 'S'
862 ; call set_var
863 ; mov eax, 0
864 ; mov byte al, 'R'
865 ; mov ebx, 0
866 ; call set_var
867 ; jmp mainloop
868 ;.second_is_var:
869 ; mov eax, 0
870 ; mov byte al, [token]
871 ; call get_var
872 ; jmp .load_part
873 ;.file_not_exists:
874 ; mov eax, 0
875 ; mov byte al, 'R'
876 ; mov ebx, 1
877 ; call set_var
878 ; call get_token ; Skip past the loading point -- unnecessary now
879 ; jmp mainloop
880 ;.error:
881 ; mov esi, err_syntax
882 ; jmp error
883 ; ------------------------------------------------------------------
884 ; MOVE
885 do_move:
886 call get_token
887 cmp eax, VARIABLE
888 je .first_is_var
889 mov esi, token
890 call b_string_to_int
891 mov dl, al
892 jmp .onto_second
893 .first_is_var:
894 mov eax, 0
895 mov byte al, [token]
896 call get_var
897 mov dl, al
898 .onto_second:
899 call get_token
900 cmp eax, VARIABLE
901 je .second_is_var
902 mov esi, token
903 call b_string_to_int
904 mov dh, al
905 jmp .finish
906 .second_is_var:
907 mov eax, 0
908 mov byte al, [token]
909 call get_var
910 mov dh, al
911 .finish:
912 call b_move_cursor
913 jmp mainloop
914 ; ------------------------------------------------------------------
915 ; NEXT
916 do_next:
917 call get_token
918 cmp eax, VARIABLE ; NEXT must be followed by a variable
919 jne .error
920 mov eax, 0
921 mov byte al, [token]
922 call get_var
923 inc eax ; NEXT increments the variable, of course!
924 mov ebx, eax
925 mov eax, 0
926 mov byte al, [token]
927 sub al, 65
928 mov esi, for_variables
929 add esi, eax
930 add esi, eax
931 lodsw ; Get the target number from the table
932 inc eax ; (Make the loop inclusive of target number)
933 cmp eax, ebx ; Do the variable and target match?
934 je .loop_finished
935 mov eax, 0 ; If not, store the updated variable
936 mov byte al, [token]
937 call set_var
938 mov eax, 0 ; Find the code point and go back
939 mov byte al, [token]
940 sub al, 65
941 mov esi, for_code_points
942 add esi, eax
943 add esi, eax
944 lodsw
945 mov dword [prog], eax
946 jmp mainloop
947 .loop_finished:
948 jmp mainloop
949 .error:
950 mov esi, err_syntax
951 jmp error
952 ; ------------------------------------------------------------------
953 ; PAUSE
954 do_pause:
955 call get_token
956 cmp eax, VARIABLE
957 je .is_var
958 mov esi, token
959 call b_string_to_int
960 jmp .finish
961 .is_var:
962 mov eax, 0
963 mov byte al, [token]
964 call get_var
965 .finish:
966 call b_delay
967 jmp mainloop
968 ; ------------------------------------------------------------------
969 ; PEEK
970 do_peek:
971 call get_token
972 cmp eax, VARIABLE
973 jne .error
974 mov eax, 0
975 mov byte al, [token]
976 mov byte [.tmp_var], al
977 call get_token
978 cmp eax, VARIABLE
979 je .dereference
980 cmp eax, NUMBER
981 jne .error
982 mov esi, token
983 call b_string_to_int
984 .store:
985 mov esi, eax
986 mov ebx, 0
987 mov byte bl, [esi]
988 mov eax, 0
989 mov byte al, [.tmp_var]
990 call set_var
991 jmp mainloop
992 .dereference:
993 mov byte al, [token]
994 call get_var
995 jmp .store
996 .error:
997 mov esi, err_syntax
998 jmp error
999 .tmp_var db 0
1000 ; ------------------------------------------------------------------
1001 ; POKE
1002 do_poke:
1003 call get_token
1004 cmp eax, VARIABLE
1005 je .first_is_var
1006 cmp eax, NUMBER
1007 jne .error
1008 mov esi, token
1009 call b_string_to_int
1010 cmp eax, 255
1011 jg .error
1012 mov byte [.first_value], al
1013 jmp .onto_second
1014 .first_is_var:
1015 mov eax, 0
1016 mov byte al, [token]
1017 call get_var
1018 mov byte [.first_value], al
1019 .onto_second:
1020 call get_token
1021 cmp eax, VARIABLE
1022 je .second_is_var
1023 cmp eax, NUMBER
1024 jne .error
1025 mov esi, token
1026 call b_string_to_int
1027 .got_value:
1028 mov edi, eax
1029 mov eax, 0
1030 mov byte al, [.first_value]
1031 mov byte [edi], al
1032 jmp mainloop
1033 .second_is_var:
1034 mov eax, 0
1035 mov byte al, [token]
1036 call get_var
1037 jmp .got_value
1038 .error:
1039 mov esi, err_syntax
1040 jmp error
1041 .first_value db 0
1042 ; ------------------------------------------------------------------
1043 ; PORT
1044 do_port:
1045 call get_token
1046 mov esi, token
1047 mov edi, .out_cmd
1048 call b_string_compare
1049 jc .do_out_cmd
1050 mov edi, .in_cmd
1051 call b_string_compare
1052 jc .do_in_cmd
1053 jmp .error
1054 .do_out_cmd:
1055 call get_token
1056 cmp eax, NUMBER
1057 jne .error
1058 mov esi, token
1059 call b_string_to_int ; Now EAX = port number
1060 mov edx, eax
1061 call get_token
1062 cmp eax, NUMBER
1063 je .out_is_num
1064 cmp eax, VARIABLE
1065 je .out_is_var
1066 jmp .error
1067 .out_is_num:
1068 mov esi, token
1069 call b_string_to_int
1070 ; call b_port_byte_out
1071 jmp mainloop
1072 .out_is_var:
1073 mov eax, 0
1074 mov byte al, [token]
1075 call get_var
1076 ; call b_port_byte_out
1077 jmp mainloop
1078 .do_in_cmd:
1079 call get_token
1080 cmp eax, NUMBER
1081 jne .error
1082 mov esi, token
1083 call b_string_to_int
1084 mov edx, eax
1085 call get_token
1086 cmp eax, VARIABLE
1087 jne .error
1088 mov byte cl, [token]
1089 ; call b_port_byte_in
1090 mov ebx, 0
1091 mov bl, al
1092 mov al, cl
1093 call set_var
1094 jmp mainloop
1095 .error:
1096 mov esi, err_syntax
1097 jmp error
1098 .out_cmd db "OUT", 0
1099 .in_cmd db "IN", 0
1100 ; ------------------------------------------------------------------
1101 ; PRINT
1102 do_print:
1103 call get_token ; Get part after PRINT
1104 cmp eax, QUOTE ; What type is it?
1105 je .print_quote
1106 cmp eax, VARIABLE ; Numerical variable (eg X)
1107 je .print_var
1108 cmp eax, STRING_VAR ; String variable (eg $1)
1109 je .print_string_var
1110 cmp eax, STRING ; Special keyword (eg CHR or HEX)
1111 je .print_keyword
1112 mov esi, err_print_type ; We only print quoted strings and vars!
1113 jmp error
1114 .print_var:
1115 mov eax, 0
1116 mov byte al, [token]
1117 call get_var ; Get its value
1118 call b_int_to_string ; Convert to string
1119 mov esi, eax
1120 call b_print_string
1121 jmp .newline_or_not
1122 .print_quote: ; If it's quoted text, print it
1123 mov esi, token
1124 call b_print_string
1125 jmp .newline_or_not
1126 .print_string_var:
1127 mov esi, string_vars
1128 mov eax, 128
1129 mul ebx
1130 add esi, eax
1131 call b_print_string
1132 jmp .newline_or_not
1133 .print_keyword:
1134 mov esi, token
1135 mov edi, chr_keyword
1136 call b_string_compare
1137 jc .is_chr
1138 mov edi, hex_keyword
1139 call b_string_compare
1140 jc .is_hex
1141 mov esi, err_syntax
1142 jmp error
1143 .is_chr:
1144 call get_token
1145 cmp eax, VARIABLE
1146 jne .error
1147 mov eax, 0
1148 mov byte al, [token]
1149 call get_var
1150 mov ah, 0Eh
1151 int 10h
1152 jmp .newline_or_not
1153 .is_hex:
1154 call get_token
1155 cmp eax, VARIABLE
1156 jne .error
1157 mov eax, 0
1158 mov byte al, [token]
1159 call get_var
1160 call b_debug_dump_ax
1161 jmp .newline_or_not
1162 .error:
1163 mov esi, err_syntax
1164 jmp error
1165 .newline_or_not:
1166 ; We want to see if the command ends with ';' -- which means that
1167 ; we shouldn't print a newline after it finishes. So we store the
1168 ; current program location to pop ahead and see if there's the ';'
1169 ; character -- otherwise we put the program location back and resume
1170 ; the main loop
1171 xchg bx, bx
1172 mov dword eax, [prog]
1173 mov dword [.tmp_loc], eax
1174 call get_token
1175 cmp eax, UNKNOWN
1176 jne .ignore
1177 mov eax, 0
1178 mov al, [token]
1179 cmp al, ';'
1180 jne .ignore
1181 jmp mainloop ; And go back to interpreting the code!
1182 .ignore:
1183 call b_print_newline
1184 mov dword eax, [.tmp_loc]
1185 mov dword [prog], eax
1186 jmp mainloop
1187 .tmp_loc dd 0
1188 ; ------------------------------------------------------------------
1189 ; RAND
1190 do_rand:
1191 call get_token
1192 cmp eax, VARIABLE
1193 jne .error
1194 mov byte al, [token]
1195 mov byte [.tmp], al
1196 call get_token
1197 cmp eax, NUMBER
1198 jne .error
1199 mov esi, token
1200 call b_string_to_int
1201 mov dword [.num1], eax
1202 call get_token
1203 cmp eax, NUMBER
1204 jne .error
1205 mov esi, token
1206 call b_string_to_int
1207 mov dword [.num2], eax
1208 mov dword eax, [.num1]
1209 mov dword ebx, [.num2]
1210 ; call b_get_random
1211 mov ebx, ecx
1212 mov eax, 0
1213 mov byte al, [.tmp]
1214 call set_var
1215 jmp mainloop
1216 .tmp db 0
1217 .num1 dd 0
1218 .num2 dd 0
1219 .error:
1220 mov esi, err_syntax
1221 jmp error
1222 ; ------------------------------------------------------------------
1223 ; REM
1224 do_rem:
1225 mov dword esi, [prog]
1226 mov byte al, [esi]
1227 inc dword [prog]
1228 cmp al, 10 ; Find end of line after REM
1229 jne do_rem
1230 jmp mainloop
1231 ; ------------------------------------------------------------------
1232 ; RETURN
1233 do_return:
1234 mov eax, 0
1235 mov byte al, [gosub_depth]
1236 cmp al, 0
1237 jne .is_ok
1238 mov esi, err_return
1239 jmp error
1240 .is_ok:
1241 mov esi, gosub_points
1242 add esi, eax ; Table is words (not bytes)
1243 add esi, eax
1244 lodsw
1245 mov dword [prog], eax
1246 dec byte [gosub_depth]
1247 jmp mainloop
1248 ; ------------------------------------------------------------------
1249 ;; SAVE
1250 ;do_save:
1251 ; call get_token
1252 ; cmp eax, QUOTE
1253 ; je .is_quote
1254 ; cmp eax, STRING_VAR
1255 ; jne near .error
1256 ; mov esi, string_vars
1257 ; mov eax, 128
1258 ; mul ebx
1259 ; add esi, eax
1260 ; jmp .get_position
1261 ;.is_quote:
1262 ; mov esi, token
1263 ;.get_position:
1264 ; mov edi, .tmp_filename
1265 ; call b_string_copy
1266 ; call get_token
1267 ; cmp eax, VARIABLE
1268 ; je .second_is_var
1269 ; cmp eax, NUMBER
1270 ; jne .error
1271 ; mov esi, token
1272 ; call b_string_to_int
1273 ;.set_data_loc:
1274 ; mov dword [.data_loc], eax
1275 ; call get_token
1276 ; cmp eax, VARIABLE
1277 ; je .third_is_var
1278 ; cmp eax, NUMBER
1279 ; jne .error
1280 ; mov esi, token
1281 ; call b_string_to_int
1282 ;.set_data_size:
1283 ; mov dword [.data_size], eax
1284 ; mov dword eax, .tmp_filename
1285 ; mov dword ebx, [.data_loc]
1286 ; mov dword ecx, [.data_size]
1287 ; call b_write_file
1288 ; jc .save_failure
1289 ; mov eax, 0
1290 ; mov byte al, 'R'
1291 ; mov ebx, 0
1292 ; call set_var
1293 ; jmp mainloop
1294 ;.second_is_var:
1295 ; mov eax, 0
1296 ; mov byte al, [token]
1297 ; call get_var
1298 ; jmp .set_data_loc
1299 ;.third_is_var:
1300 ; mov eax, 0
1301 ; mov byte al, [token]
1302 ; call get_var
1303 ; jmp .set_data_size
1304 ;.save_failure:
1305 ; mov eax, 0
1306 ; mov byte al, 'R'
1307 ; mov ebx, 1
1308 ; call set_var
1309 ; jmp mainloop
1310 ;.error:
1311 ; mov esi, err_syntax
1312 ; jmp error
1313 ;.filename_loc dd 0
1314 ;.data_loc dd 0
1315 ;.data_size dd 0
1316 ;.tmp_filename: times 15 db 0
1317 ; ------------------------------------------------------------------
1318 ; SERIAL
1319 do_serial:
1320 call get_token
1321 mov esi, token
1322 mov edi, .on_cmd
1323 call b_string_compare
1324 jc .do_on_cmd
1325 mov edi, .send_cmd
1326 call b_string_compare
1327 jc .do_send_cmd
1328 mov edi, .rec_cmd
1329 call b_string_compare
1330 jc .do_rec_cmd
1331 jmp .error
1332 .do_on_cmd:
1333 call get_token
1334 cmp eax, NUMBER
1335 je .do_on_cmd_ok
1336 jmp .error
1337 .do_on_cmd_ok:
1338 mov esi, token
1339 call b_string_to_int
1340 cmp eax, 1200
1341 je .on_cmd_slow_mode
1342 cmp eax, 9600
1343 je .on_cmd_fast_mode
1344 jmp .error
1345 .on_cmd_fast_mode:
1346 mov eax, 0
1347 ; call b_serial_port_enable
1348 jmp mainloop
1349 .on_cmd_slow_mode:
1350 mov eax, 1
1351 ; call b_serial_port_enable
1352 jmp mainloop
1353 .do_send_cmd:
1354 call get_token
1355 cmp eax, NUMBER
1356 je .send_number
1357 cmp eax, VARIABLE
1358 je .send_variable
1359 jmp .error
1360 .send_number:
1361 mov esi, token
1362 call b_string_to_int
1363 call b_serial_send
1364 jmp mainloop
1365 .send_variable:
1366 mov eax, 0
1367 mov byte al, [token]
1368 call get_var
1369 call b_serial_send
1370 jmp mainloop
1371 .do_rec_cmd:
1372 call get_token
1373 cmp eax, VARIABLE
1374 jne .error
1375 mov byte al, [token]
1376 mov ecx, 0
1377 mov cl, al
1378 call b_serial_recv
1379 mov ebx, 0
1380 mov bl, al
1381 mov al, cl
1382 call set_var
1383 jmp mainloop
1384 .error:
1385 mov esi, err_syntax
1386 jmp error
1387 .on_cmd db "ON", 0
1388 .send_cmd db "SEND", 0
1389 .rec_cmd db "REC", 0
1390 ; ------------------------------------------------------------------
1391 ; SOUND
1392 do_sound:
1393 call get_token
1394 cmp eax, VARIABLE
1395 je .first_is_var
1396 mov esi, token
1397 call b_string_to_int
1398 jmp .done_first
1399 .first_is_var:
1400 mov eax, 0
1401 mov byte al, [token]
1402 call get_var
1403 .done_first:
1404 call b_speaker_tone
1405 call get_token
1406 cmp eax, VARIABLE
1407 je .second_is_var
1408 mov esi, token
1409 call b_string_to_int
1410 jmp .finish
1411 .second_is_var:
1412 mov eax, 0
1413 mov byte al, [token]
1414 call get_var
1415 .finish:
1416 call b_delay
1417 call b_speaker_off
1418 jmp mainloop
1419 ; ------------------------------------------------------------------
1420 ; WAITKEY
1421 do_waitkey:
1422 call get_token
1423 cmp eax, VARIABLE
1424 je .is_variable
1425 mov esi, err_syntax
1426 jmp error
1427 .is_variable:
1428 mov eax, 0
1429 mov byte al, [token]
1430 push rax
1431 call b_input_key_wait
1432 cmp eax, 48E0h
1433 je .up_pressed
1434 cmp eax, 50E0h
1435 je .down_pressed
1436 cmp eax, 4BE0h
1437 je .left_pressed
1438 cmp eax, 4DE0h
1439 je .right_pressed
1440 .store:
1441 mov ebx, 0
1442 mov bl, al
1443 pop rax
1444 call set_var
1445 jmp mainloop
1446 .up_pressed:
1447 mov eax, 1
1448 jmp .store
1449 .down_pressed:
1450 mov eax, 2
1451 jmp .store
1452 .left_pressed:
1453 mov eax, 3
1454 jmp .store
1455 .right_pressed:
1456 mov eax, 4
1457 jmp .store
1458 ; ==================================================================
1459 ; INTERNAL ROUTINES FOR INTERPRETER
1460 ; ------------------------------------------------------------------
1461 ; Get value of variable character specified in AL (eg 'A')
1462 get_var:
1463 sub al, 65
1464 mov esi, variables
1465 add esi, eax
1466 add esi, eax
1467 lodsw
1469 ; ------------------------------------------------------------------
1470 ; Set value of variable character specified in AL (eg 'A')
1471 ; with number specified in EBX
1472 set_var:
1473 mov ah, 0
1474 sub al, 65 ; Remove ASCII codes before 'A'
1475 mov edi, variables ; Find position in table (of words)
1476 add edi, eax
1477 add edi, eax
1478 mov eax, ebx
1479 stosw
1481 ; ------------------------------------------------------------------
1482 ; Get token from current position in prog
1483 get_token:
1484 mov dword esi, [prog]
1485 lodsb
1486 cmp al, 10
1487 je .newline
1488 cmp al, 13 ;allow for CRLF
1489 je .newline
1490 cmp al, ' '
1491 je .newline
1492 call is_number
1493 jc get_number_token
1494 cmp al, '"'
1495 je get_quote_token
1496 cmp al, 39 ; Quote mark (')
1497 je get_char_token
1498 cmp al, '$'
1499 je near get_string_var_token
1500 jmp get_string_token
1501 .newline:
1502 inc dword [prog]
1503 jmp get_token
1504 get_number_token:
1505 mov dword esi, [prog]
1506 mov edi, token
1507 .loop:
1508 lodsb
1509 cmp al, 10
1510 je .done
1511 cmp al, 13 ;allow for CRLF
1512 je .done
1513 cmp al, ' '
1514 je .done
1515 call is_number
1516 jc .fine
1517 mov esi, err_char_in_num
1518 jmp error
1519 .fine:
1520 stosb
1521 inc dword [prog]
1522 jmp .loop
1523 .done:
1524 mov al, 0 ; Zero-terminate the token
1525 stosb
1526 mov eax, NUMBER ; Pass back the token type
1528 get_char_token:
1529 inc dword [prog] ; Move past first quote (')
1530 mov dword esi, [prog]
1531 lodsb
1532 mov byte [token], al
1533 lodsb
1534 cmp al, 39 ; Needs to finish with another quote
1535 je .is_ok
1536 mov esi, err_quote_term
1537 jmp error
1538 .is_ok:
1539 inc dword [prog]
1540 inc dword [prog]
1541 mov eax, CHAR
1543 get_quote_token:
1544 inc dword [prog] ; Move past first quote (") char
1545 mov dword esi, [prog]
1546 mov edi, token
1547 .loop:
1548 lodsb
1549 cmp al, '"'
1550 je .done
1551 cmp al, 10
1552 je .error
1553 stosb
1554 inc dword [prog]
1555 jmp .loop
1556 .done:
1557 mov al, 0 ; Zero-terminate the token
1558 stosb
1559 inc dword [prog] ; Move past final quote
1560 mov eax, QUOTE ; Pass back token type
1562 .error:
1563 mov esi, err_quote_term
1564 jmp error
1565 get_string_var_token:
1566 lodsb
1567 mov ebx, 0 ; If it's a string var, pass number of string in EBX
1568 mov bl, al
1569 sub bl, 49
1570 inc dword [prog]
1571 inc dword [prog]
1572 mov eax, STRING_VAR
1575 get_string_token:
1576 mov dword esi, [prog]
1577 mov edi, token
1578 .loop:
1579 lodsb
1580 cmp al, 10
1581 je .done
1582 cmp al, 13 ;allow for CRLF
1583 je .done
1584 cmp al, ' '
1585 je .done
1586 stosb
1587 inc dword [prog]
1588 jmp .loop
1589 .done:
1590 mov al, 0 ; Zero-terminate the token
1591 stosb
1592 mov eax, token
1593 call b_string_uppercase
1594 mov eax, token
1595 call b_string_length ; How long was the token?
1596 cmp eax, 1 ; If 1 char, it's a variable or delimiter
1597 je .is_not_string
1598 mov esi, token ; If the token ends with ':', it's a label
1599 add esi, eax
1600 dec esi
1601 lodsb
1602 cmp al, ':'
1603 je .is_label
1604 mov eax, STRING ; Otherwise it's a general string of characters
1606 .is_label:
1607 mov eax, LABEL
1609 .is_not_string:
1610 mov byte al, [token]
1611 call is_letter
1612 jc .is_var
1613 mov eax, UNKNOWN
1615 .is_var:
1616 mov eax, VARIABLE ; Otherwise probably a variable
1618 ; ------------------------------------------------------------------
1619 ; Set carry flag if AL contains ASCII number
1620 is_number:
1621 cmp al, 48
1622 jl .not_number
1623 cmp al, 57
1624 jg .not_number
1627 .not_number:
1630 ; ------------------------------------------------------------------
1631 ; Set carry flag if AL contains ASCII letter
1632 is_letter:
1633 cmp al, 65
1634 jl .not_letter
1635 cmp al, 90
1636 jg .not_letter
1639 .not_letter:
1642 ; ------------------------------------------------------------------
1643 ; Print error message and quit out
1644 error:
1645 call b_print_newline
1646 call b_print_string ; Print error message
1647 call b_print_newline
1648 mov dword esp, [orig_stack] ; Restore the stack to as it was when BASIC started
1649 ret ; And finish
1650 ; ------------------------------------------------------------------
1654 ; Error messages text...
1655 err_char_in_num db "Error: unexpected character in number", 0
1656 err_quote_term db "Error: quoted string or character not terminated correctly", 0
1657 err_print_type db "Error: PRINT command not followed by quoted text or variable", 0
1658 err_cmd_unknown db "Error: unknown command", 0
1659 err_goto_notlabel db "Error: GOTO or GOSUB not followed by label", 0
1660 err_label_notfound db "Error: GOTO or GOSUB label not found", 0
1661 err_return db "Error: RETURN without GOSUB", 0
1662 err_nest_limit db "Error: FOR or GOSUB nest limit exceeded", 0
1663 err_next db "Error: NEXT without FOR", 0
1664 err_syntax db "Error: syntax error", 0
1665 ; ==================================================================
1666 ; DATA SECTION
1667 orig_stack dd 0 ; Original stack location when BASIC started
1668 prog dd 0 ; Pointer to current location in BASIC code
1669 prog_end dd 0 ; Pointer to final byte of BASIC code
1670 load_point dd 0
1671 token_type db 0 ; Type of last token read (eg NUMBER, VARIABLE)
1672 token: times 255 db 0 ; Storage space for the token
1673 variables: times 26 dd 0 ; Storage space for variables A to Z
1674 for_variables: times 26 dd 0 ; Storage for FOR loops
1675 for_code_points: times 26 dd 0 ; Storage for code positions where FOR loops start
1676 alert_cmd db "ALERT", 0
1677 call_cmd db "CALL", 0
1678 cls_cmd db "CLS", 0
1679 cursor_cmd db "CURSOR", 0
1680 curschar_cmd db "CURSCHAR", 0
1681 end_cmd db "END", 0
1682 for_cmd db "FOR", 0
1683 gosub_cmd db "GOSUB", 0
1684 goto_cmd db "GOTO", 0
1685 getkey_cmd db "GETKEY", 0
1686 if_cmd db "IF", 0
1687 input_cmd db "INPUT", 0
1688 load_cmd db "LOAD", 0
1689 move_cmd db "MOVE", 0
1690 next_cmd db "NEXT", 0
1691 pause_cmd db "PAUSE", 0
1692 peek_cmd db "PEEK", 0
1693 poke_cmd db "POKE", 0
1694 port_cmd db "PORT", 0
1695 print_cmd db "PRINT", 0
1696 rem_cmd db "REM", 0
1697 rand_cmd db "RAND", 0
1698 return_cmd db "RETURN", 0
1699 save_cmd db "SAVE", 0
1700 serial_cmd db "SERIAL", 0
1701 sound_cmd db "SOUND", 0
1702 waitkey_cmd db "WAITKEY", 0
1703 then_keyword db "THEN", 0
1704 chr_keyword db "CHR", 0
1705 hex_keyword db "HEX", 0
1706 progstart_keyword db "PROGSTART", 0
1707 ramstart_keyword db "RAMSTART", 0
1708 gosub_depth db 0
1709 gosub_points: times 10 dd 0 ; Points in code to RETURN to
1710 string_vars: times 1024 db 0 ; 8 * 128 byte strings
1711 ; ------------------------------------------------------------------
1712 basic_prog:
1713 DB 'CLS',13,10
1714 DB 'PRINT "Please type your name: ";',13,10
1715 DB 'INPUT $N',13,10
1716 DB 'PRINT ""',13,10
1717 DB 'PRINT "Hello "',13,10
1718 DB 'PRINT $N',13,10
1719 DB 'PRINT ", welcome to MikeOS Basic!"',13,10
1720 DB 'PRINT ""',13,10
1721 DB 'PRINT "It supports FOR...NEXT loops and simple integer maths..."',13,10
1722 DB 'PRINT ""',13,10
1723 DB 'FOR I = 1 TO 15',13,10
1724 DB 'J = I * I',13,10
1725 DB 'K = J * I',13,10
1726 DB 'L = K * I',13,10
1727 DB 'PRINT I',13,10
1728 DB 'PRINT " "',13,10
1729 DB 'PRINT J',13,10
1730 DB 'PRINT " "',13,10
1731 DB 'PRINT K',13,10
1732 DB 'PRINT " "',13,10
1733 DB 'PRINT L',13,10
1734 DB 'NEXT I',13,10
1735 DB 'PRINT ""',13,10
1736 DB 'PRINT " ...and IF...THEN and GOSUB and lots of other stuff. Bye!"',13,10
1737 DB 'END',13,10