函数和变量是否以“_"开头?使用 gcc 编译时? [英] Will the functions and variables precede with an "_" when compiled using gcc?
问题描述
我正在使用 GCC 在 Linux 环境中学习操作系统开发.我在 Bran 的内核开发中了解到,编译时 C 中的所有函数和变量名称在其相应的汇编源文件中都以_"(下划线)开头.但是当我浏览一个编译好的C程序的汇编源代码时,我什至找不到_main"函数.我执行了以下操作.
cpp 示例.c 示例.i
gcc -S 样本.I
早期确实如此.给定的 C 函数 foo
将在汇编器中显示为 _foo
.这样做是为了避免与手动生成的 .s
文件发生冲突.
它也将被限制为总共 8 个字符[链接器限制].
几十年来,情况并非如此.现在,符号不再以 _
为前缀,并且可以超过 8 个字符.
更新:
<块引用>那么,现在的 GCC 不会在函数和变量前面产生 _ 吗?
在大多数情况下,不会.IMO,您引用的参考文献,在这一点上似乎有点过时了.
大多数 POSIX 系统(例如 linux、*BSD)使用 gcc
[或 clang
] 并且它们省略了 _
.
当我第一次开始用 C 编程时 [大约 1981 年],_
仍在使用中.这是在 AT&T Unix v7、System III 和 System V 上运行的.
IIRC,它在 1990 年代初期已用于较新的系统(如 linux).就我个人而言,从那以后我就再也没有遇到过 _
前缀了,但我 [大部分] 使用过 linux [有时也使用 cygwin].
一些 AT&T Unix 派生系统可能会保留它以实现向后兼容性,但最终,大多数人都将其标准化为foo is foo".我无法访问 OSX,所以我不能排除 Johnathan 对此的评论.
_
自 Unix 早期(大约 1970 年)就已经存在.这是在我之前,但是,IIRC,Unix 最初是用汇编程序编写的.它被转换为 C._
用于划分用 C 编写的函数,或者可以从 C 函数调用的 asm 函数.
那些没有前缀的是asm only"[因为他们可能使用了非标准的调用约定].在过去,一切都很宝贵:RAM、CPU 周期等.
因此,asm 函数可以/将使用技巧"来节省资源.多个 asm 函数可以作为一个组工作,因为它们彼此了解.
如果可以从 C 调用给定的 asm 函数,则以 _
为前缀的符号是它的 C 兼容包装器"[在 prolog/epilog 中进行额外的保存/恢复].p><块引用>
那么,我可以将 C 程序的 main 函数调用为call main"而不是call _main"吗?
这是一个相当安全的赌注.
如果您从 C 中调用给定函数,它会自动执行正确的操作(即是否添加前缀).
只有在尝试从手动生成的汇编程序调用 C 函数时,才会出现问题可能.
所以,对于 asm,我只需做简单的事情并执行 call main
.它适用于大多数 [如果不是全部] 系统.
如果您想对您的代码进行防弹",您可以通过 C 预处理器(通过 .S
文件)运行您的 asm 并执行(例如):
#ifdef C_USES_UNDERSCORE#define CF(_x) _##_x#别的#define CF(_x) _x#万一呼叫 CF(主)
但是,我认为这太过分了.
它还说明了 _
前缀的整个问题.在现代系统 [有大量内存和 CPU 周期] 上,为什么汇编程序函数必须知道它正在调用的 ABI 兼容函数是由 C 或手写汇编程序生成的?
I am learning OS development in a Linux environment using GCC. I learnt in Bran's Kernel Development that all the functions and variable names in C when compiled precedes with an "_"(underscore) in its corresponding Assembly source file. But when I went through the assembly source of a compiled C program, I can't even find the "_main" function. I performed the following.
cpp sample.c sample.i
gcc -S sample.I
That was true in the early days. A given C function foo
would show up as _foo
in the assembler. This was done to avoid conflicts with hand generated .s
files.
It would also be limited to 8 characters total [a linker restriction].
This hasn't been true for decades. Now, symbols are no longer prefixed with _
and can be much longer than 8 characters.
UPDATE:
So, Nowadays GCC does not produce a _ in front of functions and variables?
For the most part, no. IMO, the reference you're citing, on this point, does seem to be a bit dated.
Most POSIX systems (e.g. linux, *BSD) use gcc
[or clang
] and they leave off the _
.
When I first started programming in C [circa 1981], the _
was still being used. This was on AT&T Unix v7, System III, and System V.
IIRC, it was gone by the early 1990s for newer systems (like linux). Personally, I haven't encountered the _
prefix since then, but I've [mostly] used linux [and sometimes cygwin].
Some AT&T Unix derived systems may have kept it around for backward compatibility, but, eventually, most everybody standardized on "foo is foo". I don't have access to OSX, so I can't rule out Johnathan's comment regarding that.
The _
had been around since the early days of Unix (circa 1970). This was before my time, but, IIRC, Unix was originally written in assembler. It was converted to C. The _
was to demarcate functions either written in C, or asm ones that could be called from C functions.
Those that didn't have the prefix were "asm only" [as they may have used non-standard calling conventions]. Back in the day, everything was precious: RAM, CPU cycles, etc.
So, asm functions could/would use "tricks" to conserve resources. Several asm functions could work as a group because they knew about one another.
If a given asm function could be called from C, the _
prefixed symbol was the C compatible "wrapper" for it [that did extra save/restore in the prolog/epilog].
So, I can just call the main function of a C program as "call main" instead of "call _main"?
That's a reasonably safe bet.
If you're calling a given function from C, it will automatically do the right thing (i.e. add prefix or not).
It's only when trying to call a C function from hand generated assembler that the issue might even come up.
So, for asm, I'd just do the simple thing and do call main
. It will work on most [if not all] systems.
If you wanted to "bullet proof" your code, you could run your asm through the C preprocessor (via a .S
file) and do (e.g.):
#ifdef C_USES_UNDERSCORE
#define CF(_x) _##_x
#else
#define CF(_x) _x
#endif
call CF(main)
But, I think that's overkill.
It also illustrates the whole problem with the _
prefix thing. On a modern system [with lots of memory and CPU cycles], why should an assembler function have to know whether an ABI compatible function it is calling was generated from C or hand written assembler?
这篇关于函数和变量是否以“_"开头?使用 gcc 编译时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!