99FE Get address of the specified Array element
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
in the variable parameter block.]. Increment Y.
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 |
Or