8-Bit Software

The BBC and Master Computer Public Domain Library

Back to 8BS Or Back to Disassembly


Page Last Altered:

A7B5 SQR

Submitted by Steve Fewell

Description:

Call routine &96DA to get the value from text pointer B generating
Type Mismatch error is the value is a String, and converting any Integer value to a
Floating-Point value.
If the sign of the Floating-Point value is 0 (meaning FWA = 0.0) then exit with FWA unchanged
(as result = 0.0) and exit with A = &FF (as current value is Floating-Point).
If the sign of the Floating-Point value is negative (meaning FWA is negative) then
generate a '-ve root' error as SQR cannot evaluate negative values.

Divide the FWA exponent by 2 & add #&41 to obtain a 'guess value' (usually FWA value
divided by 2?). If overflow occurred (LSB bit was lost from Exponent) the divide the
FWA mantissa by 2 (to make up for the lost bit, and retain the required value).

Initialise the Result Mantissa value (&3D to &41 [FWB Mantissa]) to #&40.
Initialise the Test Mantissa value (&42 to &46) to #&40.
Start by subtracting #&40 from the FWA Mantissa (Byte 1).

Loop for each bit in the result value (&3D-&41):
During this loop X will specify which byte the current bit is in (i.e. #&FB specifies
the first byte (&3D) and #&FF specifies the last/5th byte (&41)).
Also, Y specifies the current bit number within the current byte.
For the first byte, only the lower 5 bits are tested (Y starts at #&10 meaning start with bit 4,
then test bit 3, and then bit 2, and then bit 1 and lastly bit 0)
[as each loop affects the value of the previous bit, the value of the first 6 bits of the
first byte of the result could be changed].
for all other bytes (&3E to &41), all bits are tested, MSB first.
Only 1 bit of the result is processed at a time.

For each bit (each loop iteration), the following processing is done:
*1) Copy the current Result value to the Test value (as only the current byte can change, then
    only the current byte is copied). Set the current bit position (the bit we are currently testing)
    in the Test Value (i.e. set the relevent bit to test). So: &42-&46 is an exact copy of the
    current result (&3D-&41) with the addition that the current bit is set (i.e. the "test bit").(br>
*2) Compare the FWA Mantissa with the Test value (byte by byte, stopping at the first difference).
    If the FWA Mantissa >&eq; Test value then subtract the test value from the
      FWA mantissa, and set the previous bit in the result (this works even if the previous
      bit is in the previous byte!). Update any change to the Test value (overwriting the previous
      'Result value + "test bit"' contents of the Temp value. If the previous byte was changed, then
      also update the current byte value to the test result (to set back the "test bit").
    If the FWA Mantissa < Test value then do nothing.
*3) Multiply the FWA Mantissa by 2.
*4) Loop again to test the next bit, or if we have reached the end of the last byte (&41), then we have finished.

When we have completed the loop, copy the FWB Mantissa (the result value) to the FWA Mantissa &
[&A854] normalise the value (if necessary). Round the FWA Mantissa value to 4 bytes (loosing the rounding byte)
and exit with A=&FF (indicating a Floating-Point result).

I am not exactly sure how this routine works, so if anyone else can provide a better
description or an example of the algorithum using decimal (base 10) values, then please do so.


Examples:


Example 1:
FWA = 9 (Exponent = &84, Mantissa = &90).
"Guess value" = 4.5 (Exponent = &83, Mantissa = &90).
FWB Mantissa = &40
&42-&46 = &40
Subtract &40 from FWA Mantissa (FWA => Exponent = &83, Mantissa = &50).

