Reputation: 69
I have this code in FASM that calculates a measurement using the FPU that works great in 32 bit programs. How would I convert it so it would run in 64 bit program. when I use this code in the 64 bit program it gives me 0.00000 instead of a number like 54.24457 I think it is something with the FPU instructions but I don't know enough about assembly or 64 bit programming to get it to work
macro calculateresultlengthX {
;calculate result length x
;formula is resultlengthX = resultlengthXpixelstextbox / MeasuredlengthXpixelstextbox * MeasuredlengthXtextbox
;read in resultlengthXinpixelstextbox
invoke GetDlgItemTextA, [hwnd], resultlengthxpixelstextbox, bufferbuffer1, 100
cinvoke sscanf, bufferbuffer1, "%f", buffer1
;read in MeasuredlengthXinpixelstextbox
invoke GetDlgItemTextA, [hwnd], measuredlengthxpixelstextbox, bufferbuffer2, 100
cinvoke sscanf, bufferbuffer2, "%f", buffer2
;resultlengthXpixels / MeasuredlengthXpixels
finit
fld dword [buffer1]
fld dword [buffer2]
fdivp
fstp qword [buffer3]
cinvoke sprintf, addr buffer1, "%.16lf", dword [buffer3], dword [buffer3 + 4]
invoke SetDlgItemTextA,[hwnd],resultlengthxtextbox,addr buffer1
;read in ResultlengthXtextbox to get the temporary value
invoke GetDlgItemTextA, [hwnd],resultlengthxtextbox, bufferbuffer1, 100
cinvoke sscanf, bufferbuffer1, "%f", buffer1
;read in MeasuredlengthXtextbox
invoke GetDlgItemTextA, [hwnd],measuredlengthxtextbox, bufferbuffer2, 100
cinvoke sscanf, bufferbuffer2, "%f", buffer2
;answer * MeasuredlengthXtextbox
finit
fld dword [buffer1]
fld dword [buffer2]
fmulp
fstp qword [buffer3]
cinvoke sprintf, addr buffer1, "%.16lf", dword [buffer3], dword [buffer3 + 4]
invoke SetDlgItemTextA,[hwnd],resultlengthxtextbox,addr buffer1
}
thanks
Upvotes: 0
Views: 1623
Reputation: 58762
The calling convention for doubles in 64 bit mode uses xmm
registers, you'll have to adjust your cinvoke
lines if it even supports that. Otherwise just use manual code, something like:
lea rcx, [buffer1]
lea rdx, [format]
movsd xmm0, [buffer3]
sub rsp, 32
call sprintf
add rsp, 32
Disclaimer: I don't have windows to test.
Update: cinvoke
is a helper macro that tries to do the right thing for calling a C function. You are passing the double in two parts, which might work for a stack-based calling convention, but in 64 bit mode registers are used to pass arguments. For doubles you need to use xmm
registers. The cinvoke
macro might know how to do that, but you certainly need to help it by telling it you want to pass a double. The code I posted is a hopefully correct calling sequence for sprintf
, as such you can use it instead of the cinvoke
.
Update #2: msdn says that for varargs functions (and sprintf
is one) floating point arguments must be duplicated in both integer and xmm registers.
Here is a complete console program multiplying 2 values using the FPU:
global main
extern scanf
extern printf
main:
sub rsp, 40 ; shadow space + stack alignment
lea rcx, [infmt]
lea rdx, [op1]
call scanf
lea rcx, [infmt]
lea rdx, [op2]
call scanf
fld dword [op1]
fld dword [op2]
fmulp
fstp qword [result]
lea rcx, [outfmt]
movsd xmm1, [result]
mov rdx, [result]
call printf
add rsp, 40
xor eax, eax
ret
section .data
op1: dd 0
op2: dd 0
result: dq 0
infmt: db "%f", 0
outfmt: db "%.16lf", 0
Note this is for nasm
but you should be able to adapt this to your needs. I have tested this using wine.
Upvotes: 1