×   Main Menu ALL The 8BS News Manuals (New menu) Links Worth a Look Tools Disc and Basic Webring Site Map 8BS Guestbook Old Guest Book Me The Barnsley Rovers   
8-Bit Software

The BBC and Master Computer Public Domain Library

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

 


 Back to 8BS
Or