Submitted by Steve Fewell
Routine: amult10
Name: Float Multiply 10
Starting Address: &A436
Entry criteria: The FWA contains the
Floating-point number to multiply 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 Multiplication by 10 routine. The Division by 10 routine can be found here.
3 is added to the FWA exponent, this multiplies the number by 8 (as the number is stored in binary). The FWA overflow exponent is also updated, if this causes the FWA exponent to overflow.
Copy the FWA to FWB, and divide the FWB mantissa by 4. Then add the FWB mantissa to the FWA mantissa (Least significant byte first, as usual).
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:
> FWA = FWA * 8
> FWA = FWA + (0.25 * FWA)
which is the same as the following:
> FWA = 1.25 * (FWA * 8)
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 multiply 10 routine
A436 | 024 | 18 | CLC | |
A437 | 0 | 165 048 | A5 30 | LDA &30 |
A439 | i | 105 003 | 69 03 | ADC#&03 |
A43B | 0 | 133 048 | 85 30 | STA &30 |
A43D | 144 002 | 90 02 | BCC 2 --> &A441 | |
A43F | / | 230 047 | E6 2F | INC &2F |
A441 | ( | 032 040 164 | 20 28 A4 | JSR &A428 |
A444 | + | 032 043 164 | 20 2B A4 | JSR &A42B |
A447 | 5 | 165 053 | A5 35 | LDA &35 |
A449 | eA | 101 065 | 65 41 | ADC &41 |
A44B | 5 | 133 053 | 85 35 | STA &35 |
A44D | 4 | 165 052 | A5 34 | LDA &34 |
A44F | e@ | 101 064 | 65 40 | ADC &40 |
A451 | 4 | 133 052 | 85 34 | STA &34 |
A453 | 3 | 165 051 | A5 33 | LDA &33 |
A455 | e? | 101 063 | 65 3F | ADC &3F |
A457 | 3 | 133 051 | 85 33 | STA &33 |
A459 | 2 | 165 050 | A5 32 | LDA &32 |
A45B | e> | 101 062 | 65 3E | ADC &3E |
A45D | 2 | 133 050 | 85 32 | STA &32 |
A45F | 1 | 165 049 | A5 31 | LDA &31 |
A461 | e= | 101 061 | 65 3D | ADC &3D |
A463 | 1 | 133 049 | 85 31 | STA &31 |
A465 | 144 016 | 90 10 | BCC 16 --> &A477 | |
A467 | f1 | 102 049 | 66 31 | ROR &31 |
A469 | f2 | 102 050 | 66 32 | ROR &32 |
A46B | f3 | 102 051 | 66 33 | ROR &33 |
A46D | f4 | 102 052 | 66 34 | ROR &34 |
A46F | f5 | 102 053 | 66 35 | ROR &35 |
A471 | 0 | 230 048 | E6 30 | INC &30 |
A473 | 208 002 | D0 02 | BNE 2 --> &A477 | |
A475 | / | 230 047 | E6 2F | INC &2F |
A477 | ` | 096 | 60 | RTS |
FWB = FWA / 2 (Sub routine used by amult10):
A428 | 032 011 164 | 20 0B A4 | JSR &A40B bcopya | |
A42B | F= | 070 061 | 46 3D | LSR &3D |
A42D | f> | 102 062 | 66 3E | ROR &3E |
A42F | f? | 102 063 | 66 3F | ROR &3F |
A431 | f@ | 102 064 | 66 40 | ROR &40 |
A433 | fA | 102 065 | 66 41 | ROR &41 |
A435 | ` | 096 | 60 | RTS |