簡體   English   中英

Underscore prefix problem in x86: Calling NASM function from C++ function works in x64 but fails in x86

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM