https://www.zhihu.com/people/jiu_sheng
https://blog.csdn.net/qianshang52013/article/details/138140235?spm=1001.2014.3001.5501
Autosar 系列教程:小柴带你学 AutoSar 总目录
# 小柴带你学 AutoSar 系列一、基础知识篇(4)编译
# GCC 编译
GCC 编译器是一个开源的编译器套件,用于编译多种编程语言,包括 C、C++、Objective-C、Fortran、Ada 等。它是一个功能强大且灵活的编译器,支持多种平台和架构。
# 1. 预处理阶段(Preprocessing)
在预处理阶段,GCC 将源代码中的预处理指令(以 #
开头的指令,如 #include
、 #define
)处理成纯 C 代码。预处理器会将头文件包含到源文件中,执行宏替换等操作。
生成的文件:通常,预处理后的文件会以 .i
扩展名保存,如 source.i
。
# 2. 编译阶段(Compilation)
编译阶段将预处理后的源文件翻译成汇编语言。GCC 使用的是内置的 C 编译器(称为 cc1
),它将 C 代码转换成目标机器的汇编代码。
生成的文件:通常,编译后的文件会以 .s
扩展名保存,如 source.s
。
# 3. 汇编阶段(Assembly)
在汇编阶段,汇编器将汇编代码转换成机器码指令,生成目标文件。这些目标文件包含了二进制代码和相关的元数据。
生成的文件:通常,汇编后的文件会以 .o
扩展名保存,如 source.o
。
# 4. 链接阶段(Linking)
链接阶段将所有的目标文件(包括程序的主文件和所有的库文件)链接在一起,生成最终的可执行文件。链接器(ld)负责解析符号引用、符号重定位等任务,将各个目标文件中的代码和数据段组合成一个可执行文件。
生成的文件:最终生成的可执行文件通常没有扩展名,如 a.out
。
# 示例
假设有一个 C 源文件 hello.c
:
#include <stdio.h> | |
int main() { | |
printf("Hello, world!\n"); | |
return 0; | |
} |
通过 GCC 编译该文件时,可以执行以下命令:
gcc -o hello hello.c |
这个命令会依次执行预处理、编译、汇编和链接四个阶段,并生成最终的可执行文件 hello
。
hello.i
:预处理后的文件。hello.s
:编译后的汇编文件。hello.o
:汇编后的目标文件。hello
:最终的可执行文件。
这就是 GCC 编译器的工作过程以及每个阶段生成的文件。
# GHS 编译
RH850 是一种用于嵌入式系统的微控制器(MCU),通常用 Green Hills Software(GHS)编译工具进行编译和链接。GHS 工具链包含编译器、汇编器、链接器等,支持各种目标平台和架构。编译过程包括使用链接脚本,这是生成嵌入式系统二进制文件的关键步骤。下面是一个典型的 RH850 使用 GHS 编译器的编译过程,详细介绍了每个阶段及其生成的文件,特别是链接器脚本的作用。
# 1. 源代码准备
假设有一个简单的 C 源文件 main.c
:
#include <stdio.h> | |
void main(void) { | |
printf("Hello, RH850!\n"); | |
} |
# 2. 预处理阶段
预处理器将处理所有的预处理指令,例如 #include
和 #define
,生成一个预处理后的文件。
命令:
ccrh850 -E main.c -o main.i |
生成的文件:
main.i
:预处理后的文件。
# 3. 编译阶段
编译器将预处理后的 C 代码转换为汇编代码。
命令:
ccrh850 -S main.i -o main.s |
生成的文件:
main.s
:汇编代码文件。
# 4. 汇编阶段
汇编器将汇编代码转换为机器代码,生成目标文件。
命令:
asrh850 main.s -o main.o |
生成的文件:
main.o
:目标文件(对象文件)。
# 5. 链接阶段
链接器将多个目标文件和库文件链接在一起,生成可执行文件。链接器脚本在这个阶段非常重要,用于指定代码和数据段在内存中的布局。
链接器脚本(linker script)
一个典型的链接器脚本可能如下所示( linker.ld
):
SECTIONS | |
{ | |
.text : { | |
*(.text) | |
} | |
.data : { | |
*(.data) | |
} | |
.bss : { | |
*(.bss) | |
} | |
} |
这个脚本指定了 .text
段(代码段)、 .data
段(数据段)和 .bss
段(未初始化数据段)的布局。
命令:
librh850 main.o -T linker.ld -o main.elf |
生成的文件:
main.elf
:最终的可执行文件(ELF 格式)。
# 总结
预处理:
ccrh850 -E main.c -o main.i
- 生成预处理后的文件
main.i
。
- 生成预处理后的文件
编译:
ccrh850 -S main.i -o main.s
- 生成汇编代码文件
main.s
。
- 生成汇编代码文件
汇编:
asrh850 main.s -o main.o
- 生成目标文件
main.o
。
- 生成目标文件
链接:
librh850 main.o -T linker.ld -o main.elf
- 生成最终的可执行文件
main.elf
,使用链接器脚本linker.ld
指定内存布局。
- 生成最终的可执行文件
每个阶段都生成特定的中间文件和最终的可执行文件,链接器脚本在链接阶段至关重要,它定义了程序的内存布局,使得生成的二进制文件能够正确地运行在目标硬件上。