<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://bitchin100.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=124.157.105.102</id>
	<title>Bitchin100 DocGarden - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://bitchin100.com/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=124.157.105.102"/>
	<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Special:Contributions/124.157.105.102"/>
	<updated>2026-04-29T20:37:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://bitchin100.com/wiki/index.php?title=Running_BASIC_Code_from_OptROM&amp;diff=1618</id>
		<title>Running BASIC Code from OptROM</title>
		<link rel="alternate" type="text/html" href="https://bitchin100.com/wiki/index.php?title=Running_BASIC_Code_from_OptROM&amp;diff=1618"/>
		<updated>2009-05-02T04:58:48Z</updated>

		<summary type="html">&lt;p&gt;124.157.105.102: /* How the BASIC Interpreter Works */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a place for collecting thoughts on how to embed and run BASIC code in&lt;br /&gt;
an OptROM. Clearly, this is possible since UR2 implements Idea as a BASIC&lt;br /&gt;
program.&lt;br /&gt;
&lt;br /&gt;
== Short Conversation from M100SIG ==&lt;br /&gt;
&lt;br /&gt;
Fm: Stan Wong 70346,1267  To: Denny Thomas 76701,40&lt;br /&gt;
&lt;br /&gt;
Paul&#039;s on the right track about the Basic interpreter.  The Basic code never&lt;br /&gt;
moves but there is a ROM call that interprets each tokenized statement.  Other&lt;br /&gt;
ROM routines find the next statement to execute.  Its been a while but my&lt;br /&gt;
memory is sort of dim on the subject but each BASIC line in storage is&lt;br /&gt;
prefixed with the next line pointer and the line number. followed by the statement tokens followed by a&lt;br /&gt;
null.  Three nulls indicate the end of the program (end-of-statement null&lt;br /&gt;
followed by a line number of zero).&lt;br /&gt;
&lt;br /&gt;
A small program could switch to the OptROM, read a BASIC line (tokenized)&lt;br /&gt;
into RAM, switch back to system ROM, and then feed it to the interpreter loop.&lt;br /&gt;
There is no housekeeping since BASIC takes care of it.&lt;br /&gt;
The pointer to the next statement&lt;br /&gt;
needs to be fixed up also. Anyway, it&#039;s a fairly starightforward&lt;br /&gt;
proposition. If there is any interest I can dive back into my notes and&lt;br /&gt;
re-figure out what&#039;s what (in any case I got all my info from Robert&lt;br /&gt;
Covington&#039;s ROM maps in the DLs).&lt;br /&gt;
&lt;br /&gt;
== Thoughts from Ken Pettit ==&lt;br /&gt;
&lt;br /&gt;
I have looked at the BASIC interpreter quite a bit.  The main program execution loop (for M100) is at address 0804h.  The first few function calls perform things like checking for ON COM, ON TIME, CTRL-BREAK, etc.  The middle part executes the next instruction, and the last part steps forward to the next instruction / line #.  This routine would have to be rewritten to run in RAM and fetch BASIC lines from OptROM. Additionally, the routine below it would have to be rewritten too - it pushes the 0804h return address on the stack that most BASIC instructions use by doing a simple &amp;quot;RET&#039; .  This would have to push the address of the re-written RAM based loop.&lt;br /&gt;
&lt;br /&gt;
The problem areas will be in handling the ON TIME, ON COM, ON KEY, and STOP (CTRL-BREAK uses the STOP instruction).  From what I remember, these perform an absolute &amp;quot;JMP&amp;quot; into the ROM which then lead back to the 0804h loop and/or search for line numbered BASIC lines in RAM.&lt;br /&gt;
&lt;br /&gt;
Seems like GOTO and DATA/RESTORE/READ statements may be a problem too (BASIC commands that &amp;quot;lookup&amp;quot; line numbers).  You might find that several functions need to be re-implemented in the OptROM and ran from there, then switch to the main ROM to run the rest.&lt;br /&gt;
&lt;br /&gt;
== Callers of BASIC Inner Interpreter ==&lt;br /&gt;
&lt;br /&gt;
The following routines enter BASIC 0x0804 with a JMP (as opposed to returning to 0x0804 on the stack):&lt;br /&gt;
&lt;br /&gt;
CLOAD, CLOADM, CLEAR, NEXT, Input Routine, Various places in Menu.&lt;br /&gt;
&lt;br /&gt;
== How the BASIC Interpreter Works ==&lt;br /&gt;
&lt;br /&gt;
This disassembly of the Altair BASIC interpreter, though not the same code, should shed some light since it is so well commented (Philip Avery hipped me to this resource):&lt;br /&gt;
&lt;br /&gt;
[http://www.interact-sw.co.uk/altair/index2.html Altair BASIC Walk-Through]&lt;br /&gt;
&lt;br /&gt;
In particular, note the &amp;quot;Execution&amp;quot; section 1.9 which is relevant to this problem.&lt;br /&gt;
&lt;br /&gt;
== Running BASIC Programs: Excerpt from Hidden Powers (Chris Morgan) ==&lt;br /&gt;
&lt;br /&gt;
The next major area of memory contains the code that runs BASIC programs.&lt;br /&gt;
This is the heart of the BASIC interpreter. This section extends from&lt;br /&gt;
about 804h = 2052d to 871h = 2161d.&lt;br /&gt;
&lt;br /&gt;
This code has to check several conditions as it keeps running your program.&lt;br /&gt;
The first thing it checks is the communications line, by calling a&lt;br /&gt;
routine located at 6D6Dh = 28,013d (see Chapter 7).&lt;br /&gt;
Then it checks for an interrupt from the real-time clock by calling a &lt;br /&gt;
routine at 4028h = 16424d (see Chapter 5).&lt;br /&gt;
Next it checks for a break from the keyboard by calling a routine at&lt;br /&gt;
13F3h = 5107d (see Chapter 6).&lt;br /&gt;
&lt;br /&gt;
The BASIC interpreter then looks for a colon indicating the next statement&lt;br /&gt;
of a multiple statement on a BASIC command line. Finally, it checks for&lt;br /&gt;
the end of the program. It returns to the command loop via a jump to&lt;br /&gt;
428h = 1064d if the program has indeed ended.&lt;br /&gt;
&lt;br /&gt;
If the program has not ended, interpretation continues. The current line&lt;br /&gt;
number is stored in location F67Ah = 63,098d, and then the interpreter&lt;br /&gt;
dispatches to the routine to handle the keyword for the BASIC command&lt;br /&gt;
currently under consideration. It points to the address table for&lt;br /&gt;
BASIC commands. It is interesting to note that the last part of the&lt;br /&gt;
dispatching routine (locations 858h = 2136d) uses the same code&lt;br /&gt;
as is used by the RST 2 routine to check for numbers and skip over&lt;br /&gt;
spaces.&lt;br /&gt;
&lt;br /&gt;
== Commented M100 &amp;quot;Inner Interpreter&amp;quot; Code ==&lt;br /&gt;
&lt;br /&gt;
This commented disassembly is based on merging the Altair walkthrough&lt;br /&gt;
with the disassembly of the M100 BASIC ROM produced by VirtualT.&lt;br /&gt;
&lt;br /&gt;
In Forth circles, this code is called the &amp;quot;inner interpreter.&amp;quot; The &amp;quot;prompt&amp;quot;&lt;br /&gt;
that accepts BASIC commands is the outer interpreter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
; ======================================================&lt;br /&gt;
; &#039;ExecNext&#039; Execute BASIC program&lt;br /&gt;
; ======================================================&lt;br /&gt;
0804H  (CDH) CALL 6D6DH     ; Check RS232 queue for pending characters&lt;br /&gt;
0807H  (C4H) CNZ 4028H&lt;br /&gt;
080AH  (3AH) LDA F654H&lt;br /&gt;
080DH  (B7H) ORA A&lt;br /&gt;
080EH  (C4H) CNZ 402BH&lt;br /&gt;
0811H  (CDH) CALL 13F3H	    ; scan for break key&lt;br /&gt;
0814H  (22H) SHLD FB9BH     ; Most recent or currenly running line pointer&lt;br /&gt;
0817H  (EBH) XCHG&lt;br /&gt;
0818H  (21H) LXI H,0000H&lt;br /&gt;
081BH  (39H) DAD SP&lt;br /&gt;
081CH  (22H) SHLD FB9DH     ; SP used by BASIC to reinitialize the stack&lt;br /&gt;
081FH  (EBH) XCHG&lt;br /&gt;
&lt;br /&gt;
; If we have a &#039;:&#039; then that&#039;s a statement seperator (which allows multiple&lt;br /&gt;
; statements on the same line) so we jump to Exec to run it.&lt;br /&gt;
0820H  (7EH) MOV A,M&lt;br /&gt;
0821H  (FEH) CPI &#039;:&#039;&lt;br /&gt;
0823H  (CAH) JZ 083AH       ; Start executing BASIC program at HL&lt;br /&gt;
&lt;br /&gt;
; Well it wasn&#039;t a statement seperator, therefore it must be the null byte&lt;br /&gt;
; terminating the line otherwise it&#039;s a syntax error.&lt;br /&gt;
0826H  (B7H) ORA A&lt;br /&gt;
0827H  (C2H) JNZ 0446H      ; Generate Syntax error&lt;br /&gt;
&lt;br /&gt;
; The next two bytes should be the address of the next line.&lt;br /&gt;
; We can ignore this, since lines are stored consecutively,&lt;br /&gt;
; but must jump back to Main if we&#039;ve reached the end of the program&lt;br /&gt;
082AH  (23H) INX H&lt;br /&gt;
082BH  (7EH) MOV A,M&lt;br /&gt;
082CH  (23H) INX H&lt;br /&gt;
082DH  (B6H) ORA M&lt;br /&gt;
082EH  (CAH) JZ 0428H ; exit to interactive interpreter&lt;br /&gt;
&lt;br /&gt;
; Get the number of the following program line, store it in CURRENT_LINE and fall into Exec to run it.&lt;br /&gt;
0831H  (23H) INX H&lt;br /&gt;
0832H  (5EH) MOV E,M&lt;br /&gt;
0833H  (23H) INX H&lt;br /&gt;
0834H  (56H) MOV D,M&lt;br /&gt;
0835H  (EBH) XCHG&lt;br /&gt;
0836H  (22H) SHLD F67AH     ; Current executing line number&lt;br /&gt;
0839H  (EBH) XCHG&lt;br /&gt;
&lt;br /&gt;
; ======================================================&lt;br /&gt;
; &#039;Exec&#039; Start executing BASIC program at HL&lt;br /&gt;
; ======================================================&lt;br /&gt;
083AH  (D7H) RST 2          ; Get next non-white char from M&lt;br /&gt;
&lt;br /&gt;
; Stick address of ExecNext onto stack so we can return to it.&lt;br /&gt;
083BH  (11H) LXI D,0804H&lt;br /&gt;
083EH  (D5H) PUSH D&lt;br /&gt;
&lt;br /&gt;
; Return immediately if this is an empty statement&lt;br /&gt;
083FH  (C8H) RZ&lt;br /&gt;
&lt;br /&gt;
; ======================================================&lt;br /&gt;
; Execute instruction in A, HL points to args&lt;br /&gt;
; ======================================================&lt;br /&gt;
&lt;br /&gt;
; See if we lead with a keyword, ie first byte is &amp;gt;=0x80. If it isn&#039;t&lt;br /&gt;
; then it might be an implicit LET statement (ie where the LET has not&lt;br /&gt;
; been typed) and so we defer to the LET handler to deal with it.&lt;br /&gt;
0840H  (D6H) SUI 80H&lt;br /&gt;
0842H  (DAH) JC 09C3H       ; LET statement&lt;br /&gt;
&lt;br /&gt;
; If it&#039;s not a general keyword then that&#039;s a syntax error.&lt;br /&gt;
0845H  (FEH) CPI 40H&lt;br /&gt;
0847H  (D2H) JNC 10F4H	    ; Syntax Error&lt;br /&gt;
&lt;br /&gt;
; So we have a general keyword, so here we get the address of the&lt;br /&gt;
; handling function into HL, preserving the program ptr in DE.&lt;br /&gt;
084AH  (07H) RLC&lt;br /&gt;
084BH  (4FH) MOV C,A&lt;br /&gt;
084CH  (06H) MVI B,00H&lt;br /&gt;
084EH  (EBH) XCHG&lt;br /&gt;
084FH  (21H) LXI H,0262H    ; BASIC statement vector table for END to NEW&lt;br /&gt;
0852H  (09H) DAD B&lt;br /&gt;
&lt;br /&gt;
; Read the keyword handler function address into BC.&lt;br /&gt;
0853H  (4EH) MOV C,M&lt;br /&gt;
0854H  (23H) INX H&lt;br /&gt;
0855H  (46H) MOV B,M&lt;br /&gt;
&lt;br /&gt;
; Stick keyword handler function address on stack,&lt;br /&gt;
; restore program ptr to HL. Fall through to&lt;br /&gt;
; RST 10H w/ pre-increment of HL to get next character&lt;br /&gt;
; of the statement, and enter the keyword handler&lt;br /&gt;
; upon RET.&lt;br /&gt;
0856H  (C5H) PUSH B&lt;br /&gt;
0857H  (EBH) XCHG&lt;br /&gt;
&lt;br /&gt;
; ======================================================&lt;br /&gt;
; RST 10H routine with pre-increment of HL&lt;br /&gt;
; ======================================================&lt;br /&gt;
0858H  (23H) INX H&lt;br /&gt;
&lt;br /&gt;
; ======================================================&lt;br /&gt;
; RST 10H routine&lt;br /&gt;
; ======================================================&lt;br /&gt;
0859H  (7EH) MOV A,M&lt;br /&gt;
085AH  (FEH) CPI 3AH&lt;br /&gt;
085CH  (D0H) RNC&lt;br /&gt;
085DH  (FEH) CPI 20H&lt;br /&gt;
085FH  (CAH) JZ 0858H       ; RST 10H routine with pre-increment of HL&lt;br /&gt;
0862H  (FEH) CPI 0BH&lt;br /&gt;
0864H  (D2H) JNC 086CH&lt;br /&gt;
0867H  (FEH) CPI 09H&lt;br /&gt;
0869H  (D2H) JNC 0858H      ; RST 10H routine with pre-increment of HL&lt;br /&gt;
086CH  (FEH) CPI 30H&lt;br /&gt;
086EH  (3FH) CMC&lt;br /&gt;
086FH  (3CH) INR A&lt;br /&gt;
0870H  (3DH) DCR A&lt;br /&gt;
0871H  (C9H) RET&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Model T Developer Reference]]&lt;/div&gt;</summary>
		<author><name>124.157.105.102</name></author>
	</entry>
</feed>