Convertir un número en una cadena usando FPU

Toda persona aficionada a la programación está obligada a escribir su propia versión de la solución a este problema. Decidí no ser la excepción.





De acuerdo con, x64 software conventions



asumiremos que el número a convertir se encuentra en XMM0



.





Usaremos x64



código de x32



bits para el direccionamiento de bits. Esta forma de direccionamiento le permite aprovechar ambos dialectos.





Guarde el valor de la pila y cree un punto de datos alineado con párrafos para mejorar el rendimiento:





	;  
	mov    r9d, esp
	lea    r8d,[r9d - 70h]
	and    r8d, 0FFFFFFF0h
	mov    esp, r8d
      
      



Lo preparamos FPU



liberándolo de datos y establecemos el aumento de precisión y redondeo a cero:





	fsave [esp]
	finit
	mov  dword ptr[esp - dword], 037F0F7Fh
	fldcw         [esp - dword]
      
      



Sobrecargamos el número de XMM0



a FPU



:





	movd qword ptr[esp - xmmword], xmm0
	fld  qword ptr[esp - xmmword]
      
      



Encuentra el orden decimal del número:





	fld     st(0)
	fxtract
	fldl2t
	fst     st(1)
	fdivr   st(0),st(2)
	frndint
      
      



Establezca el redondeo al número más cercano:





	fldcw	[esp - word]
      
      



Conservamos el orden del Número y encontramos el orden decimal del Multiplicador para convertir los dígitos significativos del Número a la parte entera:





	fist      dword ptr[esp - dword]
	movzx edx, word ptr[esp - dword]
	mov       dword ptr[esp - dword], 10h
	fisubr    dword ptr[esp - dword]
      
      



Encuentra el multiplicador decimal y multiplícalo por el número:





	fmulp   st(1),st(0)
	fst     st(1)
	frndint
	fsub    st(1),st(0)
	fld1
	fscale
	fstp    st(1)
	fmulp   st(2),st(0)
	f2xm1
	fld1
	faddp   st(1),st(0)
	fmulp   st(1),st(0)
	frndint
      
      



Recargamos el número resultante FPU



en los registros AX



y XMM0



en el tamaño de los primeros 2 y 8 bytes posteriores, respectivamente. Cuando cargamos 8 bytes en un registro, XMM0



simultáneamente cambiamos el orden de los bytes al alinear previamente el puntero de la pila por el párrafo:





	fbstp           tbyte ptr[esp - xmmword]
	mov       ax,    word ptr[esp -   qword]
	pshuflw xmm0, xmmword ptr[esp - xmmword], 00011011b
      
      



Restauramos el estado FPU



:





	frstor [esp]
      
      



0



:





	punpcklbw xmm0, xmm0
	pshuflw   xmm0, xmm0, 10110001b
	pshufhw   xmm0, xmm0, 10110001b
      
      



:





	mov            dword ptr[esp], 0FF00FF0h
	pshufd xmm1, xmmword ptr[esp], 0
	pand   xmm0, xmm1
	psrlw  xmm1, 4
	movdqa xmm2, xmm1
	pand   xmm1, xmm0
	psrlw  xmm1, 4
	pandn  xmm2, xmm0
	paddb  xmm1, xmm2
      
      



:





	pxor    xmm0, xmm0
	pcmpeqb xmm0, xmm1
      
      



:





	mov            dword ptr[esp], 30303030h
	pshufd xmm2, xmmword ptr[esp], 0
	paddb  xmm1, xmm2
      
      



:





	mov  byte ptr[esp],'-'
	btr             ax, 0Fh
	adc            esp, 0
	add             ax,'.0'
	mov  word ptr[esp], ax
      
      



0



:





	movdqu	      xmmword ptr[esp + word], xmm1
	pmovmskb ecx, xmm0
	bsf      ecx, ecx
	add      esp, ecx
      
      



:





	mov    ecx,(word + dword)
	mov    eax, edx
	neg     dx
	jnc     @f
	cmovns eax, edx
	setns   dh
      
      



:





	cmp   ax, 0Ah
	sbb  ecx, ecx
	mov   dl, 0Ah
	div   dl
	cmp   al, 0Ah
	sbb  ecx, 0
	shl  eax, 8
	shr   ax, 8
	div   dl
	add eax, 303030h
	lea edx,[edx * 2 + 2B51h]
	
	mov dword ptr[esp + word + ecx + word], eax
	mov  word ptr[esp + word], dx
      
      



EAX



ECX



:





@@:	lea ecx,[esp + ecx + qword]
	sub ecx, r8d
  mov eax,ecx
      
      



XMM1



XMM2



:





	movdqa xmm1, xmmword ptr[r8d]
	movdqa xmm2, xmmword ptr[r8d + xmmword]
      
      



:





	mov esp, r9d
      
      



.





/ . x64 software conventions



.






- .





- , .





- .





- SIMD



FPU



.





, - .








All Articles