历史上的今天

今天是:2024年09月16日(星期一)

2021年09月16日 | Freestanding C与交叉编译器的生成原理分析

发布者:科技创客 来源: eefocus关键字:交叉编译器 手机看文章 扫描二维码
随时随地手机看文章

0 问题由来

以前也用过C51写过简单的裸机程序,但是并没有认真的考虑过其与Linux环境下一般C语言程序的不同,只是想当然地认为C是跨平台的语言,并没有考虑过C语言的标准问题。


今天在编译GCC交叉编译器时,遇到了种种问题,不得不重新考虑C语言的实现标准,否则很难清晰的了解交叉编译器的编译过程。


1 C编译器的两种实现要求

C语言标准的正式文档中明确提出了C编译器的两种实现标准:


1.1 conforming freestanding implementation

所谓的Freestanding,C编译器只需提供C语言语句的编译,外加



等基本的类型与数值范围定义头文件。


可以看出,在这种级别的编译器下写程序时,基本的printf都是不能够直接使用的。

此种实现,主要用于裸机开发,比如OS开发,bootloader,以及C库本身的开发。


1.2 conforming hosted implementation

这是一种更加全面的实现,除了包含Freestanding要求的功能外,必须包含完整的标准C库实现。这也是大多数应用程序员能接触到的环境。由于中的输入输出函数的实现需要OS系统调用的支持,Hosted编译器都是依赖于具体的操作系统而存在。


1.3 小结

可以看出,Hosted是比Freestanding更加全面的C实现要求,Hosted本身包含了Freestanding。例如Hosted的GCC实现,提供了-freestanding参数来作为Freestanding降级使用。


gcc -ffreestanding


C语言这种把语言本身和库独立对待的方式,使得它能够适应更广泛的开发环境。从单片机裸机开发到大型数据库系统,C语言的身影无处不在。


2 C语言的两种执行环境

与C语言的两种实现等级相对应,C语言的程序的执行环境也有两种,这里直接贴出C语言标准原文。


5.1.2 Execution environments

Tw o execution environments are defined: freestanding and hosted. In both cases,

program startup occurs when a designated C function is called by the execution

environment. All objects with static storage duration shall be initialized (set to their

initial values) before program startup. The manner and timing of such initialization are

otherwise unspecified. Program termination returns control to the execution

environment.


在Hosted环境下,C程序入口点必须是命名为main的函数,而且其函数原型必须符合标准。


而在Freestanding环境下,C程序的入口点没有指定的名称,由程序员自行决定。


3 C语言交叉编译器制作过程原理分析

3.1 为什么需要单独生成不同目标平台的编译器

理论上一个编译器可以通过命令行参数来编译生成各种不同平台的可执行程序。例如:


mycompiler -platform=arm-linux 1.c  # 生成可以运行在ARM平台上的Linux程序

mycompiler -platform=mips-linux 1.c # 生成可以运行在MIPS平台的Linux程序

mycompiler -platform=i386-linux 1.c # 生成可以运行在Intel X86平台的Linux程序


然而实际上,这种做法的代价是十分巨大的,因为


不同平台差异巨大,代码转换逻辑完全不同,在一个可执行程序中包含所有平台转换代码,导致编译器程序本身体积巨大


不同平台的C库实现严重依赖于平台,在一个库中包含所有平台的实现代码,造成C库体积巨大,管理混乱。


汇编器、连接器也存在同样的问题

所以在现实中,虽然GCC,GLIBC,binutils这样的项目本身能够支持很多的软硬件平台,但是支持方式是通过配置来进行选择性的编译部分源代码来生成针对具体平台二进制工具。


3.2 交叉编译器生成步骤原理分析

理论上一个C交叉编译器的生成非常简单:

(0)编译生成交叉汇编器和交叉链接器

之所以会存在这个步骤是因为,像GCC这样的C编译器本身只负责把C语言代码编译为汇编代码。把汇编代码转换为二进制机器码,以及把二进制对象文件链接为可执行文件的功能需要其他程序来实现。对Unix世界来说,提供汇编链接功能的就是著名的binutils包。


gcc编译器在生成时,需要使用binutils来测试相关功能,以动态生成各种配置与代码。所以,在编译GCC之前,必须要有可用的binutils。


对于汇编程序员来说,binutils已经提供了一个完整的汇编开发环境,完全可以停留这里享受汇编程序设计的美好。

然而,对于C程序员来说,这才刚刚开始。


(1)编译生成Freestanding的交叉编译器;

这个交叉编译器完全可以用来编译裸机C程序,编译OS,编译BootLoader,对于嵌入式底层开发者来说,这样一个编译器就足够了,完全可以到此为止。


然而对于一个在OS环境下的应用开发者来说,就需要一个功能更完整的编译器,以及完整的标准C库,这就需要进入步骤(2)。


(2)用刚生成的交叉编译器编译生成标准C库;

Freestanding编译器可以用来编译标准C库,这个是很重要的。


此时虽然编译器和C库都有了,却存在两个缺陷:


编译器可执行文件本身并不知道对应的C库的路径,所以编译程序时就需要额外的命令行参数来提供这些信息。


编译器不能提供Hosted类型C程序初始化环境,因为Hosted环境的建立需要标准C库的支持,而Freestanding编译器在生成时还没有可用的标准C库。这就是一个“鸡生蛋蛋生鸡”的问题了。


