C语言与ELF机器语言之间的关系

本文探讨了C语言如何提供高效且精确的控制能力,并保持良好的可移植性。此外,文章详细介绍了C语言源码与ELF文件之间的关联,包括编译过程中变量与函数如何转换为汇编代码中的符号,以及这些符号如何被赋予特定的类型和大小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C语言对机器模型的抽象层次,恰到好处。

C语言使得开发者,刚好从最底层的费力低效的汇编编程中解脱出来,而又没有进一步往上层做抽象。
这样一来既大大提高了开发效率,又不失对程序行为的精确控制能力,还使程序获得了良好的可移植性。可谓一举三得。

同时,基本C库的理念,也是只做确定正确的事。他所提供的,大体都是最小粒度的几乎不会有变数的基础例程。

不过,本文是要谈一谈C源码与ELF之间的一些联系。


C语言中的各种概念,最终都要转换成汇编层次的概念,进而变成实际可运行的机器码。
C语言中的运算符,编译时转换成运算指令,变量类型决定运算操作的数字宽度,引用结构体成员转换成相应的内存操作的偏移。
C代码经过编译,变量与函数,变成了汇编代码中的符号。
汇编代码再经汇编器变成目标文件,即elf文件(当然,可执行文件、动态库、内核模块,也是ELF文件)。

在elf这个层次,一个符号就相当于是给某个地址起了个名字。
不过,编译器编译C代码,生成的汇编代码中,为C中定义的符号,指定了type(并不是C语言中的类型,而是data or code)和size。
这就保存了更多的信息。这样一来,通过nm工具就可以查看符号的大小了。
但是,通过链接脚本中简单赋值创建的符号(例如,__bss_start = .;),并没有大小信息。

由于每一个C文件的编译是孤立的进行的,因此编译器遇到C代码中引用一个外部的变量或函数时,编译器就认为这是在引用一个外部符号。
编译器只是标识一下,这个外部符号的地址需要在链接时确定其实际的地址。
至于C代码中描述自己引用的是什么东东,编译器并不能判断是不是确实如此。因为编译器也不知道那个符号到底是什么样以及在哪里。
所以,对于外部的符号(不管是变量、函数,还是诸如__bss_start等系统符号),把他当成什么声明,怎么访问,完全是C代码说了算。
至于编译器,只能根据C代码声明的引用方式,生成对此符号地址的各种操作指令。


另外需要说明的是,当nm工具显示一个符号的类型为T时,只能说明符号所在section为code/text section,并不表示此符号一定位于名为.text的这个section。

同样,当nm显示一个符号的类型为D时,只能说明符号所在section为data section,并不表示此符号一定位于名为.data的这个section。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值