Convertir una cadena de caracteres en un doble

Convierta la cadena de caracteres a doble precisión en MASM64 sin usar FPU usando las instrucciones SSE4.1. El formato del número corresponde al formato aceptado por el compilador ML64.EXE



1. Configuración de convenciones de compilación, direccionamiento y llamada.
1.1. .
x64 software conventions



RCX



.



1.2. .
x64



x32



. . /LARGEADDRESSAWARE:NO



.





2. Constantes de texto y alias.
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. Sección de datos
. «» , , 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. Sección de código.
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