Cada pessoa que gosta de programação é obrigada a escrever sua própria versão da solução para este problema. Decidi não ser exceção.
De acordo com, x64 software conventions
assumiremos que o número a ser convertido está localizado em XMM0
.
Usaremos x64
código de x32
bits para endereçamento de bits. Essa forma de endereçamento permite que você aproveite os dois dialetos.
Salve o valor da pilha e crie um ponto de dados alinhado ao parágrafo para melhorar o desempenho:
;
mov r9d, esp
lea r8d,[r9d - 70h]
and r8d, 0FFFFFFF0h
mov esp, r8d
Nós o preparamos FPU
libertando-o dos dados e definimos a maior precisão e arredondamento para zero:
fsave [esp]
finit
mov dword ptr[esp - dword], 037F0F7Fh
fldcw [esp - dword]
Sobrecarregamos o número de XMM0
para FPU
:
movd qword ptr[esp - xmmword], xmm0
fld qword ptr[esp - xmmword]
Encontre a ordem decimal do número:
fld st(0)
fxtract
fldl2t
fst st(1)
fdivr st(0),st(2)
frndint
Defina o arredondamento para o número mais próximo:
fldcw [esp - word]
Preservamos a ordem do número e encontramos a ordem decimal do multiplicador para converter os dígitos significativos do número para a parte inteira:
fist dword ptr[esp - dword]
movzx edx, word ptr[esp - dword]
mov dword ptr[esp - dword], 10h
fisubr dword ptr[esp - dword]
Encontre o multiplicador decimal e multiplique-o pelo 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
Recarregamos o número resultante FPU
em registradores AX
e XMM0
no tamanho dos primeiros 2 e 8 bytes subsequentes, respectivamente. Ao carregar 8 bytes em um registrador, XMM0
alteramos simultaneamente a ordem dos bytes, pré-alinhando o ponteiro da pilha pelo parágrafo:
fbstp tbyte ptr[esp - xmmword]
mov ax, word ptr[esp - qword]
pshuflw xmm0, xmmword ptr[esp - xmmword], 00011011b
Nós restauramos o 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
.
, - .