
Submitted by Steve Fewell
Routine:ArrayElemAddr
Name: Get address of the specified Array element
Starting Address: &99FE
Entry criteria: &37 and &38 point to the start of the variable name.
Y = length of the variable name (Y points to the '(' character of the variable name.
&2C contains the return type of the variable.
Exit: (&2A, &2B) = the address of the required data element (&2A = LSB).
Description:
Increment the X and Y pointers to point to after the '(' character of the variable name.
Call routine &8085 to get the address of the variable block (stored in (&2A, &2B).
If the variable was not found (Zero flag set), then the variable hasn't been defined
so, generate 'Array' error.
Update the Text Pointer B offset value (&1B) with X.
Push the variable return type, the variable pointer LSB and variable pointer MSB to the stack.
Load the first byte from the variable pointer address (&2A, &2B). This value is
the pointer to position after the last dimension.
If the pointer to position after the last dimension is 4 (indicating 1 dimension) then goto &9A85 to
handle a 1 dimensional-array.
[&9A16] Handle Multiple Array dimensions
Clear the IWA and set byte &2D of the IWA to 1. [Bytes &2A and &2B is the requested element
value. Byte &2D is the pointer to the dimension subscript (max value)].
[&9A1D] Push the IWA value to the stack. This is the current subscript value & pointer to max subscript.
Call routine &96AF to evaluate the expression after the '(' character, and convert the
expression result to an Integer (if it was a Float). A Type Mismatch error is generated
if the result is a String. Now the IWA contains the requested element.
If the next character is not a comma then generate an Array error, as the declared Array
is a multi-dimensional array, but the array usage does not specify a second dimension, so
the array the text pointer is refering to does not exist!
Increment the Text pointer B offset (to point to after the comma character).
Set (&37,&38) to Variable block pointer & retrieve current subscript from stack to &39-&3C
Pop the Integer value stored to the stack to locations &39 to &3C.
Set Y = the current dimension offset in the variable block (the 4th byte of the Integer variable).
Store the Variable block pointer MSB in &38 (keeping the value on the stack).
Store the Variable block pointer LSB in &37 (keeping the value on the stack).
Check subscript value in the IWA & get next dimension's max subscript value
[&9A3A] Call routine &9AD3 to check the dimension subscript.
Update &2D with the value returned by the check subscript routine. This value now points
to the Dimensioned subscript value for the next dimension in the variable parameter block
[each 2-byte dimensioned subscript value is stored, one after the other, after the pointer to
the position after the last dimension (1-byte) value in the variable parameter block].
Load the second dimension's subscript (maximum element number) and store this 2-byte value in
locations &3F-&40.
Add the current subscript value (in the IWA) to the previous subscript value (&39-&3A)
and store the result in &2A-&2B, as the current subscript value now takes into account
any previous dimensions that have been specified.
The previous subscript value is the previous IWA value (before the current element subscript) was
obtained. This value is the total of all previous subscript values.
Call routine &9508 to multiply the current subscript value (&2A, &2B)
(or "the Upper limit", as it is the total element value from all earlier elements) by the
Lower Limit (&3F-&40). The lower limit is the maximum number of elements in the next dimension.
We need to multiply the current subscript by the lower limit (of the next element) in
order to take into account the relative position of the element we require within the
Array as a whole.
E.g. "DIM r(100,100):r(37, 50)=1" will return the element value for r as: 37 * 100 (= 3700) + 50 = 3750.
The 37 * 100 part is the value that is calculated by the section of the routine described above.
Load the pointer to the position after the last dimension of the array (the first byte of the
variable parameter block). Subtract the current dimension maximim subscript pointer (&2D) from
the pointer to the position after the last dimension.
If this value is >&eq;3 then there is more than 1 more dimension to process, so goto &9A1D
to handle the other dimensions.
One more element left to process - obtain details for last element
Push the IWA to the Stack, the IWA contains the current element location )&2A-&2B) and a
pointer to the next element details in the Variable Parameter block (&2D).
Call routine &96A7 to evaluate the next expression pointed to by Text pointer B.Convert the
[&ADAC] If the next character after the expression is not an ")" then generate a Missing ) error.
Convert the expression result to an Integer (if it was a Float). A Type Mismatch error is generated
if the result is a String. Now the IWA contains the requested element value of the last element.
Pop the Array variable parameter block pointer address from the Stack (and place it in &37-&38).
Pop the Integer value from the stack to locations &39-&3C (this is the current element location).
Set Y = the Dimension offset in the variable paremeter block (?&3C).
Call routine &9AD3 to check the dimension subscript.
Add the current subscript value (in the IWA) to the previous subscript value (&39-&3A)
and store the result in &2A-&2B, as the current subscript value now takes into account
any previous dimensions that have been specified. Now IWA bytes &2A-&2B contain
the required element position within the array.
Jump to &9A96 to calculate the address of the element's value.
[&9A85] Handle Single/Last dimension of array
Call routine &ADAC to evaluate the next expression pointed to by Text pointer B.Convert the
If the next character after the expression is not an ")" then generate a Missing ) error.
Convert the expression result to an Integer (if it was a Float). A Type Mismatch error is generated
if the result is a String. Now the IWA contains the requested element value.
Pop the Array variable parameter block pointer address from the Stack (and place it in &37-&38).
Set Y = 1 (the Dimension offset in the variable paremeter block).
Call routine &9AD3 to check the dimension subscript.
Continue to &9A96 to calculate the address of the element's value.
&9A96 Calculate the address of the element's value.
Pop the variable return type from the Stack.
If the variable return type = 5 (Floating-Point value) then Store the original element
position (&2A-&2B) in A and X and Multiply the element position by 4 and then
add the original element position to the result. This will have multiplied the value by 5 in total.
Each Floating-Point value is 5-bytes in length, so now bytes &2A-&2B contain the
address of the required value. Jump to &9ABC to finish off and tweek this value to the correct address.
If the variable return type is either Integer or String (both values are 4-bytes long), then
Multiply the element position by 4, so that bytes &2A-&2B now point to the required value.
[&9ABC] However, as the values are offset from the variable paremeter block, we need to add the
length of the array parameter block to the address we generated. This is because, depending on the
number of dimensions, the parameter block could be different lengths for each array - not a fixed length.
Add Y (Byte &2D of the IWA value), which is the offset of the last dimension in the parameter block,
to &2A, and increment byte &2B if an overflow occurred.
Now, to obtain the direct address of the specified value we need to add the value we calculated
in &2A-&2B to the base address of our variable paremeter block (&37-&38). This will
give us the exact memory start address for the first byte of our value.
Exit with &2A-&2B = The value address and &2C = value type.
[&9AD3] Check the dimension subscript
Load byte 2 of the Integer subscript value in the IWA & 'AND' the value with #&C0,
then 'ORA' the result with &2C and &2D. This checks the subscript value, if the value
is > 8392 or < 0 (&2C or &2D contain a value or one of the top 2 bits of &2B are set).
then generate a Subscript error, as the subscript value is too large or negative.
Compare the first byte (&2A) of the subscript value with the dimension subscript LSB value
Compare the second byte (&2B) of the subscript value with
the dimension subscript MSB value (maximum size of subscript, MSB).
If either of the compares exceed the maximum subscript value for that dimension then
generate Subscript error. Increment Y to point to the next byte of the variable block.
The subscript is ok, so return to the calling routine.
[&9508] Multiply specified upper dimension by the lower dinension
(&2A, &2B) return the specified upper dimension adjusted to take into account the lower elements.
Multiplies &2A, &2B by &3F-&40.
Firstly: zero X and Y.
[&950C] Divide copy of 2nd dimension's max subscript (&3F-&40) by 2 (shift right).
Next, if the lost bit (from the right-hand end) was 0 then multiply &2A,&2B by 2 and
if &3F and &40 are not zero then loop again [&950C].
Otherwise: clear carry flag, add &2A to Y & add &2B to X. If the addition
overflowed, then generate a Bad Dim error, as the element value is >&FFFF)
(this should only occur during the DIM statement, and not during access to
the array - as the DIM would have already generated the error).
Multiply &2A-&2B by 2.
If &3F-&40 is not zero then loop again [&950C].
Now, the second value (&3F-&40) is zero, and X & Y contain the result of
the first value (&2A-&2B) multiplied by the second value (&3F-&40).
Set &2A = Y and &2B = X and return with the updated element location.
Disassembly for the Get address of specified Array element routine
99FE
232
E8
INX
99FF
200
C8
INY
9A00
032 133 128
20 85 80
JSR &8085 Get pointer to variable block (array)
9A03
240 241
F0 F1
BEQ -15 --> &99F6 Array error
9A05
134 027
86 1B
STX &1B
9A07
,
165 044
A5 2C
LDA &2C
9A09
H
072
48
PHA
9A0A
*
165 042
A5 2A
LDA &2A
9A0C
H
072
48
PHA
9A0D
+
165 043
A5 2B
LDA &2B
9A0F
H
072
48
PHA
9A10
*
178 042
B2 2A
LDA (&2A)
9A12
201 004
C9 04
CMP#&04
9A14
o
144 111
90 6F
BCC 111 --> &9A85
9A16
032 232 171
20 E8 AB
JSR &ABE8 FALSE - Clear IWA
9A19
169 001
A9 01
LDA#&01
9A1B
-
133 045
85 2D
STA &2D
9A1D
&
032 038 188
20 26 BC
JSR &BC26 Push IWA to Stack
9A20
032 175 150
20 AF 96
JSR &96AF Get Integer result of expression
9A23
230 027
E6 1B
INC &1B
9A25
,
224 044
E0 2C
CPX#&2C
9A27
208 205
D0 CD
BNE -51 --> &99F6 Array error
9A29
9
162 057
A2 39
LDX#&39
9A2B
032 008 189
20 08 BD
JSR &BD08 Pop Integer from Stack to Zero page address
9A2E
<
164 060
A4 3C
LDY &3C
9A30
h
104
68
PLA
9A31
8
133 056
85 38
STA &38
9A33
h
104
68
PLA
9A34
7
133 055
85 37
STA &37
9A36
H
072
48
PHA
9A37
8
165 056
A5 38
LDA &38
9A39
H
072
48
PHA
9A3A
032 211 154
20 D3 9A
JSR &9AD3 Check Dimension Subscript
9A3D
-
132 045
84 2D
STY &2D
9A3F
7
177 055
B1 37
LDA (&37),Y
9A41
?
133 063
85 3F
STA &3F
9A43
200
C8
INY
9A44
7
177 055
B1 37
LDA (&37),Y
9A46
@
133 064
85 40
STA &40
9A48
*
165 042
A5 2A
LDA &2A
9A4A
e9
101 057
65 39
ADC &39
9A4C
*
133 042
85 2A
STA &2A
9A4E
+
165 043
A5 2B
LDA &2B
9A50
e:
101 058
65 3A
ADC &3A
9A52
+
133 043
85 2B
STA &2B
9A54
032 008 149
20 08 95
JSR &9508 Multiply upper dimension by the lower dimenson
9A57
8
056
38
SEC
9A58
7
178 055
B2 37
LDA (&37)
9A5A
-
229 045
E5 2D
SBC &2D
9A5C
201 003
C9 03
CMP#&03
9A5E
176 189
B0 BD
BCS -67 --> &9A1D
9A60
&
032 038 188
20 26 BC
JSR &BC26 Push IWA to Stack
9A63
032 167 150
20 A7 96
JSR &96A7 Extract Integer result of expression & check for ')'
9A66
h
104
68
PLA
9A67
8
133 056
85 38
STA &38
9A69
h
104
68
PLA
9A6A
7
133 055
85 37
STA &37
9A6C
9
162 057
A2 39
LDX#&39
9A6E
032 008 189
20 08 BD
JSR &BD08 Pop Integer from Stack to Zero page address
9A71
<
164 060
A4 3C
LDY &3C
9A73
032 211 154
20 D3 9A
JSR &9AD3 Check Dimension Subscript
9A76
024
18
CLC
9A77
9
165 057
A5 39
LDA &39
9A79
e*
101 042
65 2A
ADC &2A
9A7B
*
133 042
85 2A
STA &2A
9A7D
:
165 058
A5 3A
LDA &3A
9A7F
e+
101 043
65 2B
ADC &2B
9A81
+
133 043
85 2B
STA &2B
9A83
144 017
90 11
BCC 17 --> &9A96
9A85
032 172 173
20 AC AD
JSR &ADAC Evaluate expression & check for ')'
9A88
032 191 150
20 BF 96
JSR &96BF Check value & convert to Integer (if float)
9A8B
h
104
68
PLA
9A8C
8
133 056
85 38
STA &38
9A8E
h
104
68
PLA
9A8F
7
133 055
85 37
STA &37
9A91
160 001
A0 01
LDY#&01
9A93
032 211 154
20 D3 9A
JSR &9AD3 Check Dimension Subscript
9A96
h
104
68
PLA
9A97
,
133 044
85 2C
STA &2C
9A99
201 005
C9 05
CMP#&05
9A9B
208 023
D0 17
BNE 23 --> &9AB4
9A9D
+
166 043
A6 2B
LDX &2B
9A9F
*
165 042
A5 2A
LDA &2A
9AA1
*
006 042
06 2A
ASL &2A
9AA3
&+
038 043
26 2B
ROL &2B
9AA5
*
006 042
06 2A
ASL &2A
9AA7
&+
038 043
26 2B
ROL &2B
9AA9
e*
101 042
65 2A
ADC &2A
9AAB
*
133 042
85 2A
STA &2A
9AAD
138
8A
TXA
9AAE
e+
101 043
65 2B
ADC &2B
9AB0
+
133 043
85 2B
STA &2B
9AB2
128 008
80 08
BRA 8 --> &9ABC
9AB4
*
006 042
06 2A
ASL &2A
9AB6
&+
038 043
26 2B
ROL &2B
9AB8
*
006 042
06 2A
ASL &2A
9ABA
&+
038 043
26 2B
ROL &2B
9ABC
152
98
TYA
9ABD
e*
101 042
65 2A
ADC &2A
9ABF
*
133 042
85 2A
STA &2A
9AC1
144 003
90 03
BCC 3 --> &9AC6
9AC3
+
230 043
E6 2B
INC &2B
9AC5
024
18
CLC
9AC6
7
165 055
A5 37
LDA &37
9AC8
e*
101 042
65 2A
ADC &2A
9ACA
*
133 042
85 2A
STA &2A
9ACC
8
165 056
A5 38
LDA &38
9ACE
e+
101 043
65 2B
ADC &2B
9AD0
+
133 043
85 2B
STA &2B
9AD2
`
096
60
RTS
Disassembly for the Check Dimension Subscript routine
9AD3
+
165 043
A5 2B
LDA &2B
9AD5
)
041 192
29 C0
AND#&C0
9AD7
,
005 044
05 2C
ORA &2C
9AD9
-
005 045
05 2D
ORA &2D
9ADB
208 013
D0 0D
BNE 13 --> &9AEA Subscript error
9ADD
*
165 042
A5 2A
LDA &2A
9ADF
7
209 055
D1 37
CMP (&37),Y
9AE1
200
C8
INY
9AE2
+
165 043
A5 2B
LDA &2B
9AE4
7
241 055
F1 37
SBC (&37),Y
9AE6
176 002
B0 02
BCS 2 --> &9AEA Subscript error
9AE8
200
C8
INY
9AE9
`
096
60
RTS
Multiply specified upper dimension by the lower dimenson subscript (2-byte multiplication)
9503
?
162 063
A2 3F
LDX#&3F
9505
032 008 189
20 08 BD
JSR &BD08 Pop Integer from Stack to Zero page address
9508
162 000
A2 00
LDX#&00
950A
160 000
A0 00
LDY#&00
950C
F@
070 064
46 40
LSR &40
950E
f?
102 063
66 3F
ROR &3F
9510
144 011
90 0B
BCC 11 --> &951D
9512
024
18
CLC
9513
152
98
TYA
9514
e*
101 042
65 2A
ADC &2A
9516
168
A8
TAY
9517
138
8A
TXA
9518
e+
101 043
65 2B
ADC &2B
951A
170
AA
TAX
951B
176 015
B0 0F
BCS 15 --> &952C Bad Dim error
951D
*
006 042
06 2A
ASL &2A
951F
&+
038 043
26 2B
ROL &2B
9521
?
165 063
A5 3F
LDA &3F
9523
@
005 064
05 40
ORA &40
9525
208 229
D0 E5
BNE -27 --> &950C
9527
*
132 042
84 2A
STY &2A
9529
+
134 043
86 2B
STX &2B
952B
`
096
60
RTS