[
Index] [
Previous] [
Next]
2.9 Reading Numbers
Function that reads a floating-point number from ASCII text.
FIn
Reads a string and converts it to a floating point number in FACCUM. The first thing we do is some initialisation.
Decrement string ptr so it points to just before the number, also set FACCUM to 0.
0AB3
2B
FIn
DCX H
Set B,D,E to 0 and C to 255.
0AB7
47
MOV B,A
B=count of fractional digits
0AB8
57
MOV D,A
D=exponent sign
0AB9
5F
MOV E,A
E=exponent
0ABA
2F
CMA
C=decimal_point_done (0xFF for no, 0x00 for yes)
0ABB
4F
MOV C,A
This is the head of the loop that processes one character of ASCII text at a time.
Get next ASCII character and if it's a digit (as determined by carry flag) then jump down to ProcessDigit.
If we have a decimal point then jump down to increment C and loop back up here (unless we've already encountered a decimal point).
0AC0
FE2E
CPI '.'
0AC2
CAE40A
JZ 0AE4
If it's not an 'E' indicating exponent then assume we've reached the end of the number and jump to ScaleResult.
0AC5
FE45
CPI 'E'
A decimal exponent has been given (eg 'E+23'). Here we read that (signed) exponent value into E. In this block we use D to hold the exponent sign (0xFF for minus and 0x01 for positive) while we loop reading the digits
Get first character of exponent (following the E).
0ACB
15
DCR D
0ACC
FE99
CPI KWID_-
0AD1
14
INR D
0AD2
FE98
CPI KWID_+
Exponent sign was not given, so it's implicitly +ve (D is 0 after above). We decrement HL so we can get the same character again without jumping.
0AD7
2B
DCX H
If the next char is a digit (of the exponent) then jump down to deal with it.
0ADC
14
INR D
D was 0xFF (ie negative exponent) therefore E = 0 - E
0AE0
AF
XRA A
0AE1
93
SUB E
0AE2
5F
MOV E,A
0AE3
0C
INR C
C was 0xFF, so here it
0AE4
0C
INR C
becomes 0x01.
0AE5
CABC0A
JZ
FInLoop
If C is now zero
We believe we've read all the characters that make up the number. The last thing that needs to be done is decimally scale our number in FACCUM with respect to the position of the decimal point and the decimal exponent value in E.
0AE8
E5
ScaleResult
PUSH H
The number of decimal positions to shift by is given by E-B, that is the (E)xponent minus the number of fractional digits given. The direction to shift in is also given by this subtraction, in the sign flag. This is preserved in the following loop.
0AE9
7B
MOV A,E
0AEA
90
SUB B
If we're shifting up (ie *ing by 10) then call the function to do that and jump to the end of the loop.
We're shifting down (ie sign flag is set) so call the function to do that and increment A,
0AF1
F5
PUSH PSW
0AF2
CD2309
CALL FDivByTen
0AF5
F1
POP PSW
0AF6
3C
INR A
If A is not yet 0 then we have more shifting to do and so loop back. Otherwise we restore the prog ptr and return.
0AFA
E1
POP H
0AFB
C9
RET
Helper function for shifting the result decimally up one place. We only do this if A !=0, and at the end we decrement A before returning.
0AFC
C8
DecimalShiftUp
RZ
0AFD
F5
PUSH PSW
0B01
F1
POP PSW
0B02
3D
DCR A
0B03
C9
RET
Process an ASCII digit. We multiply the current total by ten, then add this digit value to it.
Preserve the current exponent (DE) and copy the ASCII digit value to D.
0B04
D5
ProcessDigit
PUSH D
0B05
57
MOV D,A
Increment the count of fractional digits in B. C is 0xFF if no decimal point has been encountered, and 0 if it has. Adding with carry (which is set before this block is jumped to) makes this work.
0B06
78
MOV A,B
0B07
89
ADC C
0B08
47
MOV B,A
0B09
C5
PUSH B
0B0A
E5
PUSH H
Multiply the current total in FACCUM by ten and get the digit value in A.
0B0B
D5
PUSH D
0B0F
F1
POP PSW
0B10
D630
SUI '0'
Add this digit's value to FACCUM. To do this we first preserve FACCUM on the stack, then load FACCUM with the digit value (in A) via a call to FCharToFloat. Then we get the old FACCUM off the stack into BCDE and call FAdd.
0B18
C1
POP B
0B19
D1
POP D
Restore regpairs and jump back to FInLoop
0B1D
E1
POP H
0B1E
C1
POP B
0B1F
D1
POP D
Deal with a digit of the exponent. This is simple - just multiply the current exponent value (in E) by ten, then add the digit value to it, and finally jump back.
E=E*10 + (HL)
0B23
7B
DoExponentDigit
MOV A,E
0B24
07
RLC
0B25
07
RLC
0B26
83
ADD E
0B27
07
RLC
0B28
86
ADD M
0B29
D630
SUI '0'
0B2B
5F
MOV E,A
[Index] [Previous] [Next]