Current Byte = &3D (X = &FB), Current Bit = 4 (Y = &10)
Test value = &50 (&40 + &10 (bit 4)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA => Exponent = &83, Mantissa = &00.
Set previous Result bit; Result = &60 (&40 + &20 (previous bit position))
FWA = FWA * 2; FWA => Exponent = &83, Mantissa = &00.

Current Byte = &3D (X = &FB), Current Bit = 3 (Y = &08)
Test value = &68 (&60 + &08 (bit 3)).
FWA Mantissa is < Test Value, so do nothing.
FWA = FWA * 2; FWA => Exponent = &83, Mantissa = &00.

... From now onwards the FWA Mantissa value is always less than the test value, so we can stop
here as the result will not alter now. [Note: BASIC does not stop, it keeps going until all the
bits have been tested).
Copy FWB Mantissa to FWA Mantissa; FWA => Exponent = &83, Mantissa = &60.
Normalise FWA and exit with FWA => Exponent = &82, Mantissa = &C0 (i.e. 3.0) which is the SQR of 9.

Example 2:
FWA = 28.512 (Exponent = &85, Mantissa = &E418937500).
"Guess value" = 14.256 (Exponent = &84, Mantissa = &720C49BA80).
FWB Mantissa = &40
&42-&46 = &40
Subtract &40 from FWA Mantissa (FWA => Exponent = &84, Mantissa = &320C49BA80).

Current Byte = &3D (X = &FB), Current Bit = 4 (Y = &10)
Test value = &50 (&40 + &10 (bit 4)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &6418937500

Current Byte = &3D (X = &FB), Current Bit = 3 (Y = &08)
Test value = &48 (&40 + &08 (bit 3)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &1C18937500.
Set previous Result bit; Result = &50 (&40 + &10 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &383126EA00

Current Byte = &3D (X = &FB), Current Bit = 2 (Y = &04)
Test value = &54 (&50 + &04 (bit 2)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &70624DD400

Current Byte = &3D (X = &FB), Current Bit = 1 (Y = &02)
Test value = &52 (&50 + &02 (bit 1)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &1E624DD400.
Set previous Result bit; Result = &54 (&50 + &04 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &3CC49BA800

Current Byte = &3D (X = &FB), Current Bit = 0 (Y = &01)
Test value = &55 (&54 + &01 (bit 0)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &7989375000

Current Byte = &3E (X = &FC), Current Bit = 7 (Y = &80)
Test value = &5480 (&5400 + &80 (bit 7)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &2509375000.
Set previous Result bit; Result = &5500 (&5400 + &100 (previous bit position in previous byte))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &4A126EA000

Current Byte = &3E (X = &FC), Current Bit = 6 (Y = &40)
Test value = &5540 (&5500 + &40 (bit 6)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &9424DD4000

Current Byte = &3E (X = &FC), Current Bit = 5 (Y = &20)
Test value = &5520 (&5500 + &20 (bit 5)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &3F04DD4000.
Set previous Result bit; Result = &5540 (&5500 + &40 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &7E09BA8000

Current Byte = &3E (X = &FC), Current Bit = 4 (Y = &10)
Test value = &5550 (&5540 + &10 (bit 4)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &28B9BA8000.
Set previous Result bit; Result = &5560 (&5540 + &20 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &5173750000

Current Byte = &3E (X = &FC), Current Bit = 3 (Y = &08)
Test value = &5568 (&5560 + &08 (bit 3)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &A2E6EA0000

Current Byte = &3E (X = &FC), Current Bit = 2 (Y = &04)
Test value = &5564 (&5560 + &04 (bit 2)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &4D82EA0000.
Set previous Result bit; Result = &5568 (&5560 + &08 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &9B05D40000

Current Byte = &3E (X = &FC), Current Bit = 1 (Y = &02)
Test value = &556A (&5568 + &02 (bit 1)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &459BD40000.
Set previous Result bit; Result = &556C (&5568 + &04 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &8B37A80000

Current Byte = &3E (X = &FC), Current Bit = 0 (Y = &01)
Test value = &556D (&556C + &01 (bit 0)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &35CAA80000.
Set previous Result bit; Result = &556E (&556C + &02 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &6B95500000

Current Byte = &3F (X = &FD), Current Bit = 7 (Y = &80)
Test value = &556E80 (&556E00 + &80 (bit 7)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &1626D00000.
Set previous Result bit; Result = &556F00 (&556E00 + &100 (previous bit position (in previous byte)))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &2C4DA00000

Current Byte = &3F (X = &FD), Current Bit = 6 (Y = &40)
Test value = &556F40 (&556F00 + &40 (bit 6)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &589B400000

Current Byte = &3F (X = &FD), Current Bit = 5 (Y = &20)
Test value = &556F20 (&556F00 + &20 (bit 5)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &032C200000.
Set previous Result bit; Result = &556F40 (&556F00 + &40 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &0658400000

Current Byte = &3F (X = &FD), Current Bit = 4 (Y = &10)
Test value = &556F50 (&556F40 + &10 (bit 4)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &0CB0800000

Current Byte = &3F (X = &FD), Current Bit = 3 (Y = &08)
Test value = &556F48 (&556F40 + &08 (bit 3)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &1961000000

Current Byte = &3F (X = &FD), Current Bit = 2 (Y = &04)
Test value = &556F44 (&556F40 + &04 (bit 2)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &32C2000000

Current Byte = &3F (X = &FD), Current Bit = 1 (Y = &02)
Test value = &556F42 (&556F40 + &02 (bit 1)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &6584000000

Current Byte = &3F (X = &FD), Current Bit = 0 (Y = &01)
Test value = &556F41 (&556F40 + &01 (bit 0)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &1014BF0000.
Set previous Result bit; Result = &556F42 (&556F40 + &02 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &20297E0000

Current Byte = &40 (X = &FE), Current Bit = 7 (Y = &80)
Test value = &556F4280 (&556F4200 + &80 (bit 7)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &4052FC0000

Current Byte = &40 (X = &FE), Current Bit = 6 (Y = &40)
Test value = &556F4240 (&556F4200 + &40 (bit 6)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &80A5F80000

Current Byte = &40 (X = &FE), Current Bit = 5 (Y = &20)
Test value = &556F4220 (&556F4200 + &20 (bit 5)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &2B36B5E000.
Set previous Result bit; Result = &556F4240 (&556F4200 + &40 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &566D6BC000

Current Byte = &40 (X = &FE), Current Bit = 4 (Y = &10)
Test value = &556F4250 (&556F4240 + &10 (bit 4)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &00FE297000.
Set previous Result bit; Result = &556F4260 (&556F4240 + &20 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &01FC52E000

Current Byte = &40 (X = &FE), Current Bit = 3 (Y = &08)
Test value = &556F4268 (&556F4260 + &08 (bit 3)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &03F8A5C000

Current Byte = &40 (X = &FE), Current Bit = 2 (Y = &04)
Test value = &556F4264 (&556F4260 + &04 (bit 2)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &07F14B8000

Current Byte = &40 (X = &FE), Current Bit = 1 (Y = &02)
Test value = &556F4262 (&556F4260 + &02 (bit 1)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &0FE2970000

Current Byte = &40 (X = &FE), Current Bit = 0 (Y = &01)
Test value = &556F4261 (&556F4260 + &01 (bit 0)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &1FC52E0000

Current Byte = &41 (X = &FF), Current Bit = 7 (Y = &80)
Test value = &556F426080 (&556F426000 + &80 (bit 7)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &3F8A5C0000

Current Byte = &41 (X = &FF), Current Bit = 6 (Y = &40)
Test value = &556F426040 (&556F426000 + &40 (bit 6)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &7F14B80000

Current Byte = &41 (X = &FF), Current Bit = 5 (Y = &20)
Test value = &556F426020 (&556F426000 + &20 (bit 5)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &29A5759FE0.
Set previous Result bit; Result = &556F426040 (&556F426000 + &40 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &534AEB3FC0

Current Byte = &41 (X = &FF), Current Bit = 4 (Y = &10)
Test value = &556F426050 (&556F426040 + &10 (bit 4)).
FWA Mantissa is < Test Value, so nothing to update to Result
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &A695D67F80

Current Byte = &41 (X = &FF), Current Bit = 3 (Y = &08)
Test value = &556F426048 (&556F426040 + &08 (bit 3)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &5126941F38.
Set previous Result bit; Result = &556F426050 (&556F426040 + &10 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &A24D283E70

Current Byte = &41 (X = &FF), Current Bit = 2 (Y = &04)
Test value = &556F426054 (&556F426050 + &04 (bit 2)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &4CDDE5DE1C.
Set previous Result bit; Result = &556F426058 (&556F426050 + &08 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &99BBCBBC38

Current Byte = &41 (X = &FF), Current Bit = 1 (Y = &02)
Test value = &556F42605A (&556F426058 + &02 (bit 1)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &444C895BDE.
Set previous Result bit; Result = &556F42605C (&556F426058 + &04 (previous bit position))
FWA Mantissa = FWA Mantissa * 2; FWA Mantissa = &889912B7BC

Current Byte = &41 (X = &FF), Current Bit = 0 (Y = &01)
Test value = &556F42605D (&556F42605C + &01 (bit 0)).
FWA Mantissa is >&eq; Test Value, so subtract test value from FWA Mantissa
FWA Mantissa = &3329D0575F.
Set previous Result bit; Result = &556F42605E (&556F42605C + &02 (previous bit position))

FWA => (Exponent = &84, Mantissa = &556F42605E).
Normalise & Round (Round Mantissa to 4-bytes) FWA. FWA => (Exponent = &83, Mantissa = &AADE84C100).
FWA Value (in decimal) = 5.33966291 which is the SQR of 28.512.


Disassembly for the SQR routine

A7B5   032 218 150 20 DA 96 JSR &96DA Get and Check Float value
A7B8   032 242 163 20 F2 A3 JSR &A3F2 Floating-Point Sign
A7BB   240 245 F0 F5 BEQ -11 --> &A7B2 [LDA#&FF : RTS]
A7BD 0 048 156 30 9C BMI -100 --> &A75B -ve root error
A7BF 0 165 048 A5 30 LDA &30
A7C1 J 074 4A LSR A
A7C2   008 08 PHP
A7C3 iA 105 065 69 41 ADC#&41
A7C5 0 133 048 85 30 STA &30
A7C7 ( 040 28 PLP
A7C8   144 010 90 0A BCC 10 --> &A7D4
A7CA F1 070 049 46 31 LSR &31
A7CC f2 102 050 66 32 ROR &32
A7CE f3 102 051 66 33 ROR &33
A7D0 f4 102 052 66 34 ROR &34
A7D2 f5 102 053 66 35 ROR &35
A7D4 p 032 112 165 20 70 A5 JSR &A570 Clear FWB
A7D7 dC 100 067 64 43 STZ &43
A7D9 dD 100 068 64 44 STZ &44
A7DB dE 100 069 64 45 STZ &45
A7DD dF 100 070 64 46 STZ &46
A7DF @ 169 064 A9 40 LDA#&40
A7E1 = 133 061 85 3D STA &3D
A7E3 B 133 066 85 42 STA &42
A7E5   162 251 A2 FB LDX#&FB
A7E7   160 016 A0 10 LDY#&10
A7E9 8 056 38 SEC
A7EA 1 165 049 A5 31 LDA &31
A7EC @ 233 064 E9 40 SBC#&40
A7EE 1 133 049 85 31 STA &31
A7F0   152 98 TYA
A7F1 UB 085 066 55 42 EOR &42,X
A7F3 G 149 071 95 47 STA &47,X
A7F5 1 165 049 A5 31 LDA &31
A7F7 B 197 066 C5 42 CMP &42
A7F9   208 013 D0 0D BNE 13 --> &A808
A7FB   218 DA PHX
A7FC   162 252 A2 FC LDX#&FC
A7FE 6 181 054 B5 36 LDA &36,X
A800 G 213 071 D5 47 CMP &47,X
A802   208 003 D0 03 BNE 3 --> &A807
A804   232 E8 INX
A805   208 247 D0 F7 BNE -9 --> &A7FE
A807   250 FA PLX
A808 ) 144 041 90 29 BCC 41 --> &A833
A80A 5 165 053 A5 35 LDA &35
A80C F 229 070 E5 46 SBC &46
A80E 5 133 053 85 35 STA &35
A810 4 165 052 A5 34 LDA &34
A812 E 229 069 E5 45 SBC &45
A814 4 133 052 85 34 STA &34
A816 3 165 051 A5 33 LDA &33
A818 D 229 068 E5 44 SBC &44
A81A 3 133 051 85 33 STA &33
A81C 2 165 050 A5 32 LDA &32
A81E C 229 067 E5 43 SBC &43
A820 2 133 050 85 32 STA &32
A822 1 165 049 A5 31 LDA &31
A824 B 229 066 E5 42 SBC &42
A826 1 133 049 85 31 STA &31
A828   152 98 TYA
A829   010 0A ASL A
A82A   144 011 90 0B BCC 11 --> &A837
A82C   026 1A INC A
A82D UA 085 065 55 41 EOR &41,X
A82F A 149 065 95 41 STA &41,X
A831 F 149 070 95 46 STA &46,X
A833 B 181 066 B5 42 LDA &42,X
A835   128 004 80 04 BRA 4 --> &A83B
A837 UB 085 066 55 42 EOR &42,X
A839 B 149 066 95 42 STA &42,X
A83B G 149 071 95 47 STA &47,X
A83D 5 006 053 06 35 ASL &35
A83F &4 038 052 26 34 ROL &34
A841 &3 038 051 26 33 ROL &33
A843 &2 038 050 26 32 ROL &32
A845 &1 038 049 26 31 ROL &31
A847   152 98 TYA
A848 J 074 4A LSR A
A849   168 A8 TAY
A84A   144 164 90 A4 BCC -92 --> &A7F0
A84C   160 128 A0 80 LDY#&80
A84E   232 E8 INX
A84F   208 159 D0 9F BNE -97 --> &A7F0
A851 S 032 083 131 20 53 83 JSR &8353 Copy FWB Mantissa to FWA Mantissa
A854 1 165 049 A5 31 LDA &31
A856 0 048 003 30 03 BMI 3 --> &A85B
A858   032 251 129 20 FB 81 JSR &81FB Normalise FWA
A85B   032 149 166 20 95 A6 JSR &A695 Round FWA Mantissa to 4 bytes
A85E   169 255 A9 FF LDA#&FF
A860 ` 096 60 RTS

 


 Back to 8BS
Or