我有一段C代码,它调用程序集中定义的函数。举例来说,假设foo.c包含:
int bar(int x); /* returns 2x */
int main(int argc, char *argv[]) { return bar(7); }
bar.s包含x86汇编中bar()的实现:
.global bar
bar: 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调用约定的函数标识符都以下划线作为前缀,但是由于“ bar”是在程序集中定义的,因此不会获得该前缀,并且链接失败。(因此错误消息实际上是在抱怨缺少符号_bar而不是bar。)
总结一下:
% gcc -c foo.c bar.s
% nm foo.o bar.o
foo.o:
00000000 b .bss
00000000 d .data
00000000 t .text
U ___main
U _bar
00000000 T _main
bar.o:
00000000 b .bss
00000000 d .data
00000000 t .text
00000000 T bar
现在的问题是:如何解决这个问题?如果仅针对Windows编写,则可以在bar.s的标识符中添加下划线,但是在Linux上代码会中断。我已经看过gcc的-fleading-underscore和-fno-leading-underscore选项,但似乎都没有做任何事情(至少在Windows上如此)。
我现在看到的唯一替代方法是通过C预处理器传递程序集文件,并在定义WIN32的情况下手动重新定义所有声明的符号,但这也不是很漂亮。
有人对此有干净的解决方案吗?也许是我监督的编译器选项?也许GNU汇编器支持一种特定的方式,使该特定符号使用C调用约定来引用一个函数,并且应这样处理?还有其他想法吗?
跃然一笑