问题描述
我正在使用GCC在Linux环境中学习OS开发.我在Bran的内核开发中了解到,编译时C中的所有函数和变量名称在其相应的Assembly源文件中均带有"_"(下划线).但是,当我浏览已编译的C程序的汇编源代码时,我什至找不到"_main"函数.我执行了以下操作.
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
cpp sample.c sample.i
gcc -S样本.I
gcc -S sample.I
推荐答案
在早期,情况就是如此.给定的C函数foo
在汇编器中将显示为_foo
.这样做是为了避免与手工生成的.s
文件发生冲突.
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.
它也将总共限制为8个字符[链接器限制].
It would also be limited to 8 characters total [a linker restriction].
这已经不是几十年了.现在,符号不再以_
为前缀,并且可以超过8个字符.
This hasn't been true for decades. Now, symbols are no longer prefixed with _
and can be much longer than 8 characters.
更新:
在大多数情况下,没有. IMO,在这一点上,您引用的参考文献似乎有些过时了.
For the most part, no. IMO, the reference you're citing, on this point, does seem to be a bit dated.
大多数POSIX系统(例如linux,* BSD)使用gcc
[或clang
],而忽略了_
.
Most POSIX systems (e.g. linux, *BSD) use gcc
[or clang
] and they leave off the _
.
当我第一次使用C语言编程时(大约在1981年),_
仍在使用.这是在AT& T Unix v7,System III和System V上进行的.
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,在1990年代初期,它不再适用于较新的系统(例如linux).就我个人而言,从那时起我再也没有遇到_
前缀,但是我[主要]使用linux [有时是cygwin].
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].
某些AT& T Unix派生系统可能为了向后兼容而保留了它,但是最终,大多数人都将"foo is foo"标准化.我没有OSX的访问权限,因此不能排除Johnathan对此的评论.
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.
_
自Unix的早期(大约1970年)就出现了.这是我之前的工作,但是IIRC,Unix最初是用汇编程序编写的.它被转换为C._
旨在区分用C编写的函数或可以从C函数调用的asm函数.
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.
那些没有前缀的是仅asm"(因为它们可能使用了非标准的调用约定).过去,一切都很宝贵:RAM,CPU周期等.
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.
因此,asm函数可以/将使用技巧"来节省资源.几个asm职能可以作为一个小组一起工作,因为他们彼此了解.
So, asm functions could/would use "tricks" to conserve resources. Several asm functions could work as a group because they knew about one another.
如果可以从C调用给定的asm函数,则_
前缀符号是C兼容的包装器"(在prolog/epilog中进行了额外的保存/恢复).
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].
这是一个相当安全的选择.
That's a reasonably safe bet.
如果您正在使用C调用给定的函数,它将自动执行正确的操作(即是否添加前缀).
If you're calling a given function from C, it will automatically do the right thing (i.e. add prefix or not).
仅当尝试从手工生成的汇编器调用C函数时,问题可能甚至出现.
It's only when trying to call a C function from hand generated assembler that the issue might even come up.
所以,对于asm,我只做简单的事情,然后做call main
.它可以在大多数[如果不是全部]系统上使用.
So, for asm, I'd just do the simple thing and do call main
. It will work on most [if not all] systems.
如果您想对项目符号进行验证",您可以可以通过C预处理程序(通过.S
文件)运行asm并执行(例如):
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.
它也说明了_
前缀问题的整个问题.在具有大量内存和CPU周期的现代系统上,为什么汇编器函数必须知道它正在调用的ABI兼容函数是从C还是手写汇编器生成的?
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编译时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!