Convert a character string to a double

Convert character string to double precision on MASM64 without using FPU using SSE4.1 instructions. The format of the number corresponds to the format accepted by the compiler ML64.EXE



1. Settings for compilation, addressing and calling conventions.
1.1. .
x64 software conventions



RCX



.



1.2. .
x64



x32



. . /LARGEADDRESSAWARE:NO



.





2. Text constants and aliases.
2.1.
() «» :



BUFF_STR  equ esp - xmmword * 4

      
      







2.2. .
DWORD



INT







, , «» «» :



;  
CUR_CHAR  equ  ecx	      ;    
DOT_CHAR  equ  edx        ;    
HASH_STR  equ  r8d        ;    
END_CHAR  equ  HASH_STR   ;    
N_Z_CHAR  equ  r9d        ;      
OFF_CHAR  equ  N_Z_CHAR   ;       
END_FRAC  equ  r10d       ;      
EXP_CHAR  equ  END_FRAC   ;     
LEN_NUMB  equ  r11d       ;    
LEN_CELL  equ  LEN_NUMB   ;    

HASH_MUL  equ  ebx        ;      
MANT_ARG  equ  r8         ;   
LOGB_ARG  equ  r9d        ;   
MANT_MUL  equ  r10        ;  
LOGB_MUL  equ  r11d       ;  

      
      









3. Data section
. «» , , SIMD



, :



.data
Xmm_HT     byte 10h dup (09h)
Xmm_CR     byte 10h dup (0Dh)
Xmm_SP     byte 10h dup (20h)
Xmm_SL     byte 10h dup ('/')
Xmm_30     byte 10h dup ('0')
Xmm_39     byte 10h dup ('9')

Xmm_0001   word  8  dup      (010Ah)
Xmm_0010  dword  4  dup     (10064h)
Xmm_0100  qword  2  dup (100002710h)

Mask_001   word  0044h, 0944h, 0D44h, 2044h, 0046h, 0946h, 0D46h, 2046h
Mask_010   word  0064h, 0964h, 0D64h, 2064h, 0066h, 0966h, 0D66h, 2066h

Mul_0001  qword  0E8D4A51000h

Plus       word  2B00h

;  
string     byte  '	 ', 0Dh, 0Ah, '+-0098765432109876540.09876e-0248 '

      
      





.



4. Code section.
4.1. .
4.1.1.
4.1.1.1. .
β€” 3



3



-1



.

β€” CUR_CHAR







.

β€” CUR_CHAR







.



	pcmpeqb  xmm3, xmm3
	sub  CUR_CHAR, xmmword 
@@:	add  CUR_CHAR, xmmword

      
      





, -



, 15 . , , . .



4.1.1.2. .
β€” 0



1



/ 2



.

β€” ,



/



/





β€” 0



.



movdqu   xmm0,[CUR_CHAR]
movdqa   xmm1, xmm0
movdqa   xmm2, xmm0
pcmpeqb  xmm0, xmmword ptr Xmm_SP
pcmpeqb  xmm1, xmmword ptr Xmm_HT
pcmpeqb  xmm2, xmmword ptr Xmm_CR
paddb    xmm0, xmm1
paddb    xmm0, xmm2

      
      





0



-1



0



. «» .



4.1.1.3. .
β€” PTEST



AND



0



3



-1



CF=1



.

β€” CF=1



.



ptest    xmm0, xmm3
jc  @b	;    

      
      





.



/



/



SIMD



, 64



, , .





4.1.2. .
- 0



EAX



, 1



.

β€” EAX



, 1



.

β€” EAX



1



, , .

β€” EAX



CUR_CHAR



.



pmovmskb  eax, xmm0
not       eax
bsf       eax, eax
add  CUR_CHAR, eax

      
      







4.1.3. .
β€” ZF=1







.

β€” EAX



1



ZF=1



0



.

β€” EAX



CUR_CHAR







.



cmp   word ptr[CUR_CHAR - byte], 0A0Dh
setz  al
add  CUR_CHAR, eax

      
      









, .



4.1.4. .
β€” EAX



.

β€” ZF=1



EAX



0



.

β€” ZF=1



:



movzx  eax, byte ptr[CUR_CHAR]
test    al, al
jz  ErrorExit	;  

      
      









4.2. .
4.2.1. .
β€” AL







.

β€” AL



1



AL







0



.

β€” EAX



CUR_CHAR



.



cmp     al, '+'
setz    al
add    CUR_CHAR, eax

      
      









, .



4.2.2. .
β€”



.

β€” AL



1







0



.

β€” EAX



CUR_CHAR



.

β€” EAX



ESP



.



cmp    byte ptr[CUR_CHAR], '-'
setz    al
add    CUR_CHAR, eax
add    esp, eax

      
      









, ESP



1



, , . ESP



, «» «» «» , , , .