为了解决上述问题,需要额外的一个步骤:

(3)重新编译生成Hosted的交叉编译器。

这次编译时,可以有(2)生成的标准C库的支持了,所以可以产生出一个完整的Hosted交叉编译器了。

关键字:交叉编译器 引用地址:Freestanding C与交叉编译器的生成原理分析

上一篇:TQ2440开发板学习纪实(3)--- 设置时钟频率,让CPU运行的更快
下一篇:原来程序是这样从NandFlash拷贝并跳转到SDRAM的

推荐阅读

注意:如果stm32f2xx系列上面的网址的代码要做适当修改。以下说重点:stm32f2xx系列,在调试中对GPIO的初始化,切记选择GPIO_Mode_AF模式,即端口复用。随后,要做端口映射处理,即调用:GPIO_PinAFConfig()函数。这2个方式不选择,timer是不会有反应的本人是stm32f207,花了4天惨痛代价。以下贴代码: /* Private define -------------------------...
据外媒报道,当地时间8月20日,美国专利商标局(U.S. Patent and Trademark Office)授予了苹果公司53项新专利,其中有两项与苹果的泰坦计划有关。第一项专利涉及车辆稳定控制系统,第二项专利涉及具有自适应定位功能的车门。而在苹果泰坦项目(一)中,我们已经讲过了苹果的车辆稳定控制系统专利,现在我们来了解一下其自适应定位车门专利。(图片来...
中国锂电池电解液行业发展现状——国产化率提升,并逐渐走向国际锂电池电解液是锂电池的“血液”,是离子传输的载体,在正负极之间起到传导锂离子的作用,为锂离子提供一个自由脱嵌的环境,是锂电池的关键组件之一。中国锂电池电解液行业经历了进口依赖、国产替代和国际化阶段,经过不断的发展,中国企业生产的锂电池电解液性能逐步提升,获得了业内的普遍...
位带别名区地址 = 位带别名区基址 + 位带区字节偏移 × 32(位带区的一个字节膨胀过来是32个字节) + 位带区位偏移 × 4(位带区的一个位膨胀过来是32位即4个字节)1、位带认识其实学习51的时候已经初步领略过,只是当时没有提出这么专业的名次,譬如:TR0 = 1不就是嘛!51中可以进行位带操作的内存地址为20H 到 2FH 这 16 个字节共 128 位...

史海拾趣

问答坊 | AI 解惑

伟福6000版本

这是下载的伟福软件,与大家分享。…

查看全部问答∨

了解逻辑分析仪(1)

逻辑分析仪是利用时钟从测试设备上采集和显示数字信号的仪器,最主要作用在于时序判定。由于逻辑分析仪不像示波器那样有许多电压等级,通常只显示两个电压(逻辑1和0),因此设定了参考电压后,逻辑分析仪将被测信号通过比较器进行判定,高于参考电 ...…

查看全部问答∨

哪为大侠帮小弟讲解下这个复位电路啊

资料好难找呀,哪位大侠帮帮小弟,帮我讲解下这个电路的原理,万分感谢…

查看全部问答∨

求助! 谁有AD7705典型电路及程序?

新手,需要用7705来做个报警器,信号范围是0~1000mv 电路不知道设计,还有谁有程序可以帮帮我,借我参考下。。。。。。。。谢谢大家啦啦啦啦啦啦啦啦啦啦啦啦啦啦…

查看全部问答∨

关于verilog

请问verilog中出现warning:xst:883 - "uc interface.v" line 156: ignored duplicate item in case statement. 什么意思啊?                              &nb ...…

查看全部问答∨

usb HID鼠标支持一个传递压力的触摸笔吗,

我在用触摸屏模拟鼠标,但是触摸屏做一个电子画板,除了上传鼠标的坐标位置外,我还想用一个触摸笔把触摸笔的压力型号上传上去,当人画画的时候,用力比较大时,画的线粗,用力小时,画的线窄,hid协议支持吗…

查看全部问答∨

做出来应急灯电路 组要对电路进行仿真 用什么软件好?

如题 电路组成左边充电电路,由变压器T1、电阻R3、整流桥VC和蓄电池GB组成;停电时荧光灯点亮电路。由蓄电池GB、开关SA和直流/交流变换器(由三极管VT、高频变压器T2和灯管G及电阻R1、R2、电容C、二极管VD组成)组成 要是能发图就好了…

查看全部问答∨

winec5.0读excel表!!!!分不够加~!!

再wince5.0下读excel表,现在有个SpreadEC.exe文件可以再ce5.0下把XLS文件打开,请问我怎么才能再程序里调用这个.exe文件来读excel文件,再把指定的数据读到textbox里,再pc上实现了读excel文件,但是放到wince5.0环境下不能跑,请指点下,如果可以 ...…

查看全部问答∨

讨论干扰的问题

最近在写论文。有如下问题大家来讨论: 估算系统精度时,AD转换的误差可否估算? AD转换误差除了参考电压的误差和量化误差外,还要考虑些什么因素?…

查看全部问答∨

PIC16F1937驱动LCD,怎么也不亮

PIC16F1937驱动LCD,怎么也不亮,这是我的程序初始化LCD的代码,当然那些I/O口的也设置了,我像随便点亮下,他就是不亮了,很久没有玩汇编代码了,搞了好久,搞不对!LCD_RET         BANKSEL   LCDPS&nbs ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved