我在FASM中有这个代码,它使用在32位程序中运行良好的FPU计算测量值。我将如何转换它以便它将在64位程序中运行。当我在64位程序中使用这个代码时,它给我0.00000而不是像54.24457这样的数字我觉得它是FPU指令的东西,但是我对组装或64位编程知之甚少以使它工作
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
}
感谢
答案 0 :(得分:1)
64位模式下双精度调用约定使用xmm
寄存器,如果它甚至支持,你必须调整cinvoke
行。否则只需使用手动代码,例如:
lea rcx, [buffer1]
lea rdx, [format]
movsd xmm0, [buffer3]
sub rsp, 32
call sprintf
add rsp, 32
免责声明:我没有窗户可供测试。
更新:cinvoke
是一个帮助宏,它尝试为调用C函数做正确的事情。您将两部分传递给两个部分,这可能适用于基于堆栈的调用约定,但在64位模式下,寄存器用于传递参数。对于双打,您需要使用xmm
个寄存器。 cinvoke
宏可能知道如何做到这一点,但你肯定需要通过告诉它想要传递双精度来帮助它。我发布的代码是sprintf
的正确调用序列,因此您可以使用它代替cinvoke
。
更新#2 :msdn says对于varargs函数(并且sprintf
为1),浮点参数必须在整数和xmm寄存器中重复。
这是一个完整的控制台程序,使用FPU乘以2个值:
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
请注意这是nasm
,但您应该能够根据自己的需要进行调整。我用葡萄酒测试了这个。