Last active
March 27, 2024 14:54
-
-
Save thentenaar/275041e638a2145d97f237b42934acd6 to your computer and use it in GitHub Desktop.
Simple TI 99/4a XB Little Man Computer + Line Assembler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 REM Simple XB Little Man Computer + Line Assembler | |
2 REM Copyright (C) 2021 Tim Hentenaar. | |
3 REM This code is licenced under the Simplified BSD License. | |
4 REM https://opensource.org/license/bsd-2-clause | |
10 DIM MEM(100) ! Mailboxes (memory) | |
20 DIM MPOS(100,2) ! Screen positions for mailbox values | |
30 PC,IR,AR,A,N,H,IN,OUT=0 | |
40 GOTO 50 :: I :: K :: S :: OP :: L$ :: CALL CLEAR :: CALL HCHAR :: CALL VCHAR :: CALL KEY :: CALL COLOR :: !@P- | |
50 FOR I = 0 TO 99 | |
60 MPOS(I+1,1) = 5 + (I - INT(I/20) * 20) ! Row position | |
70 MPOS(I+1,2) = 5 + 5 * INT(I/20) ! Col position | |
80 MEM(I+1) = 0 | |
90 NEXT I | |
100 FOR I=0 TO 14 :: CALL COLOR(I,4,2) :: NEXT I :: I = 0 :: GOSUB 600 | |
110 IR,OP=0 :: CALL CLEAR | |
120 DISPLAY AT(1,1):"PC" :: DISPLAY AT(1,9):"IR" :: DISPLAY AT(1,17):"AR" | |
130 DISPLAY AT(2,1):"A" :: DISPLAY AT(2,9):"IN" :: DISPLAY AT(2,17):"OUT" | |
140 GOSUB 300 ! Draw Register States | |
150 CALL HCHAR(4,6,95,25) | |
160 FOR I = 0 TO 4 :: DISPLAY AT(3,5*(I+1)):I*20 :: NEXT I | |
170 FOR I = 0 TO 19 :: DISPLAY AT(5+I,1):I :: NEXT I | |
180 FOR I = 3 TO 28 STEP 5 :: CALL VCHAR(5,3+I,124,20) :: NEXT I | |
190 FOR I = 1 TO 100 :: DISPLAY AT(MPOS,I,1),MPOS(I,2)) SIZE(4):MEM(I) :: NEXT I | |
200 REM Main Loop: Wait for a key and step/halt | |
210 ON WARNING NEXT | |
220 CALL KEY(0,K,S) :: IF S=0 THEN 220 | |
230 IF K=72 OR K=104 THEN 280 ! [H]alt | |
240 IF H OR (K<>83 AND K<>115) THEN 220 ! [S]tep | |
250 GOSUB 400 ! Fetch, Decode, Execute | |
260 IF H THEN DISPLAY AT(1,24) BEEP:"HALT" | |
270 GOTO 220 | |
280 I = PC :: GOSUB 600 ! Back to monitor mode | |
290 GOTO 110 | |
300 REM Draw the state of the registers | |
310 DISPLAY AT (1,4) SIZE(4):PC | |
320 DISPLAY AT (1,12) SIZE(2):IR | |
330 DISPLAY AT (1,20) SIZE(2):AR | |
340 DISPLAY AT (2,4) SIZE(4):A | |
350 DISPLAY AT (2,12) SIZE(4):IN | |
360 DISPLAY AT (2,21) SIZE(4):OUT | |
370 RETURN | |
400 REM Fetch, Decode, Execute (4xx is undefined / treated as NOP) | |
410 AR = MEM(PC + 1) ! Fetch instruction | |
420 IR = INT(AR / 100) ! Decode opcode | |
430 OP = 1 + AR - (IR * 100) ! Decode operand | |
440 PC = PC + 1 :: IF PC > 99 THEN PC = PC - 100 | |
450 IF IR=0 THEN 470 | |
460 ON IR GOSUB 510, 520, 530, 595, 540, 550, 560, 570, 580 | |
470 H = IR=0 ! HLT | |
480 N = -1*((A>999)+(A<0)) ! Set N if an overflow occured | |
490 IF N=1 THEN A = A + 999 * (A>0+(-1*A<0)) ! Ensure A remains within range | |
500 GOTO 300 ! Draw register states | |
510 A = A + MEM(OP) :: RETURN ! 1: ADD | |
520 A = A - MEM(OP) :: RETURN ! 2: SUB | |
530 MEM(OP) = A :: DISPLAY AT(MPOS(OP,1),MPOS(OP,2)) SIZE(4):A :: RETURN !3: STA | |
540 A = MEM(OP) :: RETURN ! 5: LDA | |
550 PC = OP - 1 :: RETURN ! 6: BRA | |
560 IF A=0 THEN PC=OP - 1 ! 7: BRZ | |
565 RETURN | |
570 IF N=0 THEN PC=OP - 1 ! 8: BRP | |
575 RETURN | |
580 IF OP = 2 THEN ACCEPT AT(2,12) BEEP VALIDATE(NUMERIC) SIZE(4):IN :: A=IN ! 9: INP | |
590 IF OP = 3 THEN OUT = A ! 9: OUT | |
595 RETURN | |
600 CALL CLEAR ! Code Entry (assumes I is set on entry) | |
610 PRINT "LMC Assembler Version 1.0" | |
620 PRINT "Enter '?' at the prompt for help" :: PRINT | |
630 I = I + 1 :: IF I > 100 THEN I = I - 100 ! Handle Overflow | |
640 ON ERROR 850 ! Invalid input, etc. | |
650 LINPUT STR$(I - 1) & " (" & STR$(MEM(I)) & ") > ":L$ | |
660 IF LEN(L$) = 0 THEN 630 ELSE IR = ASC(SEG$(L$,1,1)) | |
690 IF IR=63 THEN 920 ! ? (Help) | |
670 IF IR=68 OR IR=100 THEN 860 ! [D]isplay | |
680 IF IR=71 OR IR=103 THEN 880 ! [G]o | |
700 IF IR=82 OR IR=114 THEN ON ERROR STOP :: H=0 :: PC=I-1 :: RETURN ! [R]un | |
710 IF IR=45 OR (IR>47 AND IR<58) THEN 900 ! Number literal -> mailbox | |
720 IF LEN(L$) > 3 THEN OP = VAL(SEG$(L$,5,2)) | |
730 L$ = SEG$(L$,1,3) | |
740 IF L$="HLT" OR L$="hlt" THEN MEM(I) = 0 :: GOTO 630 ! 0: HLT | |
750 IF L$="ADD" OR L$="add" THEN MEM(I) = 100 + OP :: GOTO 630 ! 1: ADD | |
760 IF L$="SUB" OR L$="sub" THEN MEM(I) = 200 + OP :: GOTO 630 ! 2: SUB | |
770 IF L$="STA" OR L$="sta" THEN MEM(I) = 300 + OP :: GOTO 630 ! 3: STA | |
780 IF L$="LDA" OR L$="lda" THEN MEM(I) = 500 + OP :: GOTO 630 ! 5: LDA | |
790 IF L$="BRA" OR L$="bra" THEN MEM(I) = 600 + OP :: GOTO 630 ! 6: BRA | |
800 IF L$="BRZ" OR L$="brz" THEN MEM(I) = 700 + OP :: GOTO 630 ! 7: BRZ | |
810 IF L$="BRP" OR L$="brp" THEN MEM(I) = 800 + OP :: GOTO 630 ! 8: BRP | |
820 IF L$="INP" OR L$="inp" THEN MEM(I) = 901 :: GOTO 630 ! 9: INP | |
830 IF L$="OUT" OR L$="out" THEN MEM(I) = 902 :: GOTO 630 ! 9: OUT | |
840 PRINT "Invalid instruction or command" :: PRINT :: GOTO 640 | |
850 PRINT "Invalid input" :: PRINT :: GOTO 640 | |
860 IR = VAL(SEG$(L$,3,2)) ! [D]isplay | |
870 IF ((IR<0)*(IR>99))=0 THEN PRINT MEM(IR + 1) :: GOTO 640 ELSE GOTO 850 | |
880 IR = VAL(SEG$(L$,3,2)) ! [G]o | |
890 IF ((IR<0)*(IR>99))=0 THEN I = IR + 1 :: GOTO 640 ELSE GOTO 850 | |
900 IR = VAL(L$) ! Literal -> Mailbox | |
910 IF ((IR<-999)*(IR>999))=0 THEN MEM(I) = IR :: GOTO 630 ELSE GOTO 850 | |
920 PRINT "-------- Help --------" | |
921 PRINT "You can enter a number to store that number in the mailbox given"; | |
922 PRINT "by the prompt. You may also enter a mnemonic instruction to be"; | |
923 PRINT "assembled." :: PRINT | |
924 PRINT "The following commands are available:" | |
925 PRINT "D mailbox - Display a mailbox (0 - 99)" | |
926 PRINT "G mailbox - Move to a mailbox" | |
927 PRINT "R - Run the program from the current mailbox" :: PRINT | |
928 PRINT "In run mode, press 'S' to step through the program or"; | |
929 PRINT "'H' to return to the prompt" :: PRINT | |
930 GOTO 650 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment