Submitted by Steve Fewell
Routine: adiv10
Name: Float Divide 10
Starting Address: &A478
Entry criteria: The FWA contains the
Floating-point number to divide by 10.
Exit: FWA contains the result of [FWA / 10]
Description:
As BASIC handles input and output of base-10 numbers (decimal), but does it's
calculations in base-2 (binary), is needs fast routines to multiple and divide
by a factor of 10.
The standard Floating-point '/' and '*' routines could be used for this purpose, and BASIC could provide 10 as the second value in the division and multiplication routines. But this wouldn't be a very satisfactory method - as BASIC requires these frequent calculations to be performed as fast as possible.
The problem with the standard Floating-point '/' and '*' routines is that they require loops (iteration), in order to perform the required action on the two variable numbers. The loops will probably be iterated for different numbers of times depending on the values of both of the variable numbers. BASIC requires multiplication and division by 10 as part of its internal routines, and as such cannot accept an undetermined number of iterations until a result is found.
Hence, the BASIC ROM contains separate routines to multiply and divide floating-point numbers by 10. These routines contain no loops (iteration), and run through a set sequence of commands each time (with little variation).
This page contains the complicated code that BASIC performs in order to achieve a Division by 10. The Multiply by 10 routine can be found here.
The routine executes the following steps:
a) 4 is subtracted from the FWA exponent, this divides the number by 16 (as the number is stored in binary). If a borrow occurred, then also decrement the FWA overflow exponent.
b) Copy the FWA to FWB, and divide the FWB mantissa by 2. Then add the FWB mantissa to the FWA mantissa (Least significant byte first, as usual). If carry if left after adding, then the FWA mantissa overflowed, so divide the FWA mantissa by 2 (making the top bit 1), and increment the FWA exponent & FWA exponent overflow (if necessary) to correct.
c) Copy the FWA to FWB, and divide the FWB mantissa by 16. Then add the FWB mantissa to the FWA mantissa (Least significant byte first, as usual). If carry if left after adding, then the FWA mantissa overflowed, so divide the FWA mantissa by 2 (making the top bit 1), and increment the FWA exponent & FWA exponent overflow (if necessary) to correct.
d) Zero &3D (FWB Mantissa byte 1), and set FWB mantissa byte 2 to FWA
mantissa byte 1, FWB mantissa byte 3 to FWA mantissa byte 2, FWB mantissa byte 4
to FWA mantissa byte 3 and FWB mantissa byte 5 to FWA mantissa byte 4. ROL
&35 (FWA mantissa byte 5), so that C = mantissa byte 5's top bit. This byte
manipulation has resulted in FWB = FWA divided by 256.
Next add the FWB mantissa to the FWA mantissa (Least significant byte first, as
usual). If carry if left after adding, then the FWA mantissa overflowed, so
divide the FWA mantissa by 2 (making the top bit 1), and increment the FWA
exponent & FWA exponent overflow (if necessary) to correct.
e) Zero &3E (FWB Mantissa byte 2, Note: FWB byte 1 is still zero from the
previous step), and set FWB mantissa byte 3 to FWA mantissa byte 1, FWB mantissa
byte 4 to FWA mantissa byte 2 and FWB mantissa byte 5 to FWA mantissa byte 3.
ROL &34 (FWA mantissa byte 4), so that C = mantissa byte 4's top bit. This
byte manipulation has resulted in FWB = FWA divided by 65536.
Next add the FWB mantissa to the FWA mantissa (Least significant byte first, as
usual). If carry if left after adding, then the FWA mantissa overflowed, so
divide the FWA mantissa by 2 (making the top bit 1), and increment the FWA
exponent & FWA exponent overflow (if necessary) to correct.
f) If the mantissa overflowed during the previous step, some extra rounding is performed, to correct the mantissa's value (this rounding correction also takes into account the value in the FWA mantissa byte 5).
g) If no overflow from the mantissa has occurred then end, otherwise divide the FWA mantissa by 2, making the top bit equal to 1 (from carry flag) to account for the overflow. The FWA exponent is then incremented to allow for the carry that was added to the mantissa. The FWA overflow exponent is also incremented if the FWA exponent overflowed.
In simpler terms, this routine is doing the following:
> a) FWA = FWA / 16
> b) FWA = FWA + (FWA / 2)
> c) FWA = FWA + (FWA / 16)
> d) FWA = FWA + (FWA / 256)
> e) FWA = FWA + (FWA / 65536)
Each of the division steps results in the following fractions of the original number:
a) 1 /
16
[0.0625]
b) 1 /
32
[0.03125]
c) 3 /
512
[0.0058593748]
d) 51 /
131072
[0.000389099]
e) 6553 / 4294967296 [0.00000152585]
All of these fractions add up to 0.1 (a tenth) - So this routines basically takes a tenth of the original number.
This gives the same result as FWA / 10, except that the calculations are done
using binary powers - which are a lot easier (and faster) to handle in 6502
Assembly language, than other decimal numbers.
Disassembly for the Floating Point divide 10 routine
A478 | 8 | 056 | 38 | SEC |
A479 | 0 | 165 048 | A5 30 | LDA &30 |
A47B | 233 004 | E9 04 | SBC#&04 | |
A47D | 0 | 133 048 | 85 30 | STA &30 |
A47F | 176 002 | B0 02 | BCS 2 --> &A483 | |
A481 | / | 198 047 | C6 2F | DEC &2F |
A483 | ( | 032 040 164 | 20 28 A4 | JSR &A428 FWB=FWA/2 |
A486 | G | 032 071 164 | 20 47 A4 | JSR &A447 Add FWB to FWA |
A489 | ( | 032 040 164 | 20 28 A4 | JSR &A428 FWB=FWA/2 |
A48C | + | 032 043 164 | 20 2B A4 | JSR &A42B FWB=FWB/2 |
A48F | + | 032 043 164 | 20 2B A4 | JSR &A42B FWB=FWB/2 |
A492 | + | 032 043 164 | 20 2B A4 | JSR &A42B FWB=FWB/2 |
A495 | G | 032 071 164 | 20 47 A4 | JSR &A447 Add FWB to FWA |
A498 | d= | 100 061 | 64 3D | STZ &3D |
A49A | 1 | 165 049 | A5 31 | LDA &31 |
A49C | > | 133 062 | 85 3E | STA &3E |
A49E | 2 | 165 050 | A5 32 | LDA &32 |
A4A0 | ? | 133 063 | 85 3F | STA &3F |
A4A2 | 3 | 165 051 | A5 33 | LDA &33 |
A4A4 | @ | 133 064 | 85 40 | STA &40 |
A4A6 | 4 | 165 052 | A5 34 | LDA &34 |
A4A8 | A | 133 065 | 85 41 | STA &41 |
A4AA | 5 | 165 053 | A5 35 | LDA &35 |
A4AC | * | 042 | 2A | ROL A |
A4AD | G | 032 071 164 | 20 47 A4 | JSR &A447 Add FWB to FWA |
A4B0 | d> | 100 062 | 64 3E | STZ &3E |
A4B2 | 1 | 165 049 | A5 31 | LDA &31 |
A4B4 | ? | 133 063 | 85 3F | STA &3F |
A4B6 | 2 | 165 050 | A5 32 | LDA &32 |
A4B8 | @ | 133 064 | 85 40 | STA &40 |
A4BA | 3 | 165 051 | A5 33 | LDA &33 |
A4BC | A | 133 065 | 85 41 | STA &41 |
A4BE | 4 | 165 052 | A5 34 | LDA &34 |
A4C0 | * | 042 | 2A | ROL A |
A4C1 | G | 032 071 164 | 20 47 A4 | JSR &A447 Add FWB to FWA |
A4C4 | 2 | 165 050 | A5 32 | LDA &32 |
A4C6 | * | 042 | 2A | ROL A |
A4C7 | 1 | 165 049 | A5 31 | LDA &31 |
A4C9 | e5 | 101 053 | 65 35 | ADC &35 |
A4CB | 5 | 133 053 | 85 35 | STA &35 |
A4CD | 144 016 | 90 10 | BCC 16 --> &A4DF | |
A4CF | 4 | 230 052 | E6 34 | INC &34 |
A4D1 | 208 012 | D0 0C | BNE 12 --> &A4DF | |
A4D3 | 3 | 230 051 | E6 33 | INC &33 |
A4D5 | 208 008 | D0 08 | BNE 8 --> &A4DF | |
A4D7 | 2 | 230 050 | E6 32 | INC &32 |
A4D9 | 208 004 | D0 04 | BNE 4 --> &A4DF | |
A4DB | 1 | 230 049 | E6 31 | INC &31 |
A4DD | 240 136 | F0 88 | BEQ -120 --> &A467 Handle Mantissa Overflow | |
A4DF | ` | 096 | 60 | RTS |