forked from CorshamTech/6502-Tiny-BASIC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mytb.lst
3460 lines (3199 loc) · 141 KB
/
mytb.lst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
AS65 Assembler for R6502 [1.42]. Page 1
---------------------------------- mytb.asm ----------------------------------
3031 lines read, no errors in pass 1.
;=====================================================
; Bob's Tiny BASIC
;
; While working on the Corsham Technologies KIM Clone
; project, I wanted to include a TINY BASIC since that
; was a highly desirable feature of early computers.
;
; Rather than negotiating copyright issues for
; existing BASICs, I decided to just write one from
; scratch.
;
; 10/07/2017
;
; This implements a stripped down Tiny BASIC
; interpreter using the Interpretive Language (IL)
; method as described in the first few issues of
; Dr Dobb's Journal. The IL interpreter can be used
; to write various languages simply by changing the
; IL code rather than the interpreter itself.
;
; 10/15/2021 v0.4 - Bob Applegate
; * Fxed major bug in findLine that
; caused corrupted lines, crashes, etc.
; * If no parameter given to RND, assume
; 32766.
; * No more error 5 when a program
; reaches the end without an END.
;
; www.corshamtech.com
;
;=====================================================
;
; Create TRUE and FALSE values for conditionals.
;
0000 = FALSE equ 0
ffff = TRUE equ ~FALSE
;
;-----------------------------------------------------
; One of these must be set to indicate which environme
; Tiny BASIC will be running in. Here are the current
; environments:
;
; KIM - This is a bare KIM-1. You'll need to add a fe
; more K of RAM.
;
; XKIM - The Corsham Technologies xKIM extended monito
; which enhances, without replacing, the standard KIM
; monitor. It gives access to routines to save/load f
; to a micro SD card.
;
; CTMON65 is a from-scratch monitor written for the
; Corsham Tech SS-50 6502 CPU board, but the monitor c
; easily be ported to other systems. It has support f
; using a micro SD card for file storage/retrieval.
;
0000 = KIM equ FALSE ;Basic KIM-1, no extensions
ffff = XKIM equ TRUE ;Corsham Tech xKIM monitor
0000 = CTMON65 equ FALSE ;Corsham Tech CTMON65
;
; If set, include disk functions.
AS65 Assembler for R6502 [1.42]. Page 2
---------------------------------- mytb.asm ----------------------------------
;
ffff = DISK_ACCESS equ TRUE
;
; If ILTRACE is set then dump out the address of every
; IL opcode before executing it.
;
0000 = ILTRACE equ FALSE
;
; If FIXED is set, put the IL code and the user
; program space at fixed locations in memory. This is
; meant only for debugging.
;
0000 = FIXED equ FALSE
;
; Sets the arithmetic stack depth. This is *TINY*
; BASIC, so keep this small!
;
0008 = STACKSIZE equ 8 ;number of entries
;
; Common ASCII constants
;
0007 = BEL equ $07
0008 = BS equ $08
0009 = TAB equ $09
000a = LF equ $0A
000d = CR equ $0D
0022 = QUOTE equ $22
0020 = SPACE equ ' '
002c = COMMA equ ','
003b = SEMICOLON equ ';'
;
; These are error codes
;
0000 = ERR_NONE equ 0
0001 = ERR_EXPR equ 1 ;expression error
0002 = ERR_UNDER equ 2 ;stack underflow
0003 = ERR_OVER equ 3 ;stack overflow
0004 = ERR_EXTRA_STUFF equ 4 ;Stuff at end of line
0005 = ERR_SYNTAX equ 5 ;various syntax errors
0006 = ERR_DIVIDE_ZERO equ 6 ;divide by zero
0007 = ERR_READ_FAIL equ 7 ;error loading file
0008 = ERR_WRITE_FAIL equ 8 ;error saving file
0009 = ERR_NO_FILENAME equ 9
;
;=====================================================
; Zero page storage.
;
bss
0040 = org $0040
0040 = ILTrace ds 1 ;non-zero means tracing
0041 = variables ds 26*2 ;2 bytes, A-Z
0075 = variablesEnd equ *
0075 = ILPC ds 2 ;IL program counter
0077 = dpl ds 2
0079 = tempIL ds 2
007b = tempIlY ds 1
007c = offset ds 1
007d = lineLength ds 1
;
; CURPTR is a pointer to curent BASIC line being
; executed. Always points to start of line, CUROFF
; is the offset to the current character.
AS65 Assembler for R6502 [1.42]. Page 3
---------------------------------- mytb.asm ----------------------------------
;
007e = CURPTR ds 2
0080 = CUROFF ds 1
;
; R0 and R1 are used for arithmetic operations and
; general use.
;
0081 = R0 ds 2 ;arithmetic register 0
0083 = R1 ds 2 ;arithmetic register 1
;
; This is zero if in immediate mode, or non-zero
; if currently running a program. Any input from
; the main loop clears this, and the XFER IL
; statement will set it.
;
0085 = RunMode ds 1
;
; Used for line insertion/removal.
;
0086 = FROM ds 2
;
;=====================================================
;
code
0200 = org $0200
;
; Cold start is at $0200. Warm start is at $0203.
;
0200 : 4c1502 TBasicCold jmp cold2 ;jump around vectors
0203 : 4c8602 warm jmp warm2
;
; These are the user-supplied vectors to I/O routines.
; If you want, you can just patch these in the binary
; file, but it would be better to change the source
; code.
;
if KIM
OUTCH jmp $1ea0 ;output char in A
GETCH jmp $1e5a ;get char in A (blocks)
CRLF jmp $1e2f ;print CR/LF
OUTHEX jmp $1e3b ;print A as hex
MONITOR jmp $1c4f ;return to monitor
endif
if XKIM
include "xkim.inc"
;=====================================================
; This file contains vectors for Corsham Technologies'
; xKIM monitor. Last update 12/12/2021 for v1.8.
;
; Note that some subroutine names have changed
; slightly to fix duplicate names in the KIM monitor.
;
; See the xKIM User Manual for documentation on the
; data in this file.
;
; www.corshamtech.com
; https://github.com/CorshamTech/xKIM
;
e000 = xKIM_BASE equ $e000
bss
0088 = origBss equ * ;SAVE BSS!!!
e000 = org xKIM_BASE
AS65 Assembler for R6502 [1.42]. Page 4
---------------------------------- mytb.asm ----------------------------------
;
; Main functions
;
e000 = extKIM ds 3 ;extended monitor
e003 = xkOUTCH ds 3 ;output A to console
e006 = xkGETCH ds 3 ;get a key and echo
e009 = xkGETCHne ds 3 ;no echo - KIM can't do it
e00c = xKIM_res_0 ds 3 ;future - console stat
e00f = putsil ds 3 ;print string after JSR
e012 = getHex ds 3 ;get hex value in A
e015 = xkPRTBYT ds 3 ;print A as hex
e018 = getStartAddr ds 3
e01b = getEndAddr ds 3
e01e = getAddrRange ds 3
;
; future use
;
e021 = xkHexDump ds 3 ;perform a hex dump
e024 = xkMemEdit ds 3 ;edit memory
e027 = loadHexConsole ds 3 ;load hex via console
e02a = loadHexFile ds 3 ;load hex from SD
e02d = doDiskDir ds 3 ;do directory of SD card
e030 = calcOffset ds 3 ;compute branch offset
;
; SD card functions
;
; org xKIM_BASE+$0033
e033 = xParInit ds 3
e036 = xParSetWrite ds 3
e039 = xParSetRead ds 3
e03c = xParWriteByte ds 3
e03f = xParReadByte ds 3
e042 = DiskPing ds 3
e045 = DiskDir ds 3
e048 = DiskDirNext ds 3
e04b = DiskOpenRead ds 3
e04e = DiskRead ds 3
e051 = DiskClose ds 3
e054 = DiskOpenWrite ds 3
e057 = DiskWrite ds 3
;
dff8 = org $dff8
dff8 = AutoRun ds 2
dffa = ColdFlag ds 2
dffc = ExtensionAddr ds 2
dffe = HighestAddress ds 2
;
; New vectors will go here.
;
;
; Now restore BSS!
;
0088 = org origBss
code
0206 : 4ca01e OUTCH jmp $1ea0
0209 : 4c06e0 GETCH jmp xkGETCH
020c : 4c2f1e CRLF jmp $1e2f ;print CR/LF
020f : 4c15e0 OUTHEX jmp xkPRTBYT
0212 : 4c00e0 MONITOR jmp extKIM
e00f = puts equ putsil
AS65 Assembler for R6502 [1.42]. Page 5
---------------------------------- mytb.asm ----------------------------------
0084 = BUFFER_SIZE equ 132
endif
if CTMON65
include "ctmon65.inc"
code
OUTCH jmp cout
GETCH jmp cin
CRLF jmp crlf
OUTHEX jmp HexA
MONITOR jmp WARM
puts equ putsil
endif
;
0215 : 200fe0 cold2 jsr puts
0218 : 0d0a db CR,LF
021a : 426f6227732054.. db "Bob's Tiny BASIC v0.3"
022f : 0d0a db CR,LF
0231 : 68747470733a2f.. db "https://github.com/CorshamTech/6502-Tiny-BASIC"
025f : 0d0a00 db CR,LF,0
;
0262 : a98b lda #IL&$ff
0264 : 8575 sta ILPC
0266 : a90c lda #IL>>8
0268 : 8576 sta ILPC+1
;
026a : a984 lda #ProgramStart&$ff ;user prog
026c : 8d7c0f sta PROGRAMEND
026f : a90f lda #ProgramStart>>8
0271 : 8d7d0f sta PROGRAMEND+1
;
; Initialize the pseudo-random number sequence...
;
0274 : a95a lda #$5a
0276 : 8df30e sta rtemp1
0279 : a99d lda #%10011101
027b : 8df40e sta random
027e : a95b lda #%01011011
0280 : 8df50e sta random+1
;
0283 : 4c9302 jmp coldtwo
;
; This is the warm start entry point
;
0286 : 200c02 warm2 jsr CRLF
0289 : adee0e lda errGoto
028c : 8575 sta ILPC
028e : adef0e lda errGoto+1
0291 : 8576 sta ILPC+1
;
; And continue with both starts here
;
0293 : 20ab0b coldtwo jsr SetOutConsole
;
; The ILTrace flag is now run-time settable.
;
0296 : a900 lda #ILTRACE&$ff
0298 : 8540 sta ILTrace
;
029a : a900 lda #0
029c : 8585 sta RunMode
029e : 8d9a0e sta LINBUF
02a1 : a99a lda #LINBUF&$ff
AS65 Assembler for R6502 [1.42]. Page 6
---------------------------------- mytb.asm ----------------------------------
02a3 : 857e sta CURPTR
02a5 : a90e lda #LINBUF>>8
02a7 : 857f sta CURPTR+1 ;fall through...
;
;=====================================================
; This is the top of the IL interpreter. This fetches
; and executes the instruction currently pointed to
; by ILPC and adjusts ILPC to point to the next
; instruction to execute.
;
02a9 : a540 NextIL lda ILTrace
02ab : f003 beq NextIL2
02ad : 20330b jsr dbgLine
02b0 : a480 NextIL2 ldy CUROFF
02b2 : 202a0b jsr SkipSpaces
02b5 : 8480 sty CUROFF
;
02b7 : 205308 jsr getILByte
;
; When the handler is called, these are the conditions
; of several important items:
;
; (ILPC) will point to the byte AFTER the IL
; opcode being executed.
;
; (CURPTR),CUROFF will point to the start of the
; next word in the input buffer. Ie, the next word
; in the user program.
;
02ba : 0a asl a
02bb : c95a cmp #ILTBLend-ILTBL+2
02bd : 9033 bcc ILgood
;
; This handles an illegal IL opcode. This is serious
; and there's no way to recover.
;
02bf : 200fe0 ILbad jsr puts
02c2 : 0d0a db CR,LF
02c4 : 496c6c6567616c.. db "Illegal IL "
02cf : 00 db 0
;
; Well this is awkward, we need to back up the IL
; by one since it no longer points to the current
; opcode.
;
02d0 : 206008 jsr decIL
;
02d3 : a000 ldy #0
02d5 : b175 lda (ILPC),y
02d7 : 200f02 jsr OUTHEX
02da : 200fe0 jsr puts
02dd : 2061742000 db " at ",0
02e2 : a576 lda ILPC+1
02e4 : 200f02 jsr OUTHEX
02e7 : a575 lda ILPC
02e9 : 200f02 jsr OUTHEX
02ec : 200c02 jsr CRLF
02ef : 4c1202 jmp MONITOR
;
; Just jump to the address (ILPC),y. Have to do
; some goofy stuff.
;
AS65 Assembler for R6502 [1.42]. Page 7
---------------------------------- mytb.asm ----------------------------------
02f2 : a8 ILgood tay ;move index into Y
02f3 : b90003 lda ILTBL,y
02f6 : 8577 sta dpl
02f8 : b90103 lda ILTBL+1,y
02fb : 8578 sta dpl+1
02fd : 6c7700 jmp (dpl) ;go to handler
;
;=====================================================
; This is the IL jump table. The IL opcode is
; mulitplied by two, then looked-up in this table.
; There is absolutely nothing special about the order
; of entries here... they all decode at exactly the
; same speed. However the entry number must match the
; values in IL.inc.
;
0300 : 6b03 ILTBL dw iXINIT ;0
0302 : 7303 dw iDONE ;1
0304 : 8603 dw iPRS ;2
0306 : a903 dw iPRN ;3
0308 : b203 dw iSPC ;4
030a : cb06 dw iNLINE ;5
030c : ba03 dw iNXT ;6
030e : d203 dw iXFER ;7
0310 : ff03 dw iSAV ;8
0312 : 0204 dw iRSTR ;9
0314 : 0504 dw iCMPR ;10
0316 : 4704 dw iINNUM ;11
0318 : 6704 dw iFIN ;12
031a : 7804 dw iERR ;13
031c : c404 dw iADD ;14
031e : da04 dw iSUB ;15
0320 : f004 dw iNEG ;16
0322 : 0805 dw iMUL ;17
0324 : 4205 dw iDIV ;18
0326 : 8b05 dw iSTORE ;19
0328 : 9e05 dw iIND ;20
032a : ae05 dw iLST ;21
032c : 5803 dw iINIT ;22
032e : 0d06 dw iGETLINE
0330 : 1906 dw iINSRT ;24
0332 : c506 dw iRTN ;25
0334 : 1202 dw MONITOR ;26
0336 : de06 dw iLIT ;27
0338 : d106 dw iCALL ;28
033a : d406 dw iJMP ;29
033c : eb06 dw iVINIT ;30
033e : f906 dw iERRGOTO
0340 : 0507 dw iTST ;32
0342 : 2e07 dw iTSTV ;33
0344 : 5407 dw iTSTL ;34
0346 : 6e07 dw iTSTN ;35
0348 : b107 dw iFREE ;36
034a : ba07 dw iRANDOM ;37
034c : 3208 dw iABS ;38
;
; Disk functions. There must be pointers
; to functions even if no disk is supported.
; Makes things easier in IL.inc.
;
if DISK_ACCESS
034e : b90b dw iOPENREAD
0350 : e50b dw iOPENWRITE
AS65 Assembler for R6502 [1.42]. Page 8
---------------------------------- mytb.asm ----------------------------------
0352 : 440c dw iDCLOSE ;41
0354 : 040c dw iDGETLINE ;Life, universe, everything
0356 : 3e0c dw iDLIST ;43
else
dw NextIL ;39
dw NextIL ;40
dw NextIL ;41
dw NextIL ;42
dw NextIL ;43
endif
;
0358 = ILTBLend equ *
;
;=====================================================
;=====================================================
;=====================================================
; This marks the start of the handlers for IL opcodes.
;=====================================================
;=====================================================
;=====================================================
;
;
0358 : a900 iINIT lda #0 ;clear IL stack pointer
035a : 8d880e sta retStackPtr
;
035d : a984 lda #ProgramStart&$ff ;user prog
035f : 857e sta CURPTR
0361 : 8d7c0f sta PROGRAMEND
0364 : a90f lda #ProgramStart>>8
0366 : 857f sta CURPTR+1
0368 : 8d7d0f sta PROGRAMEND+1
;
; fall into XINIT...
;
;=====================================================
; This initializes for the start of the next line of
; BASIC text.
;
036b : a900 iXINIT lda #0
036d : 8d770e sta mathStackPtr ;clear math stack
0370 : 4ca902 goodExit jmp NextIL
;
;=====================================================
; Verify there is nothing else on this input line.
; If there is, generate an error.
;
0373 : a480 iDONE ldy CUROFF
0375 : 202a0b jsr SkipSpaces
0378 : b17e lda (CURPTR),y
037a : f007 beq doneadv
037c : a204 ldx #ERR_EXTRA_STUFF
037e : a900 lda #0
0380 : 4c7b04 jmp iErr2
;
; Advance to the next line
;
0383 : doneadv
; jsr FindNext2
0383 : 4ca902 jmp NextIL
;
;=====================================================
; Print the string until a closing quote
AS65 Assembler for R6502 [1.42]. Page 9
---------------------------------- mytb.asm ----------------------------------
;
0386 : a480 iPRS ldy CUROFF
;
; Odd logic here. The main loop skipped any leading
; whitespace inside the quoted text, so move back to
; the quote, then move forward again.
;
0388 : a922 lda #'"' ;pre-load with char to find
038a : 88 iPRS3 dey ;move back one
038b : d17e cmp (CURPTR),y ;quote?
038d : d0fb bne iPRS3
038f : c8 iny
0390 : 8480 sty CUROFF
;
0392 : b17e iPRS2 lda (CURPTR),y
0394 : f010 beq PRSend2 ;end of line!
0396 : c922 cmp #'"'
0398 : f009 beq PRSend
039a : 200602 jsr OUTCH
039d : e680 inc CUROFF
039f : a480 ldy CUROFF
03a1 : d0ef bne iPRS2
03a3 : c8 PRSend iny ;skip closing quote
03a4 : 8480 sty CUROFF
03a6 : 4ca902 PRSend2 jmp NextIL
;
;=====================================================
; Pop the top off the stack and print it as a signed
; decimal number.
;
03a9 : 20850a iPRN jsr popR0
03ac : 20fd08 jsr PrintDecimal
03af : 4ca902 jmp NextIL
;
;=====================================================
; Space to next zone. Currently the code does not
; keep track of which column the output is on, so
; just print a tab.
;
03b2 : a909 iSPC lda #TAB
03b4 : 200602 jsr OUTCH
03b7 : 4ca902 jmp NextIL
;
;=====================================================
; If in immediate mode, jump to the address following
; the NXT instruction. Else move to the next line of
; user code and continue.
;
03ba : a585 iNXT lda RunMode
03bc : d003 bne iNxtRun ;in run mode
;
; Get address and jump to it.
;
03be : 4cd406 jmp iJMP
;
03c1 : 20d908 iNxtRun jsr FindNextLine
03c4 : 20f008 jsr AtEnd
03c7 : d003 bne iNxtRun2 ;not at end
;
; At the end of the program. Pretend an END statement
; was found.
;
AS65 Assembler for R6502 [1.42]. Page 10
---------------------------------- mytb.asm ----------------------------------
03c9 : 4c6704 iFINv jmp iFIN
;
03cc : 204f08 iNxtRun2 jsr getILWord ;ignore next word
03cf : 4ca902 jmp NextIL
;
;=====================================================
; XFER takes the number on top of the stack and looks
; for that line in the program, or the next line
; higher. Ie, if it's 1 but there is no line 1, then
; find the next one after that.
;
03d2 : 20850a iXFER jsr popR0
03d5 : 209608 jsr findLine
03d8 : 20f008 iXFER2 jsr AtEnd ;at end of user program?
03db : f0ec beq iFINv
03dd : a002 ldy #2 ;point to start of text
03df : 8480 sty CUROFF
03e1 : a9ff lda #$ff
03e3 : 8585 sta RunMode
;
; Transfer IL to STMT. I don't like having this
; hard-coded; fix it.
;
03e5 : a999 lda #STMT&$ff
03e7 : 8575 sta ILPC
03e9 : a90c lda #STMT>>8
03eb : 8576 sta ILPC+1
03ed : 4ca902 jmp NextIL
;
; Run
;
03f0 : iXferok
03f0 : a9ff lda #$ff
03f2 : 8585 sta RunMode ;we're running
;
; Need a more elegant way to do this
;
03f4 : a999 lda #STMT&$ff
03f6 : 8575 sta ILPC
03f8 : a90c lda #STMT>>8
03fa : 8576 sta ILPC+1
03fc : 4ca902 jmp NextIL
;
;=====================================================
; Save the pointer to the next line to the call stack.
;
03ff : iSAV
03ff : 4cbf02 jmp ILbad
;
;=====================================================
; Pop the next line from the call stack.
;
0402 : iRSTR
0402 : 4cbf02 jmp ILbad
;
;=====================================================
; Compare items on stack. Okay, so on input there are
; three things on the stack
;
; EXPR2 <- Top of stack
; OP <- relational operator, next on stack
; EXPR1 <- last item on stack
AS65 Assembler for R6502 [1.42]. Page 11
---------------------------------- mytb.asm ----------------------------------
;
; Comparison is: EXPR1 <operator> EXPR2
;
; Operator is one of...
;
; 2 is =
; 1 is <
; 3 is <=
; 5 is <>
; 4 is >
; 6 is >=
;
; Those are bit-mapped:
;
; xxxxxGEL
;
; G = Greater than
; E = Equal
; L = Less than
;
; If the comparison is false, do a NXT, ie, move to th
; next line and continue. If true, continue executing
; on this line.
;
0001 = REL_LT equ %001
0002 = REL_EQUAL equ %010
0004 = REL_GT equ %100
;
0405 : 20980a iCMPR jsr popR1
0408 : 20ab0a jsr popMQ ;operator in MQ
040b : 20850a jsr popR0
;
; See if they are equal or not
;
040e : a581 lda R0
0410 : c583 cmp R1
0412 : d00a bne iCMPRnoteq ;try not equal
0414 : a582 lda R0+1
0416 : c584 cmp R1+1
0418 : d004 bne iCMPRnoteq
;
; Equal, set the flag in MQ+1
;
041a : a902 lda #REL_EQUAL
041c : d014 bne iCMPcom
;
; See if EXPR1 (R0) < EXPR2 (R1)
; See www.6502.org/tutorials/compare_beyond.html
;
041e : a581 iCMPRnoteq lda R0
0420 : c583 cmp R1
0422 : a582 lda R0+1
0424 : e584 sbc R1+1
0426 : 5002 bvc iCMPR_2
0428 : 4980 eor #$80
042a : 3004 iCMPR_2 bmi iCMPlt
042c : a904 lda #REL_GT
042e : d002 bne iCMPcom
0430 : a901 iCMPlt lda #REL_LT ;R0 < R1
0432 : 0df10e iCMPcom ora MQ+1
;
; Now compare the end result with what the caller
AS65 Assembler for R6502 [1.42]. Page 12
---------------------------------- mytb.asm ----------------------------------
; was looking for.
;
0435 : 2df00e and MQ
0438 : f007 beq iCMPno ;no match
043a : 4ca902 jmp NextIL
;
; R0 > R1
;
043d : a904 iCMPgt lda #REL_GT
043f : d0f1 bne iCMPcom
;
; Not a match, so jump to the next line of code.
;
0441 : 20d908 iCMPno jsr FindNextLine
0444 : 4cd803 jmp iXFER2
;
;=====================================================
; Get a line of text from the user, convert to a
; number, leave on top of stack.
;
0447 : a580 iINNUM lda CUROFF ;save state before GetLine
0449 : 48 pha
044a : a57f lda CURPTR+1
044c : 48 pha
044d : a57e lda CURPTR
044f : 48 pha
;
0450 : a93f lda #'?'
0452 : 20e009 jsr GetLine
0455 : 206909 jsr getDecimal
0458 : 205f0a jsr pushR0 ;put onto stack
;
045b : 68 pla
045c : 857e sta CURPTR
045e : 68 pla
045f : 857f sta CURPTR+1
0461 : 68 pla
0462 : 8580 sta CUROFF
;
0464 : 4ca902 jmp NextIL
;
;=====================================================
; Stop the currently running program. Actually very
; simple to do... clear the RunMode flag, then set the
; ILPC to the standard handler and continue running.
;
0467 : a900 iFIN lda #0
0469 : 8585 sta RunMode
;
046b : adee0e lda errGoto
046e : 8575 sta ILPC
0470 : adef0e lda errGoto+1
0473 : 8576 sta ILPC+1
0475 : 4ca902 jmp NextIL
;
;=====================================================
; Handle the ERR opcode. Following the instruction is
; a 16 bit error number. Print an error message, and
; if we're in run mode, print the line number. Stop
; program execution and return to the initial state.
;
0478 : 204f08 iERR jsr getILWord ;get err code
AS65 Assembler for R6502 [1.42]. Page 13
---------------------------------- mytb.asm ----------------------------------
;
; Enter here with the error code in X (LSB) and A (MSB
;
047b : 8681 iErr2 stx R0
047d : 8582 sta R0+1
;
047f : 200fe0 jsr puts
0482 : 4572726f722000 db "Error ",0
0489 : 20fd08 jsr PrintDecimal
;
048c : a585 lda RunMode ;running?
048e : f01b beq iERR2 ;nope
0490 : 200fe0 jsr puts
0493 : 206174206c696e.. db " at line ",0
049d : a000 ldy #0
049f : b17e lda (CURPTR),y
04a1 : 8581 sta R0
04a3 : c8 iny
04a4 : b17e lda (CURPTR),y
04a6 : 8582 sta R0+1
04a8 : 20fd08 jsr PrintDecimal
;
04ab : 200c02 iERR2 jsr CRLF
04ae : a900 lda #0
04b0 : 8585 sta RunMode ;fall through...
;
;=====================================================
; Reset the IL to be back at the idle loop. Does not
; clear variables so the user can see what state
; the program is in.
;
04b2 : a900 ResetIL lda #0
04b4 : 8d880e sta retStackPtr
04b7 : adee0e lda errGoto
04ba : 8575 sta ILPC
04bc : adef0e lda errGoto+1
04bf : 8576 sta ILPC+1
04c1 : 4ca902 jmp NextIL
;
;=====================================================
; Pop two items off stack, add them, then place the
; result back onto the stack.
;
04c4 : 20850a iADD jsr popR0
04c7 : 20980a jsr popR1
04ca : 18 clc
04cb : a581 lda R0
04cd : 6583 adc R1
04cf : 8581 sta R0
04d1 : a582 lda R0+1
04d3 : 6584 adc R1+1
04d5 : 8582 sta R0+1
04d7 : 4c3c05 jmp pushR0nextIl
;
;=====================================================
; Pop two items off the stack. Subtract the top of
; stack from the lower entry.
;
04da : 20980a iSUB jsr popR1
04dd : 20850a jsr popR0
04e0 : 38 sec
04e1 : a581 lda R0
AS65 Assembler for R6502 [1.42]. Page 14
---------------------------------- mytb.asm ----------------------------------
04e3 : e583 sbc R1
04e5 : 8581 sta R0
04e7 : a582 lda R0+1
04e9 : e584 sbc R1+1
04eb : 8582 sta R0+1
04ed : 4c3c05 jmp pushR0nextIl
;
;=====================================================
; Negate the top of stack.
;
04f0 : 20850a iNEG jsr popR0
04f3 : a581 lda R0
04f5 : 49ff eor #$ff
04f7 : 8581 sta R0
04f9 : a582 lda R0+1
04fb : 49ff eor #$ff
04fd : 8582 sta R0+1
04ff : e681 inc R0
0501 : d002 bne iNEG2
0503 : e682 inc R0+1
0505 : 4c3c05 iNEG2 jmp pushR0nextIl
;
;=====================================================
; Multiply top two items on the stack, put the results
; on top. This uses the algorithm documented on page
; 115 of "Microprocessor Programming for Computer
; Hobbyists" by Neill Graham.
;
0508 : 20850a iMUL jsr popR0 ;AC
050b : 20980a jsr popR1 ;OP
;
050e : a581 lda R0
0510 : 8df00e sta MQ
0513 : a582 lda R0+1
0515 : 8df10e sta MQ+1
0518 : a900 lda #0 ;clear result
051a : 8581 sta R0
051c : 8582 sta R0+1
;
051e : a210 ldx #16 ;number of bits in value
0520 : 0681 multloop asl R0
0522 : 2682 rol R0+1
0524 : 0ef00e asl MQ
0527 : 2ef10e rol MQ+1
052a : 900d bcc multno ;skip add if no carry
;
; Add R1 back into R0
;
052c : 18 clc
052d : a581 lda R0
052f : 6583 adc R1
0531 : 8581 sta R0
0533 : a582 lda R0+1
0535 : 6584 adc R1+1
0537 : 8582 sta R0+1
;
0539 : ca multno dex ;did all bits yet?
053a : d0e4 bne multloop
;
053c : 205f0a pushR0nextIl jsr pushR0 ;OP
053f : 4ca902 jmp NextIL
;
AS65 Assembler for R6502 [1.42]. Page 15
---------------------------------- mytb.asm ----------------------------------
;=====================================================
; Divide the top of stack into the next to top item.
; Leave results on stack. Taken from:
; http://codebase64.org/doku.php?id=base:16bit_divisio
;
; MQ = R0 / R1
; Remainder is in R0
;
0542 : 20980a iDIV jsr popR1
0545 : 20850a jsr popR0
;
; Check for divide by zero
;
0548 : a583 lda R1
054a : 0584 ora R1+1
054c : f036 beq divby0
;
054e : 20c00a jsr SaveSigns
0551 : a900 lda #0 ;preset remainder to 0
0553 : 8df00e sta MQ
0556 : 8df10e sta MQ+1
0559 : a210 ldx #16 ;repeat for each bit: ...
055b : 0681 divloop asl R0 ;dividend lb & hb*2, msb -> Carry
055d : 2682 rol R0+1
055f : 2ef00e rol MQ ;remainder lb & hb * 2 + msb from carry
0562 : 2ef10e rol MQ+1
0565 : adf00e lda MQ
0568 : 38 sec
0569 : e583 sbc R1 ;substract divisor to see if it fits in
056b : a8 tay ;lb result -> Y, for we may need it late
056c : adf10e lda MQ+1
056f : e584 sbc R1+1
0571 : 9008 bcc skip ;if carry=0 then divisor didn't fit in yet
0573 : 8df10e sta MQ+1 ;else save substraction result as new remai
0576 : 8cf00e sty MQ
0579 : e681 inc R0 ;and INCrement result cause divisor fit in 1
057b : ca skip dex
057c : d0dd bne divloop
057e : 20fb0a jsr RestoreSigns
0581 : 4c3c05 jmp pushR0nextIl
;
; Indicate divide-by-zero error
;
0584 : a206 divby0 ldx #ERR_DIVIDE_ZERO
0586 : a900 lda #0
0588 : 4c7b04 jmp iErr2
;
;=====================================================
; This pops the top two items off the stack. The top
; item is a data value and the other is an index into
; the variable table. Save the value into that entry.
;
058b : 20850a iSTORE jsr popR0 ;data
058e : 20980a jsr popR1 ;index
0591 : a683 ldx R1 ;get index
0593 : a581 lda R0
0595 : 9541 sta variables,x
0597 : a582 lda R0+1
0599 : 9542 sta variables+1,x
AS65 Assembler for R6502 [1.42]. Page 16
---------------------------------- mytb.asm ----------------------------------
059b : 4ca902 jmp NextIL
;
;=====================================================
; Replaces the top of stack with the variable whose
; index it represents.
;
059e : 20980a iIND jsr popR1
05a1 : a683 ldx R1 ;get index
05a3 : b541 lda variables,x
05a5 : 8581 sta R0
05a7 : b542 lda variables+1,x
05a9 : 8582 sta R0+1
05ab : 4c3c05 jmp pushR0nextIl
;
;=====================================================
; List the current BASIC program in memory. Uses R0,
; tempIly, and dpl.
;
05ae : 20ab0b iLST jsr SetOutConsole
05b1 : a984 iLST2 lda #ProgramStart&$ff
05b3 : 8577 sta dpl
05b5 : a90f lda #ProgramStart>>8