Jeder, der gerne programmiert, ist verpflichtet, seine eigene Version der Lösung für dieses Problem zu schreiben. Ich beschloss, keine Ausnahme zu sein.
In Übereinstimmung x64 software conventions
damit gehen wir davon aus, dass sich die zu konvertierende Nummer in befindet XMM0
.
Wir werden x64
Bitcode für die x32
Bitadressierung verwenden. Diese Art der Adressierung ermöglicht es Ihnen, beide Dialekte zu nutzen.
Speichern Sie den Stapelwert und erstellen Sie einen absatzausgerichteten Datenpunkt, um die Leistung zu verbessern:
;
mov r9d, esp
lea r8d,[r9d - 70h]
and r8d, 0FFFFFFF0h
mov esp, r8d
Wir bereiten es vor, indem wir FPU
es von Daten befreien und die erhöhte Genauigkeit und Rundung auf Null setzen:
fsave [esp]
finit
mov dword ptr[esp - dword], 037F0F7Fh
fldcw [esp - dword]
Wir überladen die Nummer von XMM0
bis FPU
:
movd qword ptr[esp - xmmword], xmm0
fld qword ptr[esp - xmmword]
Finden Sie die Dezimalreihenfolge der Zahl:
fld st(0)
fxtract
fldl2t
fst st(1)
fdivr st(0),st(2)
frndint
Stellen Sie die Rundung auf die nächste Zahl ein:
fldcw [esp - word]
Wir behalten die Reihenfolge der Zahl bei und finden die Dezimalreihenfolge des Multiplikators, um die signifikanten Ziffern der Zahl in den ganzzahligen Teil umzuwandeln:
fist dword ptr[esp - dword]
movzx edx, word ptr[esp - dword]
mov dword ptr[esp - dword], 10h
fisubr dword ptr[esp - dword]
Suchen Sie den Dezimalmultiplikator und multiplizieren Sie ihn mit der Zahl:
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
Wir laden die resultierende Zahl aus FPU
Registern AX
und XMM0
in der Größe der ersten 2 bzw. 8 nachfolgenden Bytes neu. Beim Laden von 8 Bytes in ein Register XMM0
ändern wir gleichzeitig die Reihenfolge der Bytes, indem wir den Stapelzeiger durch den Absatz vorab ausrichten:
fbstp tbyte ptr[esp - xmmword]
mov ax, word ptr[esp - qword]
pshuflw xmm0, xmmword ptr[esp - xmmword], 00011011b
Wir stellen den Zustand wieder her 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
.
, - .