Submitted by Steve Fewell
Routine: ConvFWAtoInt
Name: Convert Floating-Point to Integer
Starting Address: &8242
Entry criteria: The FWA contains a
Floating-Point number.
Exit: The FWA value has been truncated,
and the Integer part of its value has been retained.
Description:
Load A with the FWA Exponent Byte, if it isn't negative (offset by &80) then
the Floating-Point value is less than or equal to zero, so jump to Clear FWA and
exit with the Integer value set to zero.
If the FWA Mantissa byte 1 is zero then assume that the FWA contains the value zero [?], so exit by doing an Integer Reverse Order Complement of the FWA's Mantissa value. I'm not sure why this is necessary though, as if the number zero doesn't need to be stored in twos complement form.
Now, keep on moving the bite in the FWA Mantissa right one position, until we
are left with the Integer part of the number (Stored most significant Byte
first, and least significant Byte in ?&34). This achieves two goals, first
it gets rid of the fractional part of the number, and second it right-aligns the
Integer value and prefixes it with leading zeros (The Integer value will still
be stored the opposite way around to an Integer in the IWA
though!).
Here is a comparison showing how a Twos-Complement Integer value is stored in
the IWA, and how it is stored in the FWA:
Integer in IWA | Integer in FWA | |
Byte | Description | Byte |
&2A | Least Significant Byte | &34 |
&2B | Integer Byte 2 | &33 |
&2C | Integer Byte 3 | &32 |
&2D | Most Significant Byte | &31 |
Note: The Floating-Points exponent is the number of bits which make up the Integer part of the number offset by &80 (128). Additionally, the FWA Mantissa Rounding Byte is ignored during this conversion.
To achieve the two goals stated above, BASIC does the following:
Keep dividing the FWA Mantissa by 2 (Moving the bits right one position, making
the first bit zero, and loosing the last bit) and incrementing the exponent
(Stored in the Accumulator), so that the exponent still points to the
imaginary decimal point which separates the Integer part from the fractional
part, until the exponent is 32 (&A0). I.e. This occurs when the start of the
fraction has just been moved out of the end of the Mantissa and lost.
This operation (divide Mantissa by 2 and Increment Exponent) is done once
at the beginning, but then if more than 7 bits need to be shifted right, then
the alternative quicker method (Divide Mantissa by 16 and Add 8 to Exponent) is
used [i.e. move the Mantissa bytes along one place, loosing the last (?&34)
byte]. If less than 8 bits need to be shifted, then the single-bit method is
used.
If at any point the exponent goes over &A0, then a Too Big error is produced (as the number is > 32 bits long), otherwise, when the exponent is equal to &A0, the Exponent [A] is stored back in the FWA Exponent Byte and an Integer Reverse Order Complement is done (which converts the Integer into Twos-complement notation if a negative result is required - i.e. if the FWA's Sign Byte is negative).
Disassembly for the Convert Floating-Point to Integer routine
8242 | 0 | 165 048 | A5 30 | LDA &30 |
8244 | , | 016 044 | 10 2C | BPL 44 --> &8272 |
8246 | 1 | 164 049 | A4 31 | LDY &31 |
8248 | 4 | 240 052 | F0 34 | BEQ 52 --> &827E Move the fractional value from the FWA to the FWB |
824A | F1 | 070 049 | 46 31 | LSR &31 |
824C | f2 | 102 050 | 66 32 | ROR &32 |
824E | f3 | 102 051 | 66 33 | ROR &33 |
8250 | f4 | 102 052 | 66 34 | ROR &34 |
8252 | 026 | 1A | INC A | |
8253 | h | 240 104 | F0 68 | BEQ 104 --> &82BD Too big error |
8255 | 201 160 | C9 A0 | CMP#&A0 | |
8257 | g | 176 103 | B0 67 | BCS 103 --> &82C0 Check Exponent and make Twos Complement Integer (if necessary) |
8259 | 201 153 | C9 99 | CMP#&99 | |
825B | 176 237 | B0 ED | BCS -19 --> &824A | |
825D | i | 105 008 | 69 08 | ADC#&08 |
825F | 3 | 164 051 | A4 33 | LDY &33 |
8261 | 4 | 132 052 | 84 34 | STY &34 |
8263 | 2 | 164 050 | A4 32 | LDY &32 |
8265 | 3 | 132 051 | 84 33 | STY &33 |
8267 | 1 | 164 049 | A4 31 | LDY &31 |
8269 | 2 | 132 050 | 84 32 | STY &32 |
826B | d1 | 100 049 | 64 31 | STZ &31 |
826D | 128 230 | 80 E6 | BRA -26 --> &8255 |
Jump to Clear FWA
8272 | L | 076 180 166 | 4C B4 A6 | JMP &A6B4 Clear FWA |
Move the fractional value from the FWA to the FWB
827E | D | 240 068 | F0 44 | BEQ 68 --> &82C4 Integer Reverse Order Complement |
8280 | F1 | 070 049 | 46 31 | LSR &31 |
8282 | f2 | 102 050 | 66 32 | ROR &32 |
8284 | f3 | 102 051 | 66 33 | ROR &33 |
8286 | f4 | 102 052 | 66 34 | ROR &34 |
8288 | f= | 102 061 | 66 3D | ROR &3D |
828A | f> | 102 062 | 66 3E | ROR &3E |
828C | f? | 102 063 | 66 3F | ROR &3F |
828E | f@ | 102 064 | 66 40 | ROR &40 |
8290 | 026 | 1A | INC A | |
8291 | * | 240 042 | F0 2A | BEQ 42 --> &82BD Too big error |
8293 | 201 160 | C9 A0 | CMP#&A0 | |
8295 | ) | 176 041 | B0 29 | BCS 41 --> &82C0 Check Exponent and make Twos Complement Integer (if necessary) |
8297 | 201 153 | C9 99 | CMP#&99 | |
8299 | 176 229 | B0 E5 | BCS -27 --> &8280 | |
829B | i | 105 008 | 69 08 | ADC#&08 |
829D | ? | 164 063 | A4 3F | LDY &3F |
829F | @ | 132 064 | 84 40 | STY &40 |
82A1 | > | 164 062 | A4 3E | LDY &3E |
82A3 | ? | 132 063 | 84 3F | STY &3F |
82A5 | = | 164 061 | A4 3D | LDY &3D |
82A7 | > | 132 062 | 84 3E | STY &3E |
82A9 | 4 | 164 052 | A4 34 | LDY &34 |
82AB | = | 132 061 | 84 3D | STY &3D |
82AD | 3 | 164 051 | A4 33 | LDY &33 |
82AF | 4 | 132 052 | 84 34 | STY &34 |
82B1 | 2 | 164 050 | A4 32 | LDY &32 |
82B3 | 3 | 132 051 | 84 33 | STY &33 |
82B5 | 1 | 164 049 | A4 31 | LDY &31 |
82B7 | 2 | 132 050 | 84 32 | STY &32 |
82B9 | d1 | 100 049 | 64 31 | STZ &31 |
82BB | 128 214 | 80 D6 | BRA -42 --> &8293 |
Jump to "Too Big" error
82BD | L | 076 197 166 | 4C C5 A6 | JMP &A6C5 Too Big error number 20 |
Check Exponent and make Twos Complement Integer (if necessary)
82C0 | 208 251 | D0 FB | BNE -5 --> &82BD | |
82C2 | 0 | 133 048 | 85 30 | STA &30 |
82C4 | ... | Integer Reverse Order Complement |