Submitted by Steve Fewell
Routine:ASCNUM:ExtractNum
Name: ASCII TO NUM: Extract Integer/Floating-Point Number at PTRB
Starting Address: &A2E1
Entry criteria: The SWA
contains the ASCII number to extract
Exit: Depending of the size of the number, and whether it contains a
fractional part
or not, either the FWA or IWA
will contain the binary conversion
or the number. A=&40 if Integer, or &FF if Floating-point.
Carry is clear if the ASCII text could not be converted to a numeric value.
Description:
Clears bytes &31 to &35 (The FWA Mantissa & rounding bytes).
Clears byte &47 - the 'Decimal Point found' flag. (remains zero if number is Integer)
Clears byte &48 - the Exponent of the extracted number. (remains zero if number is Integer)
If Next Character at PTRB is "." then A31C [if decimal point has already been found,
then A364 (Complete & tidy-up the number value) as the number is complete.
Otherwise, increment &47 (to set the decimal point found flag)
then goto A315 (to process the next character of the number).]
If Next Character at PTRB >= ":" or <= "/" then A2DA [Return 0.00 as no number found.].
Subtract 48 (47 + 1 as Carry Clear), so A=0 for "0", 1 for "1" ..., 9 for "9".
Store digit found at LSB of FWA (&35, the FWA rounding byte).
Load next character from PTRB in A.
If character >= ":" [non-digit] then A324 [process main body of number], as this checks
for "E" before terminating number extraction at an invalid character.]
Subtract 48 (47 + 1 as Carry Clear), so A=0 for "0", 1 for "1" ..., 9 for "9".
If carry clear (underflow occurred, A <= "/" [non-digit]) then A316 [ if char not = "." then A324
(to process main body of number);
otherwise, If character is "." then A31C [if decimal point has already been
found, then A364 (Complete & tidy-up the number value) as the number is complete.
Otherwise, increment &47 (to set the decimal point found flag)
then goto A315 (to process the next character of the number).]
]
Temporarily store A in &2E [FWA sign].
Multiplies the number in &35 by 10 and adds ?&2E to the result to form
a 2-digit binary number.
The multiply does this: ?&35=((?&35*4)+?&35)*2) + ?&2E
= ?&35=(?&35*5*2) plus ?&2E.
Get next character, and if it isn't "." then goto A324 [to process the main body of the
number]. Otherwise, set decimal found flag and get next character before going to A324 [main body]
or finish extraction (A364) if the next character was another ".".
ASCNUM: A324: Process main body of number:
This routine is first entered after the first two digits have been processed, (by A2E1) or after a "."
if the decimal point was encountered before that stage. This routine doesn't need to deal
with a "no number found" situation, as this has already been dealt with in A2E1.
This routine keeps the Exponent &48 in line with the binary value, and copes with
exponential values ("E"). It also copes with much bigger numbers than the 2-digit ones that
A2E1 processed.
This routines does the following:
If ASCII character is "E" then goto &A35D [to get the exponent value and convert the exponential
number to the completed binary value and exit with the result stored in the FWA]
If the character is not a valid digit (char >= ":" or char <= "/") then goto A364 to complete
the number and finish the extraction.
Subtract 48 (47 + 1 as Carry Clear), so A=0 for "0", 1 for "1" ..., 9 for "9".
X = ?&31 (FWA Mantissa byte 1). If this value is less than or equal to 24 then it is
ok to add the next digit to the end of the number [so goto &A33E]. Otherwise, the digit is not
added [number is too large] and the exponent is incremented (if no decimal point has been
found [integer value]). Then goto A315. A315 gets the next character, handles any decimal point
character found, or calls A324 again to handle all other characters.
ASCNUM: A33E: Add digit to end of number (and multiply 'old' number by 10):
If the number has a decimal point in it (?&47 not = 0) then decrement &48 (the exponent)
as we are adding a digit to the LSB of the value without moving the decimal point from its current position.
Multiply the current number by 10 (using &A279 [multiply FWA Mantissa by 10] routine).
&A279 returns with A unchanged, so we can add the next digit to &35 in order to
add the new digit to the end of the current number (now multiplied by 10 to cope with decimal-binary conversion).
If overflow occures, then we need to increment the rest of the bytes of the FWA Mantissa
(&34 and then &33 (if incrementing &34 overflowed), etc... to &31 if necessary).
lastly, we need to go back to A315 to get the next charater.
&A315 gets the next character, handles any decimal point character found, or calls &A324 again to
handle all other characters.
A2DA | 032 004 164 | 20 04 A4 | JSR &A404 | |
A2DD | 024 | 18 | CLC | |
A2DE | 169 255 | A9 FF | LDA#&FF | |
A2E0 | ` | 096 | 60 | RTS |
A2E1 | d1 | 100 049 | 64 31 | STZ &31 |
A2E3 | d2 | 100 050 | 64 32 | STZ &32 |
A2E5 | d3 | 100 051 | 64 33 | STZ &33 |
A2E7 | d4 | 100 052 | 64 34 | STZ &34 |
A2E9 | d5 | 100 053 | 64 35 | STZ &35 |
A2EB | dG | 100 071 | 64 47 | STZ &47 |
A2ED | dH | 100 072 | 64 48 | STZ &48 |
A2EF | . | 201 046 | C9 2E | CMP#&2E |
A2F1 | ) | 240 041 | F0 29 | BEQ 41 --> &A31C |
A2F3 | : | 201 058 | C9 3A | CMP#&3A |
A2F5 | 176 227 | B0 E3 | BCS -29 --> &A2DA | |
A2F7 | / | 233 047 | E9 2F | SBC#&2F |
A2F9 | 0 | 048 223 | 30 DF | BMI -33 --> &A2DA |
A2FB | 5 | 133 053 | 85 35 | STA &35 |
A2FD | 200 | C8 | INY | |
A2FE | 177 025 | B1 19 | LDA (&19),Y | |
A300 | : | 201 058 | C9 3A | CMP#&3A |
A302 | 176 032 | B0 20 | BCS 32 --> &A324 | |
A304 | / | 233 047 | E9 2F | SBC#&2F |
A306 | 144 014 | 90 0E | BCC 14 --> &A316 | |
A308 | . | 133 046 | 85 2E | STA &2E |
A30A | 5 | 165 053 | A5 35 | LDA &35 |
A30C | 010 | 0A | ASL A | |
A30D | 010 | 0A | ASL A | |
A30E | e5 | 101 053 | 65 35 | ADC &35 |
A310 | 010 | 0A | ASL A | |
A311 | e. | 101 046 | 65 2E | ADC &2E |
A313 | 5 | 133 053 | 85 35 | STA &35 |
A315 | 200 | C8 | INY | |
A316 | 177 025 | B1 19 | LDA (&19),Y | |
A318 | . | 201 046 | C9 2E | CMP#&2E |
A31A | 208 008 | D0 08 | BNE 8 --> &A324 | |
A31C | G | 165 071 | A5 47 | LDA &47 |
A31E | D | 208 068 | D0 44 | BNE 68 --> &A364 |
A320 | G | 230 071 | E6 47 | INC &47 |
A322 | 128 241 | 80 F1 | BRA -15 --> &A315 |
A324 | E | 201 069 | C9 45 | CMP#&45 |
A326 | 5 | 240 053 | F0 35 | BEQ 53 --> &A35D |
A328 | : | 201 058 | C9 3A | CMP#&3A |
A32A | 8 | 176 056 | B0 38 | BCS 56 --> &A364 |
A32C | / | 233 047 | E9 2F | SBC#&2F |
A32E | 4 | 144 052 | 90 34 | BCC 52 --> &A364 |
A330 | 1 | 166 049 | A6 31 | LDX &31 |
A332 | 224 024 | E0 18 | CPX#&18 | |
A334 | 144 008 | 90 08 | BCC 8 --> &A33E | |
A336 | G | 166 071 | A6 47 | LDX &47 |
A338 | 208 219 | D0 DB | BNE -37 --> &A315 | |
A33A | H | 230 072 | E6 48 | INC &48 |
A33C | 128 215 | 80 D7 | BRA -41 --> &A315 |
A33E | G | 166 071 | A6 47 | LDX &47 |
A340 | 240 002 | F0 02 | BEQ 2 --> &A344 | |
A342 | H | 198 072 | C6 48 | DEC &48 |
A344 | y | 032 121 162 | 20 79 A2 | JSR &A279 |
A347 | e5 | 101 053 | 65 35 | ADC &35 |
A349 | 5 | 133 053 | 85 35 | STA &35 |
A34B | 144 200 | 90 C8 | BCC -56 --> &A315 | |
A34D | 4 | 230 052 | E6 34 | INC &34 |
A34F | 208 196 | D0 C4 | BNE -60 --> &A315 | |
A351 | 3 | 230 051 | E6 33 | INC &33 |
A353 | 208 192 | D0 C0 | BNE -64 --> &A315 | |
A355 | 2 | 230 050 | E6 32 | INC &32 |
A357 | 208 188 | D0 BC | BNE -68 --> &A315 | |
A359 | 1 | 230 049 | E6 31 | INC &31 |
A35B | 128 184 | 80 B8 | BRA -72 --> &A315 |
A404 |