4.3. .
4.3.1. .
4.3.1.1. .
β€” , 16 , 0



.

β€” 1



2



.

β€” 0



9



.

β€” 0







1.



movdqu   xmm0,[CUR_CHAR + xmmword]
movdqa   xmm2, xmm0
movdqa   xmm3, xmm0
pcmpgtb  xmm0, xmmword ptr Xmm_39
movdqa   xmm1, xmm0

      
      





0



1



9



-1



, 0



.



4.3.1.2. .
β€” 2







, 2



0



-1



, 0



.

β€” PANDN



0



AND



0



2



0



.



pcmpgtb  xmm2, xmmword ptr Xmm_SL
pandn    xmm0, xmm2

      
      





0



0



9



,



, -1



0



.



4.3.1.3. .
β€” 3



0



, 3



1



-1



, 0



.

β€” PANDN



1



AND



1



3



1



.



pcmpgtb  xmm3, xmmword ptr Xmm_30
pandn    xmm1, xmm3

      
      





1



1



9



,



, -1



0



.



4.3.1.4. .
β€” 0



HASH_STR



.

β€” 1



N_Z_CHAR







pmovmskb HASH_STR, xmm0
pmovmskb N_Z_CHAR, xmm1

      
      





16 HASH_STR



16 , 1



0



, 16 N_Z_CHAR



16 , , 1



0



.





4.3.2. .
movdqu   xmm0,[CUR_CHAR]
movdqa   xmm2, xmm0
movdqa   xmm3, xmm0
pcmpgtb  xmm0, xmmword ptr Xmm_39
movdqa   xmm1, xmm0
pcmpgtb  xmm2, xmmword ptr Xmm_SL
pcmpgtb  xmm3, xmmword ptr Xmm_30
pandn    xmm0, xmm2
pandn    xmm1, xmm3

      
      







4.3.3. .
β€” 0



EAX



.

β€” 16 HASH_STR



HASH_STR



.

β€” HASH_STR



EAX



.

β€” 1



EAX



.

β€” 16 N_Z_CHAR



N_Z_CHAR



.

β€” N_Z_CHAR



EAX



.



pmovmskb  eax, xmm0
shl  HASH_STR, xmmword
add  HASH_STR, eax
pmovmskb  eax, xmm1
shl  N_Z_CHAR, xmmword
add  N_Z_CHAR, eax

      
      





HASH_STR







1



0



, , N_Z_CHAR







1



, 0



, .





4.4. .
4.4.1. .
β€” HASH_STR



1, EAX



ZF=1



.

β€” ZF=1







.

β€” ZF=0



.

β€” ZF=0







.



bsf   eax, HASH_STR
jz  ErrorExit
test  eax, eax
jnz ErrorExit

      
      













. BSF



, 1



0



BSF



0



ZF=0



, 1



, ZF=1



.



4.4.2. .
β€” HASH_STR



1







.

β€” HASH_STR



, DOT_CHAR



ZF=1



HASH_STR



.

β€” ZF=1







.

β€”







ZF=0



.

β€” ZF=0











.



not  HASH_STR
bsf  DOT_CHAR, HASH_STR
jz  ErrorExit
cmp  byte ptr[CUR_CHAR + DOT_CHAR], '.'
jnz ErrorExit

      
      







4.4.3. .
β€” N_Z_CHAR



EAX





β€” N_Z_CHAR



.

β€” 0000



1 () BUFF_STR



.

β€” 0







, N_Z_CHAR



, .

β€” BUFF_STR



.

β€” 0



N_Z_CHAR



16 .

β€”



BUFF_STR



16 .



mov        eax, N_Z_CHAR
bsf   N_Z_CHAR, N_Z_CHAR
mov   dword ptr[BUFF_STR - byte], 30303030h
movdqu    xmm0,[CUR_CHAR + N_Z_CHAR]
movdqu         [BUFF_STR + 00000000], xmm0
movdqu    xmm0,[CUR_CHAR + N_Z_CHAR + xmmword]
movdqu         [BUFF_STR + 00000000 + xmmword], xmm0

      
      





32



N_Z_CHAR



BUFF_STR



. .





4.5. .
4.5.1. .
β€” , , DOT_CHAR



0



.

β€” , , DOT_CHAR



16 1



.



movdqu  xmm0,[CUR_CHAR + DOT_CHAR + byte]
movdqu  xmm1,[CUR_CHAR + DOT_CHAR + byte + xmmword]

      
      







4.5.2. .
β€” HASH_STR



DOT_CHAR



, .

β€” HASH_STR



ZF=1



.

β€” ZF=1



.



btr    HASH_STR, DOT_CHAR
bsf    END_FRAC, HASH_STR
jz  ErrorExit

      
      





EXP_CHAR



.



4.5.3. .
4.5.3.1. .
β€” END_FRAC



