Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
函数和变量是否会在前面加一个“_&引用;当使用gcc编译时?_C_Gcc_Operating System_Kernel - Fatal编程技术网

函数和变量是否会在前面加一个“_&引用;当使用gcc编译时?

函数和变量是否会在前面加一个“_&引用;当使用gcc编译时?,c,gcc,operating-system,kernel,C,Gcc,Operating System,Kernel,我正在学习使用GCC在Linux环境中开发操作系统。我在Bran的内核开发中了解到,C中的所有函数和变量名在编译时都会在其相应的汇编源文件中以“3;”(下划线)开头。 但是当我浏览编译的C程序的汇编源代码时,我甚至找不到“\u main”函数。 我执行了以下操作 cpp sample.c sample.i gcc-S sample.I这在早期是正确的。给定的C函数foo将在汇编程序中显示为\u foo。这样做是为了避免与手动生成的.s文件发生冲突 它也将被限制为总共8个字符[链接器限制] 几十年

我正在学习使用GCC在Linux环境中开发操作系统。我在Bran的内核开发中了解到,C中的所有函数和变量名在编译时都会在其相应的汇编源文件中以“3;”(下划线)开头。 但是当我浏览编译的C程序的汇编源代码时,我甚至找不到“\u main”函数。 我执行了以下操作

cpp sample.c sample.i


gcc-S sample.I

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

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

几十年来都不是这样。现在,符号不再以
作为前缀,长度可以超过8个字符


更新:


那么,现在GCC不会在函数和变量前面生成一个uu

在大多数情况下,不。依我看,你在这一点上引用的参考文献确实有点过时了

大多数POSIX系统(例如linux,*BSD)使用
gcc
[或
clang
]并且它们不使用
\uuuuu

当我第一次开始用C语言编程时[circa 1981],
\uu
仍在使用。这是在AT&T Unix v7、System III和System V上实现的

IIRC,在20世纪90年代早期,对于较新的系统(如linux),它已经消失了。就我个人而言,从那时起我就没有遇到过
前缀,但我[主要]使用linux[有时使用cygwin]

一些AT&T Unix衍生系统可能为了向后兼容而保留了它,但最终,大多数人都将其标准化为“foo即foo”。我没有访问OSX的权限,所以我不能排除Johnathan对此的评论

自Unix早期(大约1970年)起,
就一直存在。这是在我的时代之前,但是,IIRC,Unix最初是用汇编语言编写的。它被转换为C。
\uuu
用于划分用C编写的函数,或者可以从C函数调用的asm函数

那些没有前缀的是“仅限asm”[因为他们可能使用了非标准的呼叫约定]。回到过去,一切都是宝贵的:RAM、CPU周期等等

因此,asm函数可以/将使用“技巧”来节约资源。几个asm函数可以作为一个组工作,因为它们相互了解

如果可以从C调用给定的asm函数,则前缀符号是与C兼容的“包装器”[在prolog/epilog中进行了额外的保存/恢复]


所以,我可以把C程序的主函数称为“call main”而不是“call\u main”

这是一个相当安全的赌注

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

只有当试图从手工生成的汇编程序调用C函数时,问题才可能出现

因此,对于asm,我只需要做一件简单的事情,然后调用main。它将适用于大多数(如果不是所有)系统

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

但是,我认为这太过分了


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

正如Craig所详述的,像COFF和ELF这样的现代格式/ABI不再遵循惯例

在一些使用不同ABI的目标上,它仍然在使用。 例如NeXT/OS X或16位和32位Windows。64位Windows不再使用下划线(尽管GCC在4.5.1之前一直在使用下划线)

此外,下划线可能显示为较大前缀的一部分。例如,
\u declspec(dllimport)
符号中的
\u导入
,或安腾ABI中的
\u Z

如果您出于某种原因需要影响损坏,GCC将提供一个标志。这将破坏ABI兼容性


一些链接:

  • 阿格纳·福格
  • 陈雷蒙
  • 关于维基百科

您可以编译用户空间程序。“内核”标签与该问题的关系如何?请使用最新的工具/软件资源。这至少取决于平台。在Mac OS X上,如果我编译一个C源文件
any_function.C
,其中包含函数
any_function()
,则目标文件包含一个符号
\u any_function
,根据
nm-g any_function.o
。因此,现在GCC不会在函数和变量ri8之前生成一个u,我可以直接将C程序的主函数调用为“call main”而不是“call_main”ri8?@JonathanLeffler我被吓了一跳。
\uu
前缀一直是一个很难处理的问题,[回到过去]我很高兴看到它被删除了[大约是ELF的介绍,等等]。尽管如此,OSX总是有一些类似的怪癖。
objdump
是否报告相同的情况?它是否依赖于
.o
格式(例如COFF、ELF或OSX使用的任何东西)?
objdump任何函数。o
在Mac OS X上生成
-bash:objdump:command not found
:)-是的,Mac OS X按照自己的方式进行操作,并且不使用COFF或ELF(文件类型是
Mach-o 64位对象x86\u 64
)。
#ifdef C_USES_UNDERSCORE
#define CF(_x)          _##_x
#else
#define CF(_x)          _x
#endif

    call    CF(main)