如何在masm中将两个float变量相乘

How to multiply two float variables in masm

如何在 masm 中将两个浮点变量相乘,汇编用户输入 3.02 并将其与 0.008 相乘,然后打印它

.data 
fin dd 5.0

.code
main proc

fld fin
fmul fin  ;to multiply fin with fin 
fstp dword [eax]   ;cannot mov result in eax
call writefloat

exit 
main EndP
end main

如果您想使用 FPU,请记住它使用了一组只能从内存加载或保存到内存的堆栈寄存器。
我假设您可以自己记录 FPU 编程模型,或者使用 Intel manual 1 or, if you feel nostalgic, by reading this 387 manual from Intel dated 05/26/1987.

指令fstp dword [eax]st(0)的内容保存在eax表示的地址。这种寻址方式是一种间接寻址方式,在Intel汇编语法中一直用方括号标示。
将此与在 eax 中保存 st(0) 进行对比,它应该看起来像 fstp eax(没有括号)。
las,后者不受支持,可能是因为 FPU 支持当时无法容纳任何寄存器的 64 位和 80 位格式。


推送数据。从内存进入 FPU 堆栈,使用 fld,弹出寄存器,进入内存,使用 fstp(如果不想弹出堆栈,则使用 fst)。
要执行乘法,请使用 fmul,它有几种变体,其中一种可以使用内存操作数进行运算,并将结果直接存储在 st(0).

如果你觉得偏执,你可以在程序开始时使用 finit,该指令重置 FPU 的控制寄存器以将寄存器标记为空。
OS 应该已经以干净的状态启动您的进程。

这里有一个简单的例子:

.DATA

  A dd 5.0
  B dq 0.008

  C dd 0            ;Move into a BSS section if the assembler support it

.CODE

  finit              ;For paranoid only

  fld DWORD [A]      ;ST(0) = A
  fmul QWORD [B]     ;ST(0) = ST(0)*B = A*B
  fstp DWORD [C]     ;C = ST(0) = A*B

  mov eax, DWORD [C] ;EAX = C = A*B
  call writefloat

与今天一样,您可以将向量寄存器与标量指令一起使用。
您仍然可以在之前链接的英特尔手册中找到相关文档。

.DATA

  A dd 5.0          ;Use float
  B dd 0.008        ;Use float again, avoid cvtss2sd

  C dd 0            ;Move into a BSS section if the assembler support it

.CODE

 movss xmm0, DWORD PTR [A]    ;xmm0.f[0] = A
 mulss xmm0, DWORD PTR [B]    ;xmm0.f[0] = A * B
 movd eax, xmm0               ;eax = xmm0.f[0] = A * B
                              ;Beware, 1 extra cycle for bypass delay
 call writefloat