为了账号安全,请及时绑定邮箱和手机立即绑定

在Win32上使用GCC在装配符号中添加前导下划线?

在Win32上使用GCC在装配符号中添加前导下划线?

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

3 回答

?
跃然一笑

TA贡献1826条经验 获得超6个赞

您可以使用C预处理器对程序集进行预处理,并使用宏在Windows上添加缺少的下划线。首先,您需要将程序集文件从bar.s重命名为bar.S(大写“ S”)。这告诉gcc使用cpp预处理文件。


要添加缺少的下划线,您可以定义一个宏“ 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__)



查看完整回答
反对 回复 2019-12-16
  • 3 回答
  • 0 关注
  • 508 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信