Wie wandle ich ein Integer (Dword) in eine Gleitkommazahl (Double) um?
Am einfachsten ist es, die Arbeit der FPU zu überlassen:
Nasm
BITS 32
SEGMENT .data
int32: dd 1919641698 ; Integer
int64: dq 1919641698 ; Long
SEGMENT .bss
dbl: resq 1 ; Double (Ergebnis)
SEGMENT .text
SignedInt2Double:
fninit
push dword [int32]
fild dword [esp]
add esp, 4
fstp qword [dbl]
fninit
ret
SignedLong2Double:
fninit
push dword [int64+4] ; ACHTUNG! 'push qword' geht nicht gut
push dword [int64+0]
fild qword [esp]
add esp, 8
fstp qword [dbl]
fninit
ret
UnsignedInt2Double:
fninit
push 0
push dword [int32]
fild qword [esp]
add esp, 8
fstp qword [dbl]
fninit
ret
Das erste 'fninit' ist für den Fall, dass die FPU nach der letzten Operation
nicht aufgeräumt wurde. Das zweite 'fninit' räumt die FPU auf (sinnvoll für
Programmierfehler). Beide 'fninit' können meistens weggelassen werden.
Man kann es aber auch umständlich ohne FPU machen:
Nasm
BITS 32
SEGMENT .data
int32: dd 1919641698 ; Int
SEGMENT .bss
dbl: resq 1 ; Double (Ergebnis)
SEGMENT .text
UnsignedInt2Double:
xor edx, edx
mov eax, [int32]
or eax, eax
jz .J2 ; EAX = 0
bsr ebx, eax ; erste 1 von links finden
lea edx, [ebx+1023] ; Bias
mov cl, 32 ; Anzahl Bits des Integer
sub cl, bl ; bl: Stelle der ersten 1
shl eax, cl ; nach links (führende Nullen & führende 1 löschen)
shld edx, eax, 20 ; in das Double (high) schieben (Bias nach links)
shl eax, 20 ; Double(low) anpassen
.J2:
mov [dbl], eax
mov [dbl+4], edx
ret
SignedInt2Double:
mov eax, [int32]
xor ecx, ecx ; OR-Maske Vorzeichen
or eax, eax
jz .J2 ; EAX = 0
jns .J1 ; EAX > 0
mov ecx, 100000000000b ; OR-Maske Vorzeichen
neg eax ; EAX = |EAX|
.J1:
bsr ebx, eax ; erste Eins von links finden
lea edx, [ebx+1023] ; Bias
or edx, ecx ; Vorzeichen
mov cl, 32 ; Anzahl Bits des Integer
sub cl, bl ; bl: Stelle der ersten 1
shl eax, cl ; nach links (führende Nullen & führende 1 löschen)
shld edx, eax, 20 ; in das Double (high) schieben (Bias nach links)
shl eax, 20 ; Double(low) anpassen
.J2:
mov [dbl], eax
mov [dbl+4], edx
ret
Ralph 'rkhb' Bauer Aug 2008