c - 使用 gcc 编译时,函数和变量会以 "_"开头吗?

标签 c gcc operating-system kernel

我正在使用 GCC 在 Linux 环境中学习操作系统开发。我在 Bran's Kernel Development 中了解到,C 中的所有函数和变量名在编译时在其相应的汇编源文件中都以“_”(下划线)开头。 但是当我浏览一个已编译的 C 程序的汇编源代码时,我什至找不到“_main”函数。 我执行了以下操作。

cpp 样本.c 样本.i

gcc -S 示例.I

最佳答案

早期确实如此。给定的 C 函数 foo 在汇编程序中将显示为 _foo。这样做是为了避免与手动生成的 .s 文件发生冲突。

它也将被限制为总共 8 个字符 [链接器限制]。

几十年来情况并非如此。现在,符号不再以 _ 为前缀,并且可以超过 8 个字符。


更新:

So, Nowadays GCC does not produce a _ in front of functions and variables?

在大多数情况下,不会。 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 中进行了额外的保存/恢复]。

So, I can just call the main function of a C program as "call main" instead of "call _main"?

这是一个相当安全的赌注。

如果您从 C 调用给定函数,它会自动执行正确的操作(即是否添加前缀)。

只有在尝试从手动生成的汇编器中调用 C 函数时,问题可能才会出现。

因此,对于 asm,我只做简单的事情并执行 call main。它适用于大多数 [如果不是全部] 系统。

如果您想“防弹”您的代码,您可以通过 C 预处理器(通过 .S 文件)运行您的 asm 并执行(例如):

#ifdef C_USES_UNDERSCORE
#define CF(_x)          _##_x
#else
#define CF(_x)          _x
#endif

    call    CF(main)

但是,我认为这太过分了。

它还说明了 _ 前缀的整个问题。在现代系统 [具有大量内存和 CPU 周期] 上,为什么汇编程序函数必须知道它正在调用的 ABI 兼容函数是从 C 还是手写汇编程序生成的?

关于c - 使用 gcc 编译时,函数和变量会以 "_"开头吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38272921/

相关文章:

c++ - 针对不同操作系统编译C++静态库的建议?

具有结构成员的 C++ union 结构适用于 Clang 和 MSVC,但不适用于 GCC

operating-system - 操作系统中的 "Dispatch Latency"和 "Context Switch"有什么区别?

linux - 有没有办法将一个系统上运行的应用程序转移到另一个系统上?

将 char 转换为 unsigned int - C

c - 如何在命令行应用程序中使用 Instruments 和显示控制台

c - 二进制文件读取,在c中添加额外的字符?

c - NEON 比较

c - c中的Producer_consumer使用p线程和信号量

linux - 如果一端先于另一端关闭,Linux pipe() 会发生什么