8-Bit Software

The BBC and Master Computer Public Domain Library

Back to 8BS Or Back to Disassembly


Page Last Altered:

9909 Evaluate Variable Name and return address of value

Submitted by Steve Fewell

Routine:getvar
Name: Evaluate Variable Name and return address of value
Starting Address: &98F5/&9909
Entry criteria: A contains the next character. Text PTR B points to the rest of the
command line.
Exit: (&2A, &2B) point to the variable's value. &2C contains the value type.
A = 0 if error (variable not found); otherwise, A = &FF (?).
If A = 0 for error condition, then the carry flag has the following meanings:
Carry is clear if variable name was valid but variable doesn't exist (not declared).
Carry is set if no variable was specified (invalid variable name character/Syntax error).
If A is not 0 for variable found condition, then the carry flag has the following meanings:
Carry is clear if the variable contains a numerical value.
Carry is set if the variable is a string (non-numerical) value.

Description:

If called from &98F5 then set Text Pointer B to point to the current Text Pointer A location,
and skip any leading spaces in text pointer B.

Firstly this routine checks for a 'peek/poke' address operator ('?', '!', '$').
This needs to be done first, because if a peek operator is found then this provides
us with our address value without need to look further.
If a 'peek' operator is found, then exit with the address (to be peeked) placed in (&2A, &2B) and
&2C containing the return value type (String for '$', 1-byte Integer for '?' or 4-byte Integer for '!').
Note: After a peek/poke operator is evaluated, this routine is exited. This means that a peek/poke
address cannot be modified by an address modifier ('!', '?'), as address modifier operators can only
be used with numeric variables.
If the next character was less than '@', but it wasn't a '?', '!' or '$' operator then exit (routine &99A6)
with A = 0 and the carry set as the text is not a variable name.

Secondly, the routine checks for use of a resident integer variable (@% to Z%).
This is done second to ensure that resident integer variables are processed as fast
as possible, so that the quickest access times an be given.
If a resident Integer variable is found then multiply the first character of the variable
name by 4 (to obtain the page &4 starting address of the resident Integer variable).
and store the starting address in &2A. Store 4 in &2B (as this is the page where the variable
is located). Store 4 in &2C (as the return type is a 4-byte Integer value).
Check that the variable is not an Array by checking that the character after the '%' is an open
bracket. If it isn't then we have a resident Integer variable, so jump to the exit section (&9998)
of the evaluate variable routine.

Variable is not a peek/poke or a resident integer variable, so it is a normal variable
Begin by setting the default return value type and setting (&37, &38) to point to the
start of the variable name.

