如何在装配中使用浮点数操作?

时间:2015-11-15 03:14:40

标签: c assembly floating-point x86 masm

我需要从C发送两个实数(使用extern'C'double(double num1,double num2 ))到程序集过程,它返回添加的这些数字。我还不知道该怎么做。

我尝试了这个,但它没有用。

.data

 res dq 0

.code

        procSuma proc num1,num2

           fld num1   ; load num1 and push it onto the fpu stack
           fld num2   ; load num2 and push it onto the fpu stack
           faddp      ; pop two numbers, add them, push sum on the stack
           fstp res   ; pop sum from the stack and store it in res

        procSuma endp
 end

2 个答案:

答案 0 :(得分:2)

你出错的地方是你把原来没有包含在函数中的粘贴代码复制到函数中,我相信你从这里得到了。 Adding floating point/double numbers in assembly

由于汇编代码现在包含在proc中,因此不再需要变量来存储结果,因为结果存储在堆栈中st(0)的地址,这将是您的返回值。当调用fstp时,它会弹出堆栈(提示:末尾的p),因此存储在st(0)的返回值不再有效。删除fstp设置将为您提供预期的结果。

这是代码正在执行的步骤。

procSuma proc num1,num2   

       fld num1   ; This pushes num1 onto the stack at the address of st(0)
       fld num2   ; This pushes num2 onto the stack at the address of st(1)
       faddp      ; This multiplies st(1) and st(0), stores the result at st(0), and then pops the variable stored at st(1) off the stack   
       fstp res   ; !REMOVE THIS. This is why you aren't getting the expected result.It pops the variable in st(0) off the stack, which is your return value.

procSuma endp

答案 1 :(得分:2)

我假设这是一项要求您使用x87 FPU指令的家庭作业。或者,您可以使用SSE / SSE2 SIMD指令来执行添加。

Win32上的

C 调用(cdecl)约定要求在 ST(0)中返回单精度和双精度浮点数(在FPU顶部注册)堆)。由于faddp添加了两个数字并将结果放在 ST(0)中,这意味着我们不需要任何临时变量来存储结果。然后可以删除这些行

.data
res dq 0

fstp res   ; pop sum from the stack and store it in res

创建过程时,您应指定要传递的参数的大小,以便 MASM 确切知道操作数的操作数大小。为确保使用双精度值,将 double 参数标记为REAL8(8字节REALS)。您还应该将PROC标记为使用带有PROC C的C调用约定,以便正确设置和寻址堆栈和参数。程序声明应如下所示:

procSuma proc C num1:REAL8,num2:REAL8 

生成的代码可能如下所示:

.model flat, c
.code

        procSuma proc C num1:REAL8,num2:REAL8

           fld num1   ; load num1 and push it onto the fpu stack
           fld num2   ; load num2 and push it onto the fpu stack
           faddp      ; pop two numbers, add them, push sum on the stack.
                      ; result in st(0) (top of FPU stack)
                      ; We return double values in st(0) so nothing to do
                      ; since faddp put our result in st(0)
           ret

        procSuma endp
 end

您可以使用 FADD 代替 FADDP 来减少对几条指令的添加:

       fld num1   ; load num1 and push it onto the fpu stack
       fadd num2  ; Add ST(0)(num1) to num2 and store result in ST(0).
                  ; We return double values in st(0) so nothing to do
                  ; since fadd put our result in st(0)