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
.
, - .