我有一段C代碼,它調(diào)用程序集中定義的函數(shù)。舉例來說,假設(shè)foo.c包含:int bar(int x); /* returns 2x */int main(int argc, char *argv[]) { return bar(7); }bar.s包含x86匯編中bar()的實現(xiàn):.global barbar: movl 4(%esp), %eax addl %eax, %eax ret在Linux上,我可以輕松地通過GCC編譯和鏈接這些源,如下所示:% gcc -o test foo.c bar.s% ./test; echo $?14在具有MinGW的Windows上,此操作將失敗,并顯示“未定義對'bar'的引用”錯誤。事實證明,這是因為在Windows上,所有具有C調(diào)用約定的函數(shù)標識符都以下劃線作為前綴,但是由于“ bar”是在程序集中定義的,因此不會獲得該前綴,并且鏈接失敗。(因此錯誤消息實際上是在抱怨缺少符號_bar而不是bar。)總結(jié)一下:% gcc -c foo.c bar.s% nm foo.o bar.ofoo.o:00000000 b .bss00000000 d .data00000000 t .text U ___main U _bar00000000 T _mainbar.o:00000000 b .bss00000000 d .data00000000 t .text00000000 T bar現(xiàn)在的問題是:如何解決這個問題?如果僅針對Windows編寫,則可以在bar.s的標識符中添加下劃線,但是在Linux上代碼會中斷。我已經(jīng)看過gcc的-fleading-underscore和-fno-leading-underscore選項,但似乎都沒有做任何事情(至少在Windows上如此)。我現(xiàn)在看到的唯一替代方法是通過C預(yù)處理器傳遞程序集文件,并在定義WIN32的情況下手動重新定義所有聲明的符號,但這也不是很漂亮。有人對此有干凈的解決方案嗎?也許是我監(jiān)督的編譯器選項?也許GNU匯編器支持一種特定的方式,使該特定符號使用C調(diào)用約定來引用一個函數(shù),并且應(yīng)這樣處理?還有其他想法嗎?
3 回答

智慧大石
TA貢獻1946條經(jīng)驗 獲得超3個贊
您可以使用C預(yù)處理器對程序集進行預(yù)處理,并使用宏在Windows上添加缺少的下劃線。首先,您需要將程序集文件從bar.s重命名為bar.S(大寫“ S”)。這告訴gcc使用cpp預(yù)處理文件。
要添加缺少的下劃線,您可以定義一個宏“ cdecl”,如下所示:
#if defined(__WIN32__)
# define cdecl(s) _##s
#else
# define cdecl(s) s
#endif
然后像這樣使用它:
.global cdecl(bar)
cdecl(bar):
movl 4(%esp), %eax
addl %eax, %eax
ret
請注意,Mac OSX還需要前劃線,因此您可以像這樣更新宏的第一行:
#if defined(__WIN32__) || defined(__APPLE__)
- 3 回答
- 0 關(guān)注
- 829 瀏覽
添加回答
舉報
0/150
提交
取消