This is done as follows:
* Store #5 in &2C (the variable's return value type). This defaults the return value to Floating-Point
if a '%' or '$' is not found at the end of the variable name.
* Set A to point to the Text pointer B Offset.
* Set Y to point to the Text pointer B MSB.
* If the offset (A) is not 0, then add the Text pointer B LSB address value to the offset (A)
and increment Y (if page overflowed).
* If the offset (A) is zero then add the Text pointer B LSB address value.
* If the Text pointer B LSB value is zero also, then decrement Y (to point to the
previous page (the value in A is decremented to &FF in the next step!).
* Decrement the offset(A), to point to the first character of the variable name.
* Set zero page location &37 to the LSB address of the first character of the variable name.
* Set zero page location &38 to the MSB address of the first character of the variable name.

[9949] Check the first character of the variable name, as follows:
Load the first character of the variable name. Set Y to 1.
If the first character is between 'A' and 'Z' then increment the pointers (X and Y) to point to the
next character and test the next character [995B].
If the first character is between '_' and 'z' then increment the pointers (X and Y) to point to the
next character and test the next character [995B]. Note: this includes the characters '_', '£' and 'a'-'z'.
If the first character is between '0' and '9' then increment the pointers (X and Y) to point to the
next character and test the next character [995B]. Note: his will not be the case as '0' to '9' are already
rejected as being the first character in the variable name in routine &98C1.
If the first character is anything else then goto 9977 to indicate the end of the variable name has been reached.

[995B] Check the next character of the variable name, as follows:
Get the next character.
If the next character is between 'A' and 'Z' then increment the pointers (X and Y) to point to the
next character and test the next character [995B].
If the next character is between '_' and 'z' then increment the pointers (X and Y) to point to the
next character and test the next character [995B]. Note: this includes the characters '_', '£' and 'a'-'z'.
If the next character is between '0' and '9' then increment the pointers (X and Y) to point to the
next character and test the next character [995B].
If the next character is anything else then goto 9977 to indicate the end of the variable name has been reached.

[9977] The end of the variable name has been reached, so check the following:
If Y = 1 then no valid characters were found (the first character was invalid), so
exit [&99A6] with A = 0 and Carry set.
If the invalid character (last character) was '$' then goto &99DA to handle String variables.
String variables are handled as follows:
* Decrement &2C (the variable value type, from 5 to 4). This tricks the Get Array element
routine (&99FE), if it is called, to handle Integer values. As String variables have a 4-byte
parameter block, this works well as it tells the Get Array element address routine to work with 4-byte values.
* Increment the pointers (X and Y) (to point to the character after the '$')
* If the next character is an open bracket '(', then call &99FE to get the
address of the specified element.
Otherwise, call &8085 to get the address of the variable block for the specified variable &
store the text pointer B offset (X) back to &1B; & if the variable wasn't found (Zero flag set) then
exit via (&99AA --> A = 0 and Carry clear).
* Store #&81 in &2C - to specify that the return type is a string value.
* exit with the carry set (String value) and A = &81. Note with string variables we do not need to
check for address modifier operators '!' and '?' [as done by routine &9998 for numeric values]
as a String variable cannot contain an address value in which to modify!

Now String variables have been dealt with ('$'), so the following code deals only with
Integer and Floating-Point variables.
If the invalid character (last character) was '%' then decrement &2C (from 5 to 4)
as the return type is now an Integer, Increment the pointers (Y and X) and load the next character.

If the next character is an open bracket, '(', then call &99FE (the Get Array element
address routine). Otherwise: call &8085 to get the address of the variable block for the specified variable &
store the text pointer B offset (X) back to &1B; & if the variable wasn't found (Zero flag set) then
exit via (&99AA --> A = 0 and Carry clear).

Load the next character, and exit via routine &9998 to check for address modifier
operators ('!' and '?').

9998 Exit the evaluate variable routine:
Now we have the address for a numerical variable value, we need to check whether the variable
is followed by an address modifier operator ('!' or '?'). If it is then the numeric
value of the variable needs to be modified by the number of bytes specified after the
address modifier operator. I.e. the expression could be 'var!4', meaning that the
value of variable 'var' needs to be adjusted by 4, and the return value type is a 4-byte Integer.

If an address modifier is found then the appropriate routine is called (&99AE for '!' or &99B0 for '?').
Otherwise, clear the carry (as numerical value), store the pointer B offset back in &1B and exit with A=&FF
(as routine succeeded).


Disassembly for the Evaluate Variable Name and return address of value routine

98F5   165 011 A5 0B LDA &0B
98F7   133 025 85 19 STA &19
98F9   165 012 A5 0C LDA &0C
98FB   133 026 85 1A STA &1A
98FD   164 010 A4 0A LDY &0A
98FF   136 88 DEY
9900   200 C8 INY
9901   132 027 84 1B STY &1B
9903   177 025 B1 19 LDA (&19),Y
9905   201 032 C9 20 CMP#&20
9907   240 247 F0 F7 BEQ -9 --> &9900
9909 @ 201 064 C9 40 CMP#&40
990B   144 180 90 B4 BCC -76 --> &98C1 Check for '!', '?' or '$' address peek operators
990D [ 201 091 C9 5B CMP#&5B
990F   176 026 B0 1A BCS 26 --> &992B
9911   010 0A ASL A
9912   010 0A ASL A
9913 * 133 042 85 2A STA &2A
9915   200 C8 INY
9916   177 025 B1 19 LDA (&19),Y
9918 % 201 037 C9 25 CMP#&25
991A   208 015 D0 0F BNE 15 --> &992B
991C   169 004 A9 04 LDA#&04
991E + 133 043 85 2B STA &2B
9920   162 004 A2 04 LDX#&04
9922 , 134 044 86 2C STX &2C
9924   200 C8 INY
9925   177 025 B1 19 LDA (&19),Y
9927 ( 201 040 C9 28 CMP#&28
9929 m 208 109 D0 6D BNE 109 --> a href="#9998">&9998 Exit the Evaluate Variable routine
992B   162 005 A2 05 LDX#&05
992D , 134 044 86 2C STX &2C
992F   024 18 CLC
9930   164 026 A4 1A LDY &1A
9932   165 027 A5 1B LDA &1B
9934   170 AA TAX
9935   208 008 D0 08 BNE 8 --> &993F
9937 : 058 3A DEC A
9938 e 101 025 65 19 ADC &19
993A   176 009 B0 09 BCS 9 --> &9945
993C   136 88 DEY
993D   128 006 80 06 BRA 6 --> &9945
993F : 058 3A DEC A
9940 e 101 025 65 19 ADC &19
9942   144 001 90 01 BCC 1 --> &9945
9944   200 C8 INY
9945 7 133 055 85 37 STA &37
9947 8 132 056 84 38 STY &38
9949   160 001 A0 01 LDY#&01
994B 7 177 055 B1 37 LDA (&37),Y
994D A 201 065 C9 41 CMP#&41
994F   176 026 B0 1A BCS 26 --> &996B
9951 0 201 048 C9 30 CMP#&30
9953 " 144 034 90 22 BCC 34 --> &9977
9955 : 201 058 C9 3A CMP#&3A
9957   176 030 B0 1E BCS 30 --> &9977
9959   232 E8 INX
995A   200 C8 INY
995B 7 177 055 B1 37 LDA (&37),Y
995D A 201 065 C9 41 CMP#&41
995F   176 010 B0 0A BCS 10 --> &996B
9961 0 201 048 C9 30 CMP#&30
9963   144 018 90 12 BCC 18 --> &9977
9965 : 201 058 C9 3A CMP#&3A
9967   144 240 90 F0 BCC -16 --> &9959
9969   128 012 80 0C BRA 12 --> &9977
996B [ 201 091 C9 5B CMP#&5B
996D   144 234 90 EA BCC -22 --> &9959
996F _ 201 095 C9 5F CMP#&5F
9971   144 004 90 04 BCC 4 --> &9977
9973 { 201 123 C9 7B CMP#&7B
9975   144 226 90 E2 BCC -30 --> &9959
9977   192 001 C0 01 CPY#&01
9979 + 240 043 F0 2B BEQ 43 --> &99A6 Error: Set carry
997B $ 201 036 C9 24 CMP#&24
997D [ 240 091 F0 5B BEQ 91 --> &99DA Handle String variables
997F % 201 037 C9 25 CMP#&25
9981   208 006 D0 06 BNE 6 --> &9989
9983 , 198 044 C6 2C DEC &2C
9985   232 E8 INX
9986   200 C8 INY
9987 7 177 055 B1 37 LDA (&37),Y
9989 ( 201 040 C9 28 CMP#&28
998B H 240 072 F0 48 BEQ 72 --> &99D5 Handle Numeric Array
998D   032 133 128 20 85 80 JSR &8085 Get address of variable
9990   240 024 F0 18 BEQ 24 --> &99AA Error: Clear carry
9992   134 027 86 1B STX &1B
9994   164 027 A4 1B LDY &1B
9996   177 025 B1 19 LDA (&19),Y
9998 ! 201 033 C9 21 CMP#&21
999A   240 018 F0 12 BEQ 18 --> &99AE '!' address modifier operator
999C I? 073 063 49 3F EOR#&3F
999E   240 016 F0 10 BEQ 16 --> &99B0 '?' address modifier operator
99A0   024 18 CLC
99A1   132 027 84 1B STY &1B
99A3   169 255 A9 FF LDA#&FF
99A5 ` 096 60 RTS
99A6   169 000 A9 00 LDA#&00
99A8 8 056 38 SEC
99A9 ` 096 60 RTS
99AA   169 000 A9 00 LDA#&00
99AC   024 18 CLC
99AD ` 096 60 RTS

Handle numeric array

99D5   032 254 153 20 FE 99 JSR &99FE Get address of required Array element
99D8   128 186 80 BA BRA -70 --> &9994

Handle String variables

99DA , 198 044 C6 2C DEC &2C
99DC   232 E8 INX
99DD   200 C8 INY
99DE 7 177 055 B1 37 LDA (&37),Y
99E0 ( 201 040 C9 28 CMP#&28
99E2   240 013 F0 0D BEQ 13 --> &99F1
99E4   032 133 128 20 85 80 JSR &8085 Get address of variable
99E7   240 193 F0 C1 BEQ -63 --> &99AA Error: Clear carry
99E9   134 027 86 1B STX &1B
99EB   169 129 A9 81 LDA#&81
99ED , 133 044 85 2C STA &2C
99EF 8 056 38 SEC
99F0 ` 096 60 RTS
99F1   032 254 153 20 FE 99 JSR &99FE Get address of required Array element
99F4   128 245 80 F5 BRA -11 --> &99EB

Check for '!', '$' or '?' address peek operators

98C1 ! 201 033 C9 21 CMP#&21
98C3   240 012 F0 0C BEQ 12 --> &98D1 '!' address peek operator
98C5 $ 201 036 C9 24 CMP#&24
98C7   240 019 F0 13 BEQ 19 --> &98DC '$' address peek operator
98C9 I? 073 063 49 3F EOR#&3F
98CB   240 006 F0 06 BEQ 6 --> &98D3 '?' address peek operator
98CD   169 000 A9 00 LDA#&00
98CF 8 056 38 SEC
98D0 ` 096 60 RTS

 


 Back to 8BS
Or