Code: Select all
;ONLY for test, not optimal! Don´t use the debugger! No check for string-correctness! For 64-bit-Windows! Make your own tests!
;ASCII and Unicode
Procedure StringToDouble(PointerToString.q, PointerToDouble.q) ;= ATOF(); Parameters: PointerToString = RCX, PointerToDouble = RDX
;!mov rcx,[p.v_PointerToString] ;for Debug
;!mov rdx,[p.v_PointerToDouble]
!PUSH r12
!PUSH r13
!PUSH r14
CompilerIf #PB_Compiler_Unicode
!MOV r14,2
CompilerElse
!MOV r14,1
CompilerEndIf
!XOR rax,rax
!MOV r8,rax
!MOV r9,rax
!MOV r11,rax ;signum_mantissa
!MOV r12,rax ;signum_exponent
!MOV r13,rax ;decimal_point
!MOV al,[rcx]
!CMP al,'-'
!JE .Signum_Neg
!CMP al,'+'
!JE .Signum_Pos
!JMP .Signum_End
!.Signum_Neg:
!INC r11
!.Signum_Pos:
!ADD rcx,r14
!MOV al,byte[rcx]
!.Signum_End:
!FLDZ
!.Read_Mantissa:
!CMP eax,'E'
!JE .Exponent
!CMP eax,'e'
!JE .Exponent
!CMP eax,'.'
!JE .Decimal_Point
!XOR eax,'0'
!CMP eax,9
!JA .Digits_End
!MOV [rdx],rax ;temp
!FMUL qword[Zehner]
!FIADD word[rdx]
!INC r8
!JMP .No_Decimal_Point
!.Decimal_Point:
!CMP r13,0 ;decimal_point
!JNE .Digits_End
!MOV r13,r8 ;R13 = decimal_point
!.No_Decimal_Point:
!ADD rcx,r14
!MOVZX rax,byte[rcx]
!JMP .Read_Mantissa
!.Exponent:
!ADD rcx,r14
!MOVZX rax,byte[rcx]
!CMP al,'-'
!JE .Signum_Exponent_Neg
!CMP al,'+'
!JE .Signum_Exponent_Pos
!JMP .Read_Exponent
!.Signum_Exponent_Neg:
!INC r12 ;signum_exponent
!.Signum_Exponent_Pos:
!ADD rcx,r14
!MOVZX rax,byte[rcx]
!.Read_Exponent:
!XOR rax,'0'
!CMP rax,9
!JA .Digits_End
!LEA r9,[r9*4+r9] ;R9 = Mul 5
!LEA r9,[r9*2+rax] ;R9 = Mul 10
!ADD rcx,r14
!MOVZX rax,byte[rcx]
!JMP .Read_Exponent
!.Digits_End:
!CMP r12,0 ;signum_exponent
!JE .Exponent_Ready
!NEG r9
!.Exponent_Ready:
!MOV rax,r13 ;R13 = decimal_point
!OR rax,rax
!JE .No_Decimal_Point2
!SUB r8,rax
!SUB r9,r8
!.No_Decimal_Point2:
!Or r9,r9
!JE .No_Exponent
!MOV rax,r9
!CMP rax,0
!JGE .Signum_Exponent_OK
!NEG rax
!.Signum_Exponent_OK:
!FLD1
!MOV r10b,al
!AND r10,0Fh
!JE .Big_Exponent
!LEA r10,[r10+r10*4]
!LEA r8,[Zehner_1]
!FLD tword[r10*2+r8-10]
!FMULP st1,st0
!.Big_Exponent:
!MOV r10b,al
!SHR r10b,4
!AND r10,0Fh
!JE .Bigger_Exponent
!LEA r10,[r10+r10*4]
!LEA r8,[Zehner_16]
!FLD tword[r10*2+r8-10]
!FMULP st1,st0
!.Bigger_Exponent:
!SHR rax,8
!AND rax,1Fh
!JE .Signum_Exponent
!LEA rax,[rax+rax*4]
!LEA r8,[Zehner_256]
!FLD tword[rax*2+r8-10]
!FMULP st1,st0
!.Signum_Exponent:
!CMP r9,0
!JGE .Exponent_Pos
!FDIVP st1,st0
!JMP .No_Exponent
!.Exponent_Pos:
!FMULP st1,st0
!.No_Exponent:
!CMP r11,0 ;signum_mantissa
!JE .Ready
!FCHS
!.Ready:
!FSTP qword[rdx] ;dword for Float
!POP r14
!POP r13
!POP r12
ProcedureReturn
!Zehner dq 10.0
!Zehner_1 dt 1.0e1
! dt 1.0e2
! dt 1.0e3
! dt 1.0e4
! dt 1.0e5
! dt 1.0e6
! dt 1.0e7
! dt 1.0e8
! dt 1.0e9
! dt 1.0e10
! dt 1.0e11
! dt 1.0e12
! dt 1.0e13
! dt 1.0e14
! dt 1.0e15
!Zehner_16 dt 1.0e16
! dt 1.0e32
! dt 1.0e48
! dt 1.0e64
! dt 1.0e80
! dt 1.0e96
! dt 1.0e112
! dt 1.0e128
! dt 1.0e144
! dt 1.0e160
! dt 1.0e176
! dt 1.0e192
! dt 1.0e208
! dt 1.0e224
! dt 1.0e240
!Zehner_256 dt 1.0e256
! dt 1.0e512 ;.... for extended double, for this test not used
EndProcedure
Double.d
StartTime = ElapsedMilliseconds()
For CTR = 1 To 1000000
StringToDouble$ = "13215.33414554664"
StringToDouble(@StringToDouble$, @Double)
Next
ElapsedTime = ElapsedMilliseconds() - StartTime
MessageRequester("Time!", "Elapsed Milliseconds : " + Str(ElapsedTime) + #LFCR$ + StrD(Double, 15))