ROM Addresses: Getting BASIC to do What You Want: Difference between revisions

From Bitchin100 DocGarden
Jump to navigationJump to search
Line 55: Line 55:
<tr><td>008E</td><td>INPUT</td><td>84</td><td>0CA3</td></tr>
<tr><td>008E</td><td>INPUT</td><td>84</td><td>0CA3</td></tr>
<tr><td>0093</td><td>DIM</td><td>85</td><td>478B</td></tr>
<tr><td>0093</td><td>DIM</td><td>85</td><td>478B</td></tr>
<tr><td>0096</td><td>READ</td><td>86</td><td>OCD9</td></tr>
<tr><td>0096</td><td>READ</td><td>86</td><td>0CD9</td></tr>
<tr><td>009A</td><td>LET</td><td>87</td><td>09C3</td></tr>
<tr><td>009A</td><td>LET</td><td>87</td><td>09C3</td></tr>
<tr><td>009D</td><td>GOTO</td><td>88</td><td>0936</td></tr>
<tr><td>009D</td><td>GOTO</td><td>88</td><td>0936</td></tr>
<tr><td>00A1</td><td>RUN</td><td>89</td><td>090F</td></tr>
<tr><td>00A1</td><td>RUN</td><td>89</td><td>090F</td></tr>
<tr><td>00A4</td><td>IF</td><td>8A</td><td>OB1A</td></tr>
<tr><td>00A4</td><td>IF</td><td>8A</td><td>0B1A</td></tr>
<tr><td>00A6</td><td>RESTORE</td><td>8B</td><td>407F</td></tr>
<tr><td>00A6</td><td>RESTORE</td><td>8B</td><td>407F</td></tr>
<tr><td>00AD</td><td>GOSUB</td><td>8C</td><td>091E</td></tr>
<tr><td>00AD</td><td>GOSUB</td><td>8C</td><td>091E</td></tr>
Line 67: Line 67:
<tr><td>00BF</td><td>WIDTH</td><td>9D</td><td>1DC3</td></tr>
<tr><td>00BF</td><td>WIDTH</td><td>9D</td><td>1DC3</td></tr>
<tr><td>00C4</td><td>ELSE</td><td>91</td><td>09AO</td></tr>
<tr><td>00C4</td><td>ELSE</td><td>91</td><td>09AO</td></tr>
<tr><td>00C8</td><td>LINE</td><td>92</td><td>OC45</td></tr>
<tr><td>00C8</td><td>LINE</td><td>92</td><td>0C45</td></tr>
<tr><td>00CC</td><td>EDIT</td><td>93</td><td>5E51</td></tr>
<tr><td>00CC</td><td>EDIT</td><td>93</td><td>5E51</td></tr>
<tr><td>00D0</td><td>ERROR</td><td>94</td><td>OBOF</td></tr>
<tr><td>00D0</td><td>ERROR</td><td>94</td><td>0B0F</td></tr>
<tr><td>00D5</td><td>RESUME</td><td>95</td><td>OABO</td></tr>
<tr><td>00D5</td><td>RESUME</td><td>95</td><td>0AB0</td></tr>
<tr><td>00DB</td><td>OUT</td><td>96</td><td>11OC</td></tr>
<tr><td>00DB</td><td>OUT</td><td>96</td><td>110C</td></tr>
<tr><td>00DE</td><td>ON</td><td>97</td><td>OA2F</td></tr>    
<tr><td>00DE</td><td>ON</td><td>97</td><td>0A2F</td></tr>    
<tr><td>00E0</td><td>DSKO$</td><td>98</td><td>5071</td></tr>
<tr><td>00E0</td><td>DSKO$</td><td>98</td><td>5071</td></tr>
<tr><td>00E5</td><td>OPEN</td><td>99</td><td>4CCB</td></tr>
<tr><td>00E5</td><td>OPEN</td><td>99</td><td>4CCB</td></tr>
Line 81: Line 81:
<tr><td>00FC</td><td>SAVE</td><td>9E</td><td>4DCF</td></tr>
<tr><td>00FC</td><td>SAVE</td><td>9E</td><td>4DCF</td></tr>
<tr><td>0100</td><td>LFILES</td><td>9F</td><td>506F</td></tr>
<tr><td>0100</td><td>LFILES</td><td>9F</td><td>506F</td></tr>
<tr><td>0106</td><td>LPRINT</td><td>AO</td><td>OB4E</td></tr>
<tr><td>0106</td><td>LPRINT</td><td>A0</td><td>0B4E</td></tr>
<tr><td>010C</td><td>DEF</td><td>A1</td><td>0872</td></tr>
<tr><td>010C</td><td>DEF</td><td>A1</td><td>0872</td></tr>
<tr><td>010F</td><td>POKE</td><td>A2</td><td>128B</td></tr>
<tr><td>010F</td><td>POKE</td><td>A2</td><td>128B</td></tr>
Line 97: Line 97:
<tr><td>0145</td><td>MDM</td><td>AE</td><td>1A9E</td></tr>
<tr><td>0145</td><td>MDM</td><td>AE</td><td>1A9E</td></tr>
<tr><td>0148</td><td>KEY</td><td>AF</td><td>1BB8</td></tr>
<tr><td>0148</td><td>KEY</td><td>AF</td><td>1BB8</td></tr>
<tr><td>014B</td><td>CLS</td><td>BO</td><td>4231</td></tr>
<tr><td>014B</td><td>CLS</td><td>B0</td><td>4231</td></tr>
<tr><td>014E</td><td>BEEP</td><td>B1</td><td>4229</td></tr>
<tr><td>014E</td><td>BEEP</td><td>B1</td><td>4229</td></tr>
<tr><td>0152</td><td>SOUND</td><td>B2</td><td>1DC5</td></tr>
<tr><td>0152</td><td>SOUND</td><td>B2</td><td>1DC5</td></tr>
Line 104: Line 104:
<tr><td>0160</td><td>PRESET</td><td>B5</td><td>1C66</td></tr>
<tr><td>0160</td><td>PRESET</td><td>B5</td><td>1C66</td></tr>
<tr><td>0166</td><td>MOTOR</td><td>B6</td><td>1DEC</td></tr>
<tr><td>0166</td><td>MOTOR</td><td>B6</td><td>1DEC</td></tr>
<tr><td>016B</td><td>MAX</td><td>B7</td><td>7FOB 19DB</td></tr>
<tr><td>016B</td><td>MAX</td><td>B7</td><td>7F0B 19DB</td></tr>
<tr><td>016E</td><td>POWER</td><td>B8</td><td>1419</td></tr>
<tr><td>016E</td><td>POWER</td><td>B8</td><td>1419</td></tr>
<tr><td>0173</td><td>CALL</td><td>B9</td><td>1DFA</td></tr>
<tr><td>0173</td><td>CALL</td><td>B9</td><td>1DFA</td></tr>
Line 113: Line 113:
<tr><td>0186</td><td>SCREEN</td><td>BE</td><td>1E22</td></tr>
<tr><td>0186</td><td>SCREEN</td><td>BE</td><td>1E22</td></tr>
<tr><td>018C</td><td>NEW</td><td>BF</td><td>20FE</td></tr>
<tr><td>018C</td><td>NEW</td><td>BF</td><td>20FE</td></tr>
<tr><td>018F</td><td>TAB(</td><td>CO</td><td>OC01</td></tr>
<tr><td>018F</td><td>TAB(</td><td>C0</td><td>0C01</td></tr>
<tr><td>0193</td><td>TO</td><td>C1</td><td>076B</td></tr>
<tr><td>0193</td><td>TO</td><td>C1</td><td>076B</td></tr>
<tr><td>0195</td><td>USING</td><td>C2</td><td>4991</td></tr>
<tr><td>0195</td><td>USING</td><td>C2</td><td>4991</td></tr>
<tr><td>D19A</td><td>VARPTR</td><td>C3</td><td>OF7E</td></tr>
<tr><td>D19A</td><td>VARPTR</td><td>C3</td><td>0F7E</td></tr>
<tr><td>01A0</td><td>ERL</td><td>C4</td><td>OF56</td></tr>
<tr><td>01A0</td><td>ERL</td><td>C4</td><td>0F56</td></tr>
<tr><td>01A3</td><td>ERR</td><td>C5</td><td>OF47</td></tr>
<tr><td>01A3</td><td>ERR</td><td>C5</td><td>0F47</td></tr>
<tr><td>01A6</td><td>STRING$</td><td>C6</td><td>296D</td></tr>
<tr><td>01A6</td><td>STRING$</td><td>C6</td><td>296D</td></tr>
<tr><td>01AD</td><td>INSTR</td><td>C7</td><td>2A37</td></tr>
<tr><td>01AD</td><td>INSTR</td><td>C7</td><td>2A37</td></tr>
Line 126: Line 126:
<tr><td>01C3</td><td>OFF</td><td>C8</td><td>various</td></tr>
<tr><td>01C3</td><td>OFF</td><td>C8</td><td>various</td></tr>
<tr><td>01C6</td><td>HIMEM</td><td>CC</td><td>1DB9</td></tr>
<tr><td>01C6</td><td>HIMEM</td><td>CC</td><td>1DB9</td></tr>
<tr><td>01CB</td><td>THEN</td><td>CD</td><td>OB2A</td></tr>
<tr><td>01CB</td><td>THEN</td><td>CD</td><td>0B2A</td></tr>
<tr><td>01CF</td><td>NOT</td><td>CE</td><td>1054</td></tr>
<tr><td>01CF</td><td>NOT</td><td>CE</td><td>1054</td></tr>
<tr><td>01D2</td><td>STEP</td><td>CF</td><td>O783</td></tr>
<tr><td>01D2</td><td>STEP</td><td>CF</td><td>0783</td></tr>
<tr><td>0106</td><td>+</td><td>D0</td></tr>
<tr><td>0106</td><td>+</td><td>D0</td><td>See table 2</td></tr>
<tr><td>01D7</td><td>-</td><td>D1</td></tr>
<tr><td>01D7</td><td>-</td><td>D1</td><td>See table 2</td></tr>
<tr><td>01D8</td><td>*</td><td>D2</td></tr>
<tr><td>01D8</td><td>*</td><td>D2</td><td>See table 2</td></tr>
<tr><td>01D9</td><td>/</td><td>D3</td></tr>
<tr><td>01D9</td><td>/</td><td>D3</td><td>See table 2</td></tr>
<tr><td>010A</td><td>\</td><td>D4</td></tr>
<tr><td>010A</td><td>\</td><td>D4</td><td>See table 2</td></tr>
<tr><td>01DB</td><td>AND</td><td>D5</td><td>1097</td></tr>
<tr><td>01DB</td><td>AND</td><td>D5</td><td>1097</td></tr>
<tr><td>01DE</td><td>OR</td><td>06</td><td>108C</td></tr>
<tr><td>01DE</td><td>OR</td><td>06</td><td>108C</td></tr>
Line 141: Line 141:
<tr><td>01E9</td><td>MOD</td><td>DA</td><td>37DF</td></tr>
<tr><td>01E9</td><td>MOD</td><td>DA</td><td>37DF</td></tr>
<tr><td>01EC</td><td>\</td><td>DB</td><td>377E</td></tr>
<tr><td>01EC</td><td>\</td><td>DB</td><td>377E</td></tr>
<tr><td>01ED</td><td>&gt;</td><td>DC</td><td>OE29</td></tr>
<tr><td>01ED</td><td>&gt;</td><td>DC</td><td>0E29</td></tr>
<tr><td>01EE</td><td>=</td><td>DD</td><td>OE29</td></tr>
<tr><td>01EE</td><td>=</td><td>DD</td><td>0E29</td></tr>
<tr><td>01EF</td><td><</td><td>DE</td><td>OE29</td></tr>
<tr><td>01EF</td><td><</td><td>DE</td><td>0E29</td></tr>
<tr><td>01F0</td><td>SGN</td><td>DF</td><td>3407</td></tr>
<tr><td>01F0</td><td>SGN</td><td>DF</td><td>3407</td></tr>
<tr><td>01F3</td><td>INT</td><td>E0</td><td>3654</td></tr>
<tr><td>01F3</td><td>INT</td><td>E0</td><td>3654</td></tr>
Line 176: Line 176:
<tr><td>0256</td><td>RIGHT$</td><td>FD</td><td>29DC</td></tr>
<tr><td>0256</td><td>RIGHT$</td><td>FD</td><td>29DC</td></tr>
<tr><td>025C</td><td>MID$</td><td>FE</td><td>2AC2 29E6</td></tr>
<tr><td>025C</td><td>MID$</td><td>FE</td><td>2AC2 29E6</td></tr>
<tr><td>0260</td><td>'</td><td>FF</td><td>OA90</td></tr>    
<tr><td>0260</td><td>'</td><td>FF</td><td>0A90</td></tr>    
</table>
</table>
   
   

Revision as of 09:22, 23 January 2009

How does BASIC do what you tell it to do? Clues to the language's subservience lie in ROM.

By JAKE COMMANDER
Portable l00 September 1983, pg. 24

How on earth does Basic know what to do? All those state­ments, commands, and functions, yet the interpreter untiringly plods through your code always knowing what's required next. Just how does it do it?

Well, if the answer were simple, everybody would be writing BASIC interpreters and putting Microsoft out of business. But it is possible to follow at least some of the pathways Basic uses to perform its duties.

Most addresses of the ROM routines which comprise BASIC are held in two tables. These can be unraveled to give a list of routines used to perform various tasks.

Jump Addresses

One table contains jump addresses for the commands (or verbs, as it were) which will always be the first thing the interpreter picks up from a statement. The whole repertoire of such commands is catered for the table located at 0262 hex.

BASIC gets the appropriate jump address by using the token number for the command it's about to execute. All tokens are numbers from 128 to 255; therefore subtracting 128 gives numbers from zero to 127. As each jump address in the table is two bytes long, the token (minus 128) is multiplied by two to give an offset into the table. This points straight at the address which is needed. The two-byte address is picked up and jumped to ? and we're now executing a BASIC command in pure machine code.

What happens next depends entirely on the machine code for the command itself. Various syntaxes are allowed for some commands but not for others. For instance, the print command would allow an expression such as TAB(22);l/3, so would an LPRINT. But a LET would have none of that. LET X = TAB(22); 1/3 would have you on the carpet in no time.

Also various combinations of tokens can do different things. The comparison operators, for example, can be used pretty much interchangeably. These operators, >? <> = < , etc are all OK syntactically. This versatility means a table for such a wide set of possibilities is nigh impossible.

Second Table

However, there is a second table at location 004E in the ROM. This contains many addresses used in the evaluation of Basic math functions and expressions. These are extracted and jumped to in a similar fashion to the first table.

Any BASIC word excluded from either of these tables is handled separately by the interpreter according to its particular use. However, out of a possible 128 tokens, these two tables give us a mechanism by which we can follow the machine-code execution of many of them. It is the combination of these routines and the syntax checking required to logically execute them that makes up an interpreter.

The following list has been compiled from the two tables I've described and a disassembly of other parts of the ROM. It shows the entry points for all important BASIC statements and functions. Certain functions can have more than one possible syntactic use and the list does not cover all such uses. (An example is the statement OFF, which can be SOUND OFF or MOTOR OFF etc.) The list is in four columns. The first is the address in ROM where the BASIC word occurs in the vocabu­lary table. The second entry is the word itself. Third is the token assigned to that word when it is encoded by the BASIC interpreter.

Fourth Column

The fourth column contains the address the interpreter jumps to to execute the token representing the statement or function desired. Once again, some statements can have more than one use such as MID$(LH$)=RH$, and LH$=MID$(RH$). In these cases, two addresses are given: one for use on the left hand side of the equals sign and one for the right hand side of the sign.

Perhaps unsurprisingly, things get a little more complicated with the mathematical functions in BASIC. It's not simply a matter of taking an address for, say, a multiply routine and then jumping to it. The BASIC interpreter has to know the numeric type of operator it has to work on. For instance, with the addition operator, BASIC has four choices:

  1. Signed integer
  2. Single precision
  3. Double precision
  4. String

None of the other binary operators allow string manipulation, so they're limited to the numeric variable types only.

The addresses of these binary operators can be confirmed (if you need confirmation) from three short tables in ROM, one each for double precision, single precision, and integer numbers respectively.

The tables contain six addresses apiece for addition, subtraction, multiplication, division, exponentiation, and comparison. Rather than clutter the token-addresses table, these addresses are contained separately at the end.

In a following article, I'll be looking at ways to use some of these addresses in your own machine-code programs. For the more adventur­ous, an experiment will probably prove irresistible. Remember, though, in a RAM-file machine such as the Model 100, a lock-up may cost you all your files. Use caution.

Jake's ROM Addresses For BASIC Keywords

0080END80409F
0083FOR810726
0086NEXT824174
008ADATA83099E
008EINPUT840CA3
0093DIM85478B
0096READ860CD9
009ALET8709C3
009DGOTO880936
00A1RUN89090F
00A4IF8A0B1A
00A6RESTORE8B407F
00ADGOSUB8C091E
0082RETURN8D0966
00B8REM8E09AO
00BBSTOP8F409A
00BFWIDTH9D1DC3
00C4ELSE9109AO
00C8LINE920C45
00CCEDIT935E51
00D0ERROR940B0F
00D5RESUME950AB0
00DBOUT96110C
00DEON970A2F
00E0DSKO$985071
00E5OPEN994CCB
00E9CLOSE9A4E20
00EELOAD984D70
00F2MERGE9C4D71
00F7FILES9D1F3A
00FCSAVE9E4DCF
0100LFILES9F506F
0106LPRINTA00B4E
010CDEFA10872
010FPOKEA2128B
0113PRINTA30B56
0118CONTA440DA
011CLISTA51140
0120LLISTA6113B
0125CLEARA740F9
012ACLOADA82377
012FCSAVEA92280
0134TIME$AA19AB 1904
0139DATE$AB19BD 1924
013EDAY$AC19F1 1955
0142COMAD1A9E
0145MDMAE1A9E
0148KEYAF1BB8
014BCLSB04231
014EBEEPB14229
0152SOUNDB21DC5
0157LCOPYB31E5E
015CPSETB41C57
0160PRESETB51C66
0166MOTORB61DEC
016BMAXB77F0B 19DB
016EPOWERB81419
0173CALLB91DFA
0177MENUBA5797
017BIPLBB1A78
017ENAMEBC2037
0182KILLBD1F91
0186SCREENBE1E22
018CNEWBF20FE
018FTAB(C00C01
0193TOC1076B
0195USINGC24991
D19AVARPTRC30F7E
01A0ERLC40F56
01A3ERRC50F47
01A6STRING$C6296D
01ADINSTRC72A37
0182DSKI$C85073
01B7INKEY$C94BEA
01BDCSRLINCA1D90
01C3OFFC8various
01C6HIMEMCC1DB9
01CBTHENCD0B2A
01CFNOTCE1054
01D2STEPCF0783
0106+D0See table 2
01D7-D1See table 2
01D8*D2See table 2
01D9/D3See table 2
010A\D4See table 2
01DBANDD51097
01DEOR06108C
01E0XORD710A2
01E3EQVD810AD
01E6IMPD910B5
01E9MODDA37DF
01EC\DB377E
01ED>DC0E29
01EE=DD0E29
01EF<DE0E29
01F0SGNDF3407
01F3INTE03654
OIF6ABSE133F2
01F9FREE22B4C
01FCINPE31100
01FFLPOSE410C8
0203POSE510CE
0206SQRE6305A
0209RNDE7313E
020CLOGE82FCF
020FEXPE930A4
0212COSEA2EEF
0215SINEB2F09
0218TANEC2F58
021BATNED2F71
021EPEEKEE1284
0222EOFEF1889
0225LOGF0506D
0228LOFF1506B
022BCINTF23501
022FCSNGF3352A
0233CDBLF435BA
0237FIXF53645
023ALENF62943
023DSTR$F7273A
0241VALF82A07
0244ASCF9294F
0247CHR$FA295F
0248SPACE$FB298E
0251LEFT$FC29AB
0256RIGHT$FD29DC
025CMID$FE2AC2 29E6
0260'FF0A90
	+       -      *      /        >    Cmpr
D.P.   2B78    2B69   2CFF   2DC7   3D8E    34FA
S.P.   37F4    37FD   3803   380E   3D7F    3498
INT    3704    36F8   3725   OFOD   3DF7    34C2
String 28CC                                 270C