我正在Windows 10中使用Visual Studio 2019,并且我想使用下一个代码的MSVC(平台工具集142)和NASM(版本2.14.02)在x86中进行编译:
foo.asm

section .text

global foo
foo:
    mov eax, 123
    ret
main.cpp
extern "C" int foo(void);

int main()
{
    int x = foo();
    return 0;
}
但是我得到了错误:
c++ - x86中的下划线前缀问题:从C++函数调用NASM函数在x64中有效,但在x86中失败-LMLPHP
在x64中运行良好,在x86中,生成的文件main.obj在函数名称foo前面添加了下划线,结果为_foo。在x64中不会发生这种情况,但是会将符号保留为foo,而不是_foo。
那么,是否有任何解决方案既可用于x86平台,又可用于x64平台(最好不修改源代码,或者为MSVS编译器提供一些编译器/链接器标志)?
我非常感谢您的帮助。

最佳答案

_前缀是名称处理的结果,该名称处理取决于目标平台ABI(操作系统,位,调用约定)。
根据Microsoft的说法,_前缀用于32位Windows cdecl调用约定中,而不用于64位(source):

背后的原因可能是32/64位Windows调用约定并非真正兼容。例如,64位模式下的函数参数以不同的方式传递,并且在两次调用之间必须保留不同的寄存器。
无论如何,要回答这个问题,我可以想到几个解决方法:
解决方案1 ​​
生成.asm的代码应仅在32位模式下添加前导_(生成的程序集可能也必须在其他方面有所不同,尤其是在涉及指针的情况下)。
解决方案2
使用预处理器以64位模式添加前导_:

#ifdef _WIN64
#  define foo _foo
#endif

extern "C" int foo(void);

int main()
{
    int x = foo();
    return 0;
}

关于c++ - x86中的下划线前缀问题:从C++函数调用NASM函数在x64中有效,但在x86中失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62753691/

10-11 12:17