添加前导下划线组装与符号在Win32 GCC? [英] Adding leading underscores to assembly symbols with GCC on Win32?

查看:262
本文介绍了添加前导下划线组装与符号在Win32 GCC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一块C code,它调用组件定义的函数。举例来说,假设foo.c的包括:

I have a piece of C code that calls a function defined in assembly. By way of example, let's say foo.c contains:

int bar(int x);  /* returns 2x */
int main(int argc, char *argv[]) { return bar(7); }

和bar.s包含x86汇编栏()的实现:

And bar.s contains the implementation of bar() in x86 assembly:

.global bar
bar:    movl 4(%esp), %eax
        addl %eax, %eax
        ret

在Linux上,我可以很容易地编译和链接GCC这些来源如下:

On Linux I can easily compile and link these sources with GCC as follows:

% gcc -o test foo.c bar.s
% ./test; echo $?
14

在Windows上使用MinGW这个失败的未定义参考`吧'的错误。事实证明,这样做的原因是在Windows上使用C调用约定的函数的所有标识符都是使用下划线pfixed $ P $,但由于栏中的组装的​​定义,它不会得到这个preFIX和链接失败。 (这样的错误消息其实是在抱怨缺少符号_bar,不是吧。)

On Windows with MinGW this fails with an error of "undefined reference to `bar'". It turns out the cause for this is that on Windows all identifiers of functions with C calling convention are prefixed with an underscore, but since "bar" is defined in assembly, it doesn't get this prefix and linking fails. (So the error message is actually complaining about missing the symbol _bar, not 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上的code休息。我已经看过gcc的 -fleading下划线 -fno领先的下划线选项,但它们似乎也没有做任何事情(至少在Windows上)。

The question now is: how can I resolve this nicely? If I were writing for Windows only, I could just add the underscore to the identifier in bar.s, but then the code breaks on Linux. I have looked at gcc's -fleading-underscore and -fno-leading-underscore options but neither appears to do anything (at least on Windows).

唯一的选择我看到现在传递汇编文件通过C preprocessor并手动重新定义所有声明的符号,如果WIN32定义,但要么不是很pretty。

The only alternative I see now is passing the assembly file through the C preprocessor and redefining all the declared symbols manually if WIN32 is defined, but that's not very pretty either.

有没有人有这样一个干净的解决方案?也许一个编译器选项我监督?也许GNU汇编程序支持一种特定的,这个特殊的符号是指使用C调用约定,应损毁,这样的功能?任何其他的想法?

Does anyone have a clean solution for this? Perhaps a compiler option I oversaw? Maybe the GNU assembler supports a way to specific that this particular symbol refers to a function using C calling convention and should be mangled as such? Any other ideas?

推荐答案

一个选项,虽然危险,是说服GCC省略ABI要求的下划线。

One option, though dangerous, is to convince GCC to omit the ABI-required leading underscore.


      
  • <一个href=\"http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/$c$c-Gen-Options.html#index-fleading%5F002dunderscore-1989\"><$c$c>-fleading-underscore

这个选项及其对应, -fno领先的下划线,强行改变中c符号重新在目标文件中psented $ P $。一种用途是帮助与传统组装code链接。

This option and its counterpart, -fno-leading-underscore, forcibly change the way C symbols are represented in the object file. One use is to help link with legacy assembly code.

警告: -fleading下划线开关使GCC产生code,是不是与产生code二进制兼容的没有这种开关。用它来符合非默认应用程序二进制接口。并非所有的目标提供了这个开关的完整支持。

Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch.

另外,更安全的选择,就是明确地告诉GCC使用的名称。

Another, safer option, is to explicitly tell GCC the name to use.

您可以指定写 ASM (或 __ asm__在汇编code的C函数或变量中使用的名称)的声明符之后的关键字如下:

5.39 Controlling Names Used in Assembler Code

You can specify the name to be used in the assembler code for a C function or variable by writing the asm (or __asm__) keyword after the declarator as follows:

     int foo asm ("myfoo") = 2;

这指定要使用的名称在汇编code变量应该是\\ myfoo`',而不是通常\\ _foo`。

This specifies that the name to be used for the variable foo in the assembler code should be \myfoo`' rather than the usual \_foo`'.

在下划线通常$ ppended到C函数或变量的名称p $系统,该功能允许您为不以下划线开头的链接定义名称。

On systems where an underscore is normally prepended to the name of a C function or variable, this feature allows you to define names for the linker that do not start with an underscore.

这没有意义使用此功能与非静态局部变量,因为这样的变量没有汇编程序的名字。如果你试图把变量在一个特定的寄存器中,看到的明确注册瓦尔。 GCC presently接受这样的code。与警告,但可能会被改为发出一个错误,而不是警告,在未来的。

It does not make sense to use this feature with a non-static local variable since such variables do not have assembler names. If you are trying to put the variable in a particular register, see Explicit Reg Vars. GCC presently accepts such code with a warning, but will probably be changed to issue an error, rather than a warning, in the future.

您不能在一个函数的定义的使用 ASM 以这种方式;但是你可以通过它的定义之前写的函数的声明,并把获得同样的效果 ASM 有,是这样的:

You cannot use asm in this way in a function definition; but you can get the same effect by writing a declaration for the function before its definition and putting asm there, like this:

 extern func () asm ("FUNC");

 func (x, y)
      int x, y;
 /* ... */


  
  

这是由你来确保你选择的汇编程序名称不与任何其他汇编符号冲突。此外,您不能使用寄存器名;这将产生完全无效的汇编code。 GCC不作为尚未有在寄存器中存储静态变量的能力。也许这将被添加。

It is up to you to make sure that the assembler names you choose do not conflict with any other assembler symbols. Also, you must not use a register name; that would produce completely invalid assembler code. GCC does not as yet have the ability to store static variables in registers. Perhaps that will be added.

在你的情况,

extern int bar(int x) asm("bar");

应该告诉GCC的使用ASM名\\ `栏,即使它是一个ccall功能

should tell GCC that "bar uses asm name \`bar', even though it's a ccall function".

这篇关于添加前导下划线组装与符号在Win32 GCC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