使用 SSE 将浮点值从 Assembler DLL 返回到 C++

Posted

技术标签:

【中文标题】使用 SSE 将浮点值从 Assembler DLL 返回到 C++【英文标题】:Returning float value from Assembler DLL to C++ using SSE 【发布时间】:2016-12-04 11:17:37 【问题描述】:

我在将浮点值从 DLL 汇编程序返回到 C++ 程序时遇到问题。我想它应该在 xmm0 寄存器中处理,我错了吗?这是主文件:

#include "stdafx.h"
#include<windows.h>
#include<iostream>
#include <cstdio>
#include <thread>
#include <vector>
using namespace std;

extern "C" float _stdcall MyProc1(float begin, float end, float x2 ,float x1, float x0);    //dll assembler

int main(int argc, _TCHAR* argv[])

    float suma=0;
    suma = MyProc1(12.75,9.3,0,0,1);
    cout << std::hex<< suma << endl;
    getchar();
    return 0;

这是我的汇编程序 DLL:

.686p
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE C:\masm32\include\windows.inc
.mmx
.xmm

.DATA
    pi dd 3.14159265358979 ; constant

.CODE

DllEntry PROC hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
    mov eax, TRUE 
    ret 
DllEntry ENDP


MyProc1 proc b:DWORD, e:DWORD, x2: DWORD, x1: DWORD, x0:DWORD 

    movss xmm0,[b]  
    ret

MyProc1 endp    

END DllEntry 

返回值为-1.#IND,为什么?

【问题讨论】:

您在函数声明中使用的浮点类型实际上使用 mm0 寄存器作为返回值,但 xmm 寄存器完全不同,可能您应该使用类型 __m128 而不是浮点来声明您的函数 @arash 在 x86 上没有使用 MMX 寄存器 (mm*) 来传递或返回值的调用约定。要么使用 x87 浮点堆栈,要么使用 SSE 寄存器。 stdcall 非常具体。浮点数在 FPU 堆栈的顶部返回。您可以在函数中使用 SSE 指令,但最终浮点结果必须加载到 FPU 堆栈的顶部。在这个简单的情况下,movss xmm0,[b] 应该替换为 fld [b] 假设您在 xmm0 中有一个值(以 mov [b] 到 xmm0 为例),并且您想将一个 32 位浮点数(单个标量)放在您的 FPU 堆栈的顶部可以在 CPU 堆栈上分配空间,将 32 位值存储到堆栈位置,然后将其加载到 FPU 堆栈的顶部。例如:movss xmm0, [b]push eaxmovss dword ptr [esp], xmm0fld dword ptr [esp]pop eaxret。推送可以是任何 32 位易失性寄存器(可以通过函数修改的寄存器)。放在堆栈上的值不相关。我们只想分配 4 个字节(你也可以使用 sub esp, 4 这是真的,就目前而言:MMX 在 80 位 x87 寄存器的低 64 位上具有别名。但是你不能简单地说它们是相同的寄存器,然后就这样。您不能同时将它们用于 MMX 和 FPU 操作。您必须发出EMMS 指令来“清除”与 MMX 一起使用的寄存器,然后才能将它们用于 x87 FPU,并且没有允许在 MMX 寄存器中返回值的调用约定,所以如果你想返回一个浮点值,您实际上必须在函数结束前调用EMMS。 @arash 【参考方案1】:

这是非常特定于编译器的,但我猜您使用的是 32 位 Microsoft 编译器。

在这种情况下,由于您已将函数定义为返回浮点数,因此您需要将结果放在浮点堆栈的顶部。

检查您的 C++ 代码的汇编输出以确定是否存在 - 您应该在函数调用后看到 fstfstp 指令。

【讨论】:

它不是特定于编译器的,而是特定于 ABI 的。至少在 Windows 上,主要的 32 位 C++ ABI 将在浮点堆栈顶部 (fp(0)) 或 xmm0/ymm0 中返回浮点值。

以上是关于使用 SSE 将浮点值从 Assembler DLL 返回到 C++的主要内容,如果未能解决你的问题,请参考以下文章

sse2浮点乘法

AVX/SSE 将浮点符号掩码转换为 __m128i

浮点向量的 SSE 缩减

如何将变量(不统一)浮点值从 C++ 传递到顶点着色器 OpenGL ES 2.0

如何将浮点值从一个蓝牙模块发送到其他模块(HC 05)

内在函数和寄存器(SSE)