N_Z_CHAR



CF=1



N_Z_CHAR



END_FRAC



.

β€” END_FRAC



N_Z_CHAR



CF=1



.



cmp    END_FRAC, N_Z_CHAR
cmovc  N_Z_CHAR, END_FRAC

      
      









, N_Z_CHAR



END_FRAC



, N_Z_CHAR



END_FRAC



.



4.5.3.2. .
β€” N_Z_CHAR



DOT_CHAR



N_Z_CHAR



DOT_CHAR



, , , CF=1



.

β€” LEN_NUMB



END_FRAC



.

β€” LEN_NUMB



N_Z_CHAR



CF



.



cmp    N_Z_CHAR, DOT_CHAR
mov    LEN_NUMB, END_FRAC
sbb    LEN_NUMB, N_Z_CHAR

      
      





LEN_NUMB



, , .





4.5.4. .
β€” DOT_CHAR



N_Z_CHAR



SF=0



, .

β€” OFF_CHAR



20



.

β€” SF=0



DOT_CHAR



OFF_CHAR



.

β€”



OFF_CHAR



BUFF_STR



.

β€”



OFF_CHAR



16 , BUFF_STR



sub    DOT_CHAR, N_Z_CHAR
mov    OFF_CHAR, xmmword + dword
cmovns OFF_CHAR, DOT_CHAR
movdqu   xmmword ptr[BUFF_STR + OFF_CHAR + 0000000], xmm0
movdqu   xmmword ptr[BUFF_STR + OFF_CHAR + xmmword], xmm1 

      
      





OFF_CHAR



, OFF_CHAR



20



. «» , , .



4.5.5. .
β€” 2







.

β€”



LEN_NUMB



BUFF_STR



.

β€”



LEN_NUMB



16 , BUFF_STR



.

β€” LEN_CELL



DOT_CHAR



.



movdqu     xmm2, xmmword ptr Xmm_30
movdqu           xmmword ptr[BUFF_STR + LEN_NUMB + 0000000], xmm2
movdqu           xmmword ptr[BUFF_STR + LEN_NUMB + xmmword], xmm2
lea    LEN_CELL, [DOT_CHAR * 2]

      
      





«» ,



, LEN_NUMB







. , 20



. LEN_CELL











.





4.6. .
4.6.1. .
β€” N_Z_CHAR



.

β€” 0



END_FRAC



.

β€” END_FRAC



0



.

β€” END_FRAC



0



.

β€” 0



1



.



xor  N_Z_CHAR, N_Z_CHAR
movd     xmm0, dword ptr[CUR_CHAR + END_FRAC]
pshuflw  xmm0, xmm0, 0
pshufd   xmm0, xmm0, 0
movdqa   xmm1, xmm0

      
      







4.6.2. .
β€” 0



-1



0



.

β€” 1



-1



0



.

β€” 0



1



0



.

β€” 1



1



-1



.

β€” PTEST



AND



0



1



-1



ZF=0



.

β€” ZF=0 .



pcmpeqw  xmm0, Mask_001
pcmpeqw  xmm1, Mask_010
paddw    xmm0, xmm1
pcmpeqb  xmm1, xmm1
ptest    xmm0, xmm1
jnz @f

      
      







4.6.3. .
β€” EDX



END_FRAC



.

β€” ZF=1



EDX



0



.

