[英]C/C++ Importing WinAPI function with x64 structure parameter inside x86 application
[英]Underscore prefix problem in x86: Calling NASM function from C++ function works in x64 but fails in x86
我在 Windows 10 中使用 Visual Studio 2019,我想使用 MSVC(平台工具集 142)和 NASM(版本 2.14.02)在 x86 中編譯下一個代碼:
foo.asm
section .text
global foo
foo:
mov eax, 123
ret
主文件
extern "C" int foo(void);
int main()
{
int x = foo();
return 0;
}
但我得到了錯誤:
在 x64 中運行良好,在 x86 中,生成的文件 main.obj 將前導下划線添加到 function 名稱 foo,從而產生 _foo。 這在 x64 中不會發生,但會將符號保留為 foo,而不是 _foo。
那么,是否有任何適用於 x86 和 x64 平台的解決方案(最好不修改源代碼,也許是一些用於 MSVS 編譯器的編譯器/鏈接器標志)?
我真的很感激任何幫助。
_
前綴是名稱修改的結果,這取決於目標平台 ABI(操作系統、位數、調用約定)。
根據微軟的說法, _
前綴用於 32 位 Windows cdecl
調用約定,但不在 64 位( 來源):
C 修飾名稱的格式
C function 的裝飾形式取決於其聲明中使用的調用約定,如下表所示。 這也是在聲明 C++ 代碼具有外部“C”鏈接時使用的裝飾格式。 默認調用約定是 __cdecl。 請注意,在 64 位環境中,函數沒有修飾。
調用約定——裝飾
__cdecl
前導下划線 (_
)
__stdcall
前導下划線 (_
) 和尾隨 at 符號 (@
),后跟十進制參數列表中的字節數
__fastcall
前導和尾隨符號 (@
) 后跟一個十進制數,表示參數列表中的字節數
__vectorcall
兩個結尾的 at 符號 (@@
),后跟參數列表中的十進制字節數
背后的原因可能是 32/64 位 Windows 調用約定並不真正兼容。 例如,64 位模式下的 function arguments 的傳遞方式不同,並且在調用之間必須保留不同的寄存器。
無論如何,要回答這個問題,我可以想到幾個解決方案:
解決方案 1
生成.asm
的代碼應僅在 32 位模式下添加前導_
(生成的程序集可能也必須在其他方面有所不同,尤其是在涉及指針的情況下)。
解決方案 2
使用預處理器在 64 位模式下添加前導_
:
#ifdef _WIN64
# define foo _foo
#endif
extern "C" int foo(void);
int main()
{
int x = foo();
return 0;
}
正確的解決方案是為每個架構使用不同的 asm 文件:x86、amd64 等,因為您將使用不同的匯編指令集。 而 select 將由 make 文件或環境配置編譯哪個文件取決於構建體系結構。 因此,您可以使用 '_foo' function 名稱作為 x86 和 'foo' 作為 x86_64
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.