8-Bit Software

The BBC and Master Computer Public Domain Library

Back to 8BS Or Back to Disassembly


Page Last Altered:

A2E1 ASCNUM: Extract Number at PTRB

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.


Disassembly for the ASCNUM: Extract Number at PTRB routine

ASCNUM: return wth Floating-Point value 0.0 [number not found]:
A2DA   032 004 164 20 04 A4 JSR &A404
A2DD   024 18 CLC
A2DE   169 255 A9 FF LDA#&FF
A2E0 ` 096 60 RTS

ASCNUM: Convert String at PTRB to either an Integer/Floating-Point Number:
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

ASCNUM: Convert main body of number:
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

ASCNUM: Add digit to end of number (and multiply 'old' number by 10):
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

ASCNUM: Finish zeroing the FWA (to return value 0.00):
A404

 


 Back to 8BS
Or