β€”
ZF=1[/INLINE                  .
      



movzx edx, word ptr[CUR_CHAR + END_FRAC] test dl, dl jz @f
















4.7. .
4.7.1. .
β€” 5



EDX



.

β€” ZF=0



EDX







.

β€” ZF=0



.



btr       edx, 5
cmp        dl,'E'
jnz ErrorExit

      
      







4.7.2.
4.7.2.1. .
β€” HASH_STR



EXP_CHAR



,



.

β€” EXP_CHAR



1



.

β€” HASH_STR



EXP_CHAR



,



/



CF=1



0



.

β€” CF=1



EDX







Plus



.

β€” EXP_CHAR



CF=1



.



btr    HASH_STR, EXP_CHAR
inc    EXP_CHAR
btr    HASH_STR, EXP_CHAR
cmovnc  dx, Plus
adc    EXP_CHAR, 0

      
      









. .



4.7.2.2. .
β€” ZF=1



DH







.

β€” DL



1



ZF=1



.

β€” ZF=1



DH







.

β€” DH



1



ZF=1



.

β€” 8



DX



CF



.

β€” LEN_CELL



CF



.

β€” ZF=1



EDX



0



.

β€”



cmp     dh,'+'
setz    dl
cmp     dh,'-'
setz    dh
bt      dx, 8
adc    LEN_CELL, 0

      
      





LEN_CELL



, LEN_CELL











.





4.7.3. .
β€” EAX



N_Z_CHAR



N_Z_CHAR



EAX



4.4.3.





β€” EAX



.

β€” EAX



EXP_CHAR



.

β€” EAX



, , -1



EAX



EXP_CHAR



1



0



.

β€” EAX



1



.

β€”

mov  N_Z_CHAR, eax
xor       eax, eax
bts       eax, EXP_CHAR
add       eax, -1
not       eax
and  N_Z_CHAR, eax
bsf  N_Z_CHAR, N_Z_CHAR
movdqu   xmm0,[CUR_CHAR + N_Z_CHAR]

      
      







4.7.4. .
bsf  END_CHAR, END_CHAR
jz  ErrorExit 
movzx     eax, byte ptr[CUR_CHAR + END_CHAR]
cmp       eax, 20h
ja  ErrorExit
add       rdx,(1 + 1 shl 09h + 1 shl 0Dh + 1 shl 20h)
bt        rdx, rax
jnc ErrorExit

      
      









4.8. - -
	sub  N_Z_CHAR, END_CHAR
	cmp  N_Z_CHAR, -4
;	jnc ErrorExit
@@:	cmp    byte ptr[BUFF_STR + 00000000 + xmmword + dword - byte],'5'
	mov   dword ptr[BUFF_STR + 00000000 + xmmword + dword - byte],'0000'
	movd  dword ptr[BUFF_STR + N_Z_CHAR + xmmword + qword - byte], xmm0

      
      







4.9.
	;       #region
		movdqu    xmm0,[BUFF_STR + 0000000 - byte]
		movdqu    xmm1,[BUFF_STR + xmmword - byte]
		psubb     xmm0, xmm2
		psubb     xmm1, xmm2
		pmaddubsw xmm1, xmmword ptr Xmm_0001
		pmaddwd   xmm1, xmmword ptr Xmm_0010
	; #endregion

      
      







4.10.
	;   #region
		movd      rax, xmm1
		sbb       rax, -1
		movd     xmm1, eax
		shr       rax, 20h
		movd     xmm2, rbx
		mov       ebx, eax
		neg       eax
		sar  LEN_CELL, 1
		cmovc     ebx, eax
		add       ebx, LEN_CELL
		mov       eax, ebx
		neg       eax
		cmovns    ebx, eax

		mov         rax, 0A000000000000000h
		mov    MANT_ARG, 0CCCCCCCCCCCCCCCCh
		cmovs  MANT_ARG, rax
		mov         eax, 3
		mov    LOGB_ARG, -3
		cmovs  LOGB_ARG, eax

		mov    MANT_MUL, 1
		mov    LOGB_MUL, 0
		shr    HASH_MUL, 1 
		cmovc  MANT_MUL, MANT_ARG
		cmovc  LOGB_MUL, LOGB_ARG
	
	@@:	jz  @f
		mov         rax, MANT_ARG
		mul         rax
		bt          rdx, 3Fh
		setnc        cl
		adc    LOGB_ARG, LOGB_ARG
		shld        rdx, rax, cl
		mov    MANT_ARG, rdx
		shr    HASH_MUL, 1
	jnc @b	

		mov         rax, rdx
		mul    MANT_MUL
		bt          rdx, 3Fh
		setnc        cl
		adc    LOGB_MUL, LOGB_ARG
		shld        rdx, rax, cl
		mov    MANT_MUL, rdx
		test   HASH_MUL, HASH_MUL
	jmp @b

	@@:	movd   rbx, xmm2
	; #endregion

      
      







4.11. .
	;     #region
		psubb     xmm0, xmm2
		pmaddubsw xmm0, xmmword ptr Xmm_0001
		pmaddwd   xmm0, xmmword ptr Xmm_0010
		pmulld    xmm0, xmmword ptr Xmm_0100
		phaddd    xmm0, xmm0

		movd       eax, xmm0
		imul       rax, Mul_0001
		pextrd     edx, xmm0, 1
		imul       rdx, 02710h
		add        rax, rdx
		movd       edx, xmm1
		add        rax, rdx
		bsr        rcx, rax
		add   LOGB_MUL, ecx
		inc         cl
		shrd       rax, rax, cl
	; #endregion

      
      







4.12. .
	;   #region
		mul   MANT_MUL
		bt         rdx, 3Fh
		setnc       cl
		adc   LOGB_MUL, 3FFh
		shld       rdx, rax, cl
		shl        rdx, 1
		shrd       rdx, r11, 11
		shrd       rdx, rsp, 1
		btr        esp, 0
		movd      xmm0, rdx
	; #endregion

      
      







4.13. .
	ret

      
      







4.14. ErrorExit
	ErrorExit:	;   #region
		mov      ecx, -1
		pcmpeqb xmm1, xmm1
		psllq   xmm1, 52 + 1
		psrlq   xmm1, 1
		ret
	; #endregion

      
      










All Articles