BASIC/DEBUG
BASIC/DEBUG ist eine Tiny-BASIC-Implementierung für den Z8. Entstanden ist sie vermutlich 1979/1980.
In nur 2 KByte ROM des Z8671 steckt ein vollwertiges BASIC mit folgenden Eigenschaften:
- Editor
- 15 BASIC-Kommandos
- 16-Bit Ganzzahlarithmetik
- Punkt-vor-Strich-Rechnung
- Hexadezimalzahlen
- Direktzugriff auf Register und Speicher
Das BASIC ist im Zilog-Handbuch z8671_basic_debug.pdf ausführlich beschrieben.
Das Basic orientiert sich sehr stark an das TINY-BASIC von Tom Pittman (http://www.ittybittycomputers.com/ittybitty/tinybasic/). Literatur und Programme zu den dort beschriebenen BASICs für 1802, 6502, 6800-Controller passen auch zum BASIC/DEBUG des Z8671.
11/2021: Tom Pittman hat mir bestätigt, dass er dieses BASIC Ende der 70er im Auftrag von Zilog programmiert hat.
Downloads
- z8671-basic_debug_src.zip meine reassemblierten und kommentierten Quellen:
- Z8 assembler source
- IL source + IL Makros
- IL Decompiler (perl)
- tb_pittman.zip Quellen der Tiny-BASIC-Versionen von T.Pittman (für RCA1802, 6502, 6800) sowie die aufbereiteten IL zwecks Vergleich
zur Anpassung an andere Systeme und andere Adressen sowie Erweiterungen s. BASIC/DEBUG für ES4.0
Aufbau
2021 habe ich den ROM vollständig und umfassend reassembliert, analysiert und dokumentiert:
BASIC/DEBUG ist in einer eigenen Codesprache geschrieben: TBIL (Tiny Basic Interpreter Language) Tiny_BASIC#Implementation_in_a_virtual_machine.
Das BASIC selbst ist nur 432 Byte groß. In Z8-Code ist der Interpreter für diese Codesprache enthalten, sowie Initialisierung und In/Out-Code. Diese Art der Implementierung ist extrem speichersparend. Nur so konnten die umfangreichen Fähigkeiten des BASIC/DEBUG in nur 2048 Byte untergebracht werden.
Das Zwiebelmodell (s. Bild) beschreibt sehr schön den Ablauf: Das BASIC-Anwenderprogramm wird vom BASIC-Interpreter (in TBIL) interpretiert. Dieser wiederum wird vom TBIL-Interpreter (in Z8-Code) interpretiert, und das ganze läuft auf einem Z8-Prozessor und kommuniziert mit der Außenwelt.
BASIC/DEBUG ist vielfältig konfigurierbar und bietet u.a. folgende Optionen
- beliebige RAM-Unterstützung oder reine ROM-Version
- mehrere BASIC-Programm im Speicher
- Autostart eines Programms nach RESET
- Editierzeichen für DEL, Zeilenende-Zeichenfolge frei vergebbar
- eigene I/O-Treiber anstelle Nutzung der Z8-SIO
Literatur
- z8671_basic_debug.pdf von Zilog. (der Hochpfeil in der Doku ist das Zeichen „^“)
- Buch „Mikroprozessoren in der Meß- und Regeltechnik. Funktion - Aufbau und Programmierung“ von Gerhard Ledig, Franzis-Verlag 1988
weitere Literatur zu Tom Pittman's Tiny-BASIC:
orig. Scans
HTML:
- TINY BASIC User Manual
http://www.ittybittycomputers.com/ittybitty/tinybasic/TBuserMan.htm
Beispielprogramme:
- TBprogs.zip, Advent.txt, Euphoria.txt, LifeTB.txt
http://www.ittybittycomputers.com/ittybitty/tinybasic/ - The First Book of Tiny BASIC Programs
https://www.retrotechnology.com/memship/Son_of_TFBOTBAS.HTM - Tiny Basic Experimenters Kit
http://www.ittybittycomputers.com/ittybitty/tinybasic/TBEK.txt - originale Scans und Beispiele und weitere Dokumente
http://retro.hansotten.nl/6502-sbc/kim-1-manuals-and-software/kim-1-software/
Beispiel
Das folgende Programm zeigt eine Autostart-BASIC-Programm und eigene I/O-Treiber:
Damit Autostart funktioniert, muss das Programm auf Adresse 1020h beginnen. Die Zeilennummer muss < 256 sein (d.h. das erste Byte == 0).
Im Zeile 1 wird Register %FB (Interrupt mask register) gesetzt. Dadurch werden die externen I/O-Teiber aktiviert. Nachfolgende PRINT-Befehle geben dann über diese Treiber aus. Als Beispiel wurde zu Testzwecken ein einfacher Ringpuffer implementiert.
External I/O drivers must conform to the following requirements: They must pass a single ASCII input or output character in R19 with the register pointer set to R16-31. Registers R4-R15 and R22-32 must be preserved. Location %1012 must contain a jump to the character input driver, and %1015 a jump to the character output driver. The input routine must do any necessary echoing, and the parity bit (bit 7) of all input characters must be set to 0. Drivers return to Basic/Debug with a RETURN instruction (hex AF)
cpu z8601
org 1000h
; interrupt routines
jp 0 ; IRQ 0
jp 0 ; IRQ 1
jp 0 ; IRQ 2
jp 0 ; IRQ 3
jp 0 ; IRQ 4
jp 0 ; IRQ 5
; character io
org 1012h
jp CI
jp CO
; Basic-Pgm
org 1020h
db 0,5,"@251=0:REM EXTERNAL IO",0
db 0,10,"LET A=%1234:PRINT HEX(A)",0
db 0,20,"STOP",0
db 0ffh,0ffh
; input driver
CI: ret
; output driver
; use ram ringbuffer 8000h..9000h for simple output
CO: srp #60h
cp r0, #90h
jr ge, co2
cp r0, #80h
jr ge, co1
co2: ld r0,#80h
ld r1,#0
co1: ld r3,13h
ldc @rr0,r3
incw rr0
srp #10h
ret
eigene TBIL
Nicht im Handbuch erwähnt ist die Möglichkeit, einen eigenen BASIC-Interpreter (in TBIL) anstelle des im ROM enthaltenen zu nutzen: Die Adresse des Interpreters steht im Constant Block in Byte 0 und 1. Wird ein externer Constant Block genutzt, kann ein eigener/erweiterter BASIC-Interpreter angesprochen werden. Es ist sogar möglich, maximal drei eigene TBIL-Codes (19, 1E, 1F) zu definieren und zu verwenden! Diese drei OP-Codes sind original nicht genutzt. Auf den Adressen 1018h, 101Bh, 101Eh (nur 2 Byte) sind Sprünge zu den zugehörigen Implementierungen zu setzen.
org 1018h ; IL Extension jp xxxx ; IL_19 jp xxxx ; IL_1E jr xxxx ; IL_1F 101Eh; nur 2 Byte, sonst memory overlapping mit Autostart-Programm ; Basic-Pgm org 1020h db 0,1,"^28=%1100",0 ; SET EXTERNAL CONSTANT BLOCK db ... own syntax by own IL ... db 0ffh,0ffh ; costant block org 1100h ; must be xxx0-address db hi(il) ; 0 00650h db lo(il) ; 1 db 20h ; 2 stack reserve db 8 ; 3 backspace code db 1Bh ; 4 cancel code db 0Dh ; 5 line separator sequence terminating with 0FEh db 0Ah ; 6 db 0FEh ; end of constant block ; own IL program: il: ...
Es ist nicht bekannt, ob das für die Entwicklung gedacht war oder ob es erweiterte IL-Programme gibt.
IL Source
Tom Pittman beschreibt in http://www.ittybittycomputers.com/ittybitty/tinybasic/TBEK.txt die IL (interpreter Language). Gegenüber dieser Version gibt es ein paar Unterschiede:
| Code | Beschreibung | Bemerkungen |
|---|---|---|
| 0A | CC, stop if cancel code | gibt es nicht in TBEK |
| 0B x | LB, push literal byte to TOS | in TBEK 09 |
| 0C x | LN, push addr (00xxh) to TOS | in TBEK 0A. Z8671: Es wird nur das niederwertige Byte genommen. Das höherwertige Byte wird 00 gesetzt. 1) |
| 0D | DS, duplicate stack top | in TBEK 0B |
| 0E | TS, pop Stack | in TEBEK 0C |
| 0F | TS, test sign; skip next IL if TOS is positive | in TBEK reserviert |
| 19 | reserviert, extern 1018h | in TBEK substract |
| 1E | reserviert, extern 101Bh | in TBEK reserviert |
| 1F | reserviert, extern 101Eh | in TBEK list program |
| 25 | PH, print hex number | in TBEK reserviert |
| 26 | HN, convert hex number | in TBEK reserviert |
| 28 | SN, put current line number on stack | in TBEK reserviert |
| 29 | FL, follow line; goto next line | in TBEK reserviert |
Z8671 TINY BASIC
reconstructed Volker Pohlers 10/2021, Germany, Neustadt i.H.
; THE IL CONTROL SECTION
0650 000: 62 X1 BR STRT ; ENTRY POINT DIRECT MODE
0651 001: 7A X2 BR GOTO ; ENTRY POINT NEXT STMT MODE
0652 002: 6F X3 BR XEC ; ENTRY POINT RUN MODE
0653 003: 24 BA STRT PC ":" ; PROMPT OUTPUT
0655 005: 27 GL ; GET LINE
0656 006: E1 BE X4 ; BRANCH IF NOT EMPTY
0657 007: 5B BR STRT ; TRY AGAIN IF NULL LINE
0658 008: D3 X4 BN GOTO ; TEST FOR LINE NUMBER
0659 009: 0F TS ; SKIP NEXT IF POSITIVE
065a 00A: 60 BR * ; ERROR STOP
065b 00B: 10 SB ; SAVE BASIC POINTER
065c 00C: 0D DS ; DUPLICATE TOP OF STACK
065d 00D: 16 GO ; GOTO LINE
065e 00E: 28 SN ; PUT FOUND LINE NUMBER ON STACK
065f 00F: 0E SP ; STACK POP
0660 010: 2A IL ; INSERT LINE INTO PROGRAM
0661 011: 51 BR STRT ; GO GET NEXT
0662 012: 10 XEC SB ; SAVE POINTERS FOR RUN WITH
0663 013: 11 RB ; CONCATENATED INPUT
0664 014: 0C 00 LN 00 ; PUT 0000 ON STACK
0666 016: 16 GO ; GOTO FIRST LINE
0667 017: 28 SN ; PUT FOUND LINE NUMBER ON STACK
0668 018: 0F TS ; SKIP NEXT IF POSITIVE
0669 019: 60 BR * ; ERROR STOP
066a 01A: 0E SP ; STACK POP
066b 01B: 2C X5 XQ ; EXECUTE PROGRAM
; STATEMENT EXECUTOR
066c 01C: 8F 47 CF GOTO BC IF "GO" ;
066f 01F: 9B 54 CF BC GOSB "TO" ; GOTO
0672 022: 35 1C S0 JS EXPR ; GET LINE NUMBER
0674 024: E0 S1 BE * ; ERR IF NOT END OF LINE
0675 025: 10 SB ; (DO THIS FOR STARTING)
0676 026: 11 RB ;
0677 027: 0F TS ; SKIP NEXT IF POSITIVE
0678 028: 60 BR * ; ERROR STOP
0679 029: 16 GO ; GO THERE
067a 02A: 50 BR X5 ;
067b 02B: 60 BR * ;
067c 02C: 9D 49 C6 IF BC LET "IF" ;
067f 02F: 34 E8 JS REL ;
0681 031: 84 54 48 45 CE BC S2 "THEN" ; OPTIONAL NOISEWORD
0686 036: 1C S2 CP ; COMPARE SKIPS NEXT IF TRUE
0687 037: 1D NX ; FALSE.
0688 038: C1 BN S4 ;
0689 039: 4A S3 BR S1 ;
068a 03A: 41 S4 BR GOTO ;
068b 03B: 89 53 55 C2 GOSB BC S5 "SUB" ; GOSUB
068f 03F: 34 FF JS EXPR ; GET DESTINATION.
0691 041: E0 BE * ; ERR IF NOT END OF LINE
0692 042: 28 SN ; PUT LINE NUMBER ON STACK
0693 043: 14 14 ;
0694 044: 54 BR S3 ;
0695 045: 80 C0 S5 BC * "@" ; GO@
0697 047: 34 F0 JS ARG3 ; GET 3 ARGUMENTS
0699 049: 7A BR S10 ; EXECUTE MACHINE CODE
069a 04A: 9B 4C 45 D4 LET BC S11 "LET" ;
069e 04E: A6 LET1 BV S8 ; VARIABLE NAME?
069f 04F: 80 BD S7 BC * "=" ;
06a1 051: 34 ED JS EXPR ; GO GET EXPRESSION
06a3 053: 13 SV ; STORE RESULT
06a4 054: 71 BR S11 ;
06a5 055: 84 DE S8 BC S9 "^" ; ADDR REFERENCE?
06a7 057: 35 25 JS FACT ; GET ADDR
06a9 059: 55 BR S7 ;
06aa 05A: 9A C0 S9 BC P0 "@" ; BYTE/REGISTER REFERENCE?
06ac 05C: 0C 81 LN 81 ; 0081 / =LO(LN81), HI(LN81) MUST BE 0
06ae 05E: 35 1E JS FACT ; GET DEST
06b0 060: 80 BD BC * "=" ;
06b2 062: 34 DC JS EXPR ; GET SRC
06b4 064: 2E S10 US ; USER SUBROUTINE. STACK: 0081 (ADDR), DEST, SRC
06b5 065: 0E SP ; STACK POP
06b6 066: E1 S11 BE S12 ; IF STATEMENT END,
06b7 067: 1D NX ; DONE
06b8 068: 83 BA S12 BC S14 ":" ; NEXT STATEMENT
06ba 06A: 3B B0 S13 J GOTO ; GET NEXT STATEMENT
06bc 06C: 82 A2 S14 BC PRNT """ ; PRINT STRING (WITHOUT KEYWORD)
06be 06E: 7B BR P8 ;
06bf 06F: 9D 50 52 49 4E D4 PRNT BC P9 "PRINT" ; PRINT
06c5 075: 83 BA P0 BC P1 ":" ; STATEMENT END?
06c7 077: 23 NL ; NEW LINE
06c8 078: 51 BR S13 ; NEXT STATEMENT
06c9 079: EE P1 BE P7 ; END OF LINE?
06ca 07A: 68 BR P5 ; YES
06cb 07B: 83 BB P2 BC P4 ";" ; NO CR
06cd 07D: E7 P3 BE P6 ; END OF LINE?
06ce 07E: 1D NX ; YES, NEXT BASIC STATEMENT
06cf 07F: 83 AC P4 BC P5 "," ; COMMA SPACING?
06d1 081: 22 PT ; PRINT TAB
06d2 082: 5A BR P3 ;
06d3 083: 23 P5 NL ; NEW LINE
06d4 084: 41 BR S11 ;
06d5 085: 82 BA P6 BC P7 ":" ; PRINT STMT END?
06d7 087: 42 BR S13 ;
06d8 088: 85 A2 P7 BC P10 """ ; STRING?
06da 08A: 21 P8 PQ ; PRINT QUOTE MARKS STRING
06db 08B: 60 BR * ; ERROR STOP
06dc 08C: 4E BR P2 ;
06dd 08D: 74 P9 BR RETN ; FORWARD BRANCH
06de 08E: 88 48 45 58 A8 P10 BC P12 "HEX(" ; HEX?
06e3 093: 35 16 JS F12 ; GET EXPR AND )
06e5 095: 25 PH ; PRINT HEX NUMBER
06e6 096: 44 P11 BR P2 ;
06e7 097: 34 A7 P12 JS EXPR ; PRINT EXPR
06e9 099: 17 NE ; NEGATE
06ea 09A: 0F TS ; SKIP NEXT IF POSITIVE
06eb 09B: 63 BR P13 ; NO, WAS POSITIVE NUMBER
06ec 09C: 24 AD PC "-" ; PRINT SIGN
06ee 09E: 61 BR P14 ;
06ef 09F: 17 P13 NE ; NEGATE (ORIG VALUE)
06f0 0A0: 20 P14 PN ; PRINT NUMBER
06f1 0A1: 54 BR P11 ;
06f2 0A2: 8C 52 45 D4 RETN BC STOP "RET" ; RETURN
06f6 0A6: 83 55 52 CE BC S15 "URN" ; OPTIONAL
06fa 0AA: E0 S15 BE * ; ERR IF NOT END OF LINE
06fb 0AB: 15 RS ; RESTORE SAVED LINE
06fc 0AC: 16 GO ;
06fd 0AD: 1D NX ; NEXT BASIC STATEMENT
06fe 0AE: 60 BR * ; ERROR STOP
06ff 0AF: 86 53 54 4F D0 STOP BC RUN "STOP" ;
0704 0B4: E0 BE S16 ; END OF LINE?
0705 0B5: 2D S16 WS ; YES, STOP
0706 0B6: 85 52 55 CE RUN BC NEW "RUN" ;
070a 0BA: 3B 56 J XEC ; RUN PROGRAM
070c 0BC: 85 4E 45 D7 NEW BC REM "NEW" ;
0710 0C0: E0 BE * ; ERR IF END OF LINE?
0711 0C1: 2B MT ; MARK BASIC PGM EMPTY
0712 0C2: 84 52 45 CD REM BC INPT "REM" ;
0716 0C6: 1D NX ; NEXT BASIC STATEMENT
0717 0C7: 9D 49 CE INPT BC LIST "IN" ;
071a 0CA: 86 50 55 D4 BC S17 "PUT" ; INPUT
071e 0CE: A0 BV * ; GET VARIABLE
071f 0CF: 10 SB ; SWAP POINTERS
0720 0D0: 63 BR I3 ;
0721 0D1: A0 S17 BV * ; IN COMMAND, FIRST VAR?
0722 0D2: 10 SB ; SWAP POINTERS
0723 0D3: E6 BE I4 ; END OF LINE?
0724 0D4: 24 3F A0 I3 PC "? " ; YES, TYPE PROMPT
0727 0D7: 27 GL ; READ INPUT LINE
0728 0D8: E1 BE I4 ; DID ANYTHING COME?
0729 0D9: 5A BR I3 ; NO, TRY AGAIN
072a 0DA: 81 AC I4 BC I5 "," ; NEXT PARAMETER (IN CMD)
072c 0DC: 34 62 I5 JS EXPR ; READ A NUMBER
072e 0DE: 13 SV ; STORE INTO VARIABLE
072f 0DF: 11 RB ; SWAP BACK
0730 0E0: 82 AC BC I6 "," ; ANOTHER?
0732 0E2: 4E BR S17 ; YES IF COMMA
0733 0E3: 3B 81 I6 J S11 ; OTHERWISE QUIT
0735 0E5: 8C 4C 49 53 D4 LIST BC L1 "LIST" ; LIST?
073a 0EA: 28 SN ; PUT LINE NUMBER ON STACK
073b 0EB: E8 BE L2 ; END OF LINE?
073c 0EC: 0C FF LN FF ; THEN PUT 00FF ON STACK
073e 0EE: 17 NE ; NEGATE -> FF01
073f 0EF: 0C 7F LN 7F ; PUT 007F ON STACK
0741 0F1: 67 BR L3 ; FF01007F -> 7F0100FF -> 7FFF0001
0742 0F2: 3B 5A L1 J LET1 ; ELSE LET STMT (WITHOUT KEYWORD)
0744 0F4: 34 46 L2 JS ARG2 ; GET TWO NUMBERS
0746 0F6: E0 BE * ; ERR IF NOT END OF LINE
0747 0F7: 03 SX 3 ; EXCHANGE THE TOP TWO aAbB > BAba
0748 0F8: 01 SX 1 ; NUMBERS ON THE STACK > BAab
0749 0F9: 03 L3 SX 3 ; > bAaB
074a 0FA: 02 SX 2 ; > bBaA
074b 0FB: 16 GO ; GO FIRST LINE IN AREA
074c 0FC: 28 SN ; PUT LINE NUMBER ON STACK
074d 0FD: 0E SP ;
074e 0FE: 23 L4 NL ; OUTPUT NEW LINE
074f 0FF: 0A 0A ; GOT CANCEL CODE?
0750 100: 74 BR L8 ; THEN CANCEL LIST
0751 101: 0D DS ; DUP STACK
0752 102: 0B 03 LB 03 ; 03 (>=)
0754 104: 28 SN ; PUT LINE NUMBER ON STACK
0755 105: 1C CP ; COMPARE. SKIP NEXT IF TRUE
0756 106: 6E BR L8 ; ELSE LIST END
0757 107: 28 SN ; PUT LINE NUMBER ON STACK
0758 108: 0F TS ; SKIP NEXT IF POSITIVE
0759 109: 6A BR L7 ; NEGATIVE LINE NUMBER FFFF -> END
075a 10A: 20 PN ; OUTPUT LINE NO
075b 10B: 24 A0 PC " " ; OUTPUT SPACE
075d 10D: 21 L5 PQ ; OUTPUT LINE TO 00 OR "
075e 10E: 63 BR L6 ; (PQ SKIPPES BRANCH IF ")
075f 10F: 24 A2 PC """ ; OUTPUT "
0761 111: 5B BR L5 ; AND CONTINUE
0762 112: 29 L6 FL ; SET NEXT LINE
0763 113: 4A BR L4 ; LOOP
0764 114: 0E L7 SP ; STACK POP
0765 115: 0E L8 SP ; RESTORE ORIG LINE NUMBER
0766 116: 16 GO ; GO ORIG LINE NUMBER
0767 117: 1D NX ;
0768 118: 1D NX ; ?? WHY ??
; SUBROUTINES
0769 119: 34 25 REL JS EXPR ; LEFT EXPRESSION
076b 11B: 8E BC BC R2 "<" ; CONVERT RELATION OPERATORS
076d 11D: 84 BD BC R0 "=" ; TO CODE BYTE ON STACK
076f 11F: 0B 06 LB 06 ; <= 6
0771 121: 76 BR R5 ;
0772 122: 84 BE R0 BC R1 ">" ;
0774 124: 0B 05 LB 05 ; <> 5
0776 126: 71 BR R5 ;
0777 127: 0B 04 R1 LB 04 ; < 4
0779 129: 6E BR R5 ;
077a 12A: 89 BE R2 BC R4 ">" ;
077c 12C: 84 BD BC R3 "=" ;
077e 12E: 0B 03 LB 03 ; >= 3
0780 130: 67 BR R5 ;
0781 131: 0B 01 R3 LB 01 ; > 1
0783 133: 64 BR R5 ;
0784 134: 80 BD R4 BC * "=" ;
0786 136: 0B 02 LB 02 ; = 2
0788 138: 67 R5 BR EXPR ; RIGHT EXPRESSION
0789 139: 34 01 ARG3 JS ARG2 ; GET 3 ARGUMENTS
078b 13B: 62 BR A1 ; 3RD OPT ARGUMENT
078c 13C: 34 02 ARG2 JS EXPR ; GET 2 ARGUMENTS
078e 13E: 97 AC A1 BC E4 "," ; OPTIONAL ARGUMENT
0790 140: 85 AD EXPR BC E0 "-" ; TRY FOR UNARY MINUS
0792 142: 34 14 JS TERM ; GET VALUE
0794 144: 17 NE ; NEGATE IT
0795 145: 64 BR E1 ; LOOK FOR MORE
0796 146: 81 AB E0 BC E4 "+" ; IGNORE UNARY PLUS
0798 148: 34 0E E4 JS TERM ; GET VALUE
079a 14A: 85 AB E1 BC E2 "+" ; TERMS SEPARATED BY PLUS
079c 14C: 34 0A JS TERM ; GET TERM
079e 14E: 18 E5 AD ; SUM TERM
079f 14F: 5A BR E1 ;
07a0 150: 86 AD E2 BC E3 "-" ; TERMS SEPARATED BY MINUS
07a2 152: 34 04 JS TERM ; GET TERM
07a4 154: 17 NE ; NEGATE
07a5 155: 58 BR E5 ; AND ADD
07a6 156: 0D E4 DS ; DUPLICATE NUMBER ON STACK
07a7 157: 2F E3 RT ;
07a8 158: 34 24 TERM JS FACT ; LEFT FACTOR
07aa 15A: 85 AA T0 BC T1 "*" ; FACTORS SEPARATED BY TIMES
07ac 15C: 34 20 JS FACT ; RIGHT FACTOR
07ae 15E: 1A MP ; MULTIPLY
07af 15F: 5A BR T0 ; NEXT FACTOR
07b0 160: 92 AF T1 BC T6 "/" ; FACTORS SEPARATED BY DIVIDE
07b2 162: 17 NE ; NEGATE DIVIDEND
07b3 163: 0F TS ; SKIP NEXT IF POSITIVE
07b4 164: 67 BR T3 ;
07b5 165: 34 17 JS FACT ; GET DIVISOR
07b7 167: 0F TS ; SKIP NEXT IF POSITIVE (-/+)
07b8 168: 71 BR T8 ;
07b9 169: 1B T2 DV ; DIVIDE (-/+, +/-)
07ba 16A: 17 NE ; NEGATE RESULT
07bb 16B: 4E BR T0 ; NEXT FACTOR
07bc 16C: 17 T3 NE ; NEGATE DIVIDEND BACK
07bd 16D: 34 0F T4 JS FACT ; GET DIVISOR
07bf 16F: 0F TS ; SKIP NEXT IF POSITIVE (+/+)
07c0 170: 65 BR T7 ;
07c1 171: 1B T5 DV ; DIVIDE (+/+, -/-)
07c2 172: 47 BR T0 ; NEXT FACTOR
07c3 173: 94 DC T6 BC F3 "\" ; UNSIGNED DIVISION?
07c5 175: 57 BR T4 ;
07c6 176: 17 T7 NE ; NEGATE
07c7 177: 0F TS ; SKIP NEXT IF POSITIVE
07c8 178: 63 BR T9 ;
07c9 179: 4F BR T2 ; (+/-)
07ca 17A: 17 T8 NE ; NEGATE BACK
07cb 17B: 0F TS ; SKIP NEXT IF POSITIVE
07cc 17C: 60 T9 BR * ; ERROR STOP
07cd 17D: 53 BR T5 ; (-/-)
07ce 17E: 8A 55 53 52 A8 FACT BC F4 "USR(" ; USR FUNCTION?
07d3 183: 33 B4 JS ARG3 ; GET ARGUMENTS
07d5 185: 80 A9 F1 BC * ")" ;
07d7 187: 2E F2 US ; USER SUBROUTINE. STACK USF-ADDR, 2 PARAM
07d8 188: 2F F3 RT ; RETURN
07d9 189: 89 41 4E 44 A8 F4 BC F5 "AND(" ; AND FUNCTION?
07de 18E: 0C 3C LN 3C ; 003C ADDRESS USF AND
07e0 190: 33 AA JS ARG2 ; GET ARGUMENTS
07e2 192: 52 BR F1 ;
07e3 193: 87 C0 F5 BC F6 "@" ; BYTE REFERENCE?
07e5 195: 0C 47 LN 47 ; 0047 ADDRESS USF FETCH
07e7 197: 33 E5 JS FACT ; GET BYTE
07e9 199: 0D DS ; DUPLICATE NUMBER ON STACK
07ea 19A: 4C BR F2 ;
07eb 19B: 84 DE F6 BC F7 "^" ; ADDR REFERENCE?
07ed 19D: 33 DF JS FACT ; GET ADDR
07ef 19F: 61 BR F8 ;
07f0 1A0: A2 F7 BV F9 ; VARIABLE?
07f1 1A1: 12 F8 FV ; FETCH VALUE
07f2 1A2: 2F RT ; RETURN
07f3 1A3: 83 A5 F9 BC F10 "%" ; HEX NUMBER?
07f5 1A5: 26 HN ; GET HEX NUMBER
07f6 1A6: 2F RT ; RETURN
07f7 1A7: C1 F10 BN F11 ; NUMBER?
07f8 1A8: 2F RT ; GOT IT.
07f9 1A9: 80 A8 F11 BC * "(" ; OTHERWISE MUST BE (EXPR)
07fb 1AB: 33 93 F12 JS EXPR ;
07fd 1AD: 80 A9 BC * ")" ;
07ff 1AF: 2F RT ; RETURN
Aufgrund der Beschränkungen bei LN (nur Werte 00xxh möglich) muss bei LIST ohne Parameter ein wenig gezaubert werden: Die Werte auf dem Stack werden durch Manipulation in kleinste und größtmögliche Zeilennummer gewandelt. Das entspricht dann dem Aufruf „LIST 1,32767“.
Die Division ist nur als vorzeichenlose 16-Bit-Division implementiert. Deshalb muss in der IL die Fallunterscheidung bzgl. Vorzeichen und Division durch 0 erfolgen.
Um Bytes zu sparen, wurden Unterprogramme verlegt und Codes zusammengeführt. Das erzeugt leider auch schwerer lesbaren Spaghetti-Code, aber nur so passt der gesamte Basic-Interpreter in 2kByte.