• Compiler编译过程


    Compiler编译过程

    1.原理

    编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的目标代码,这种编译器又叫做“本地”编译器。另外,编译器也可以生成用来在其它平台上运行的目标代码,这种编译器又叫做交叉编译器。交叉编译器在生成新的硬件平台时非常有用。“源码到源码编译器”是指用一种高阶语言作为输入,输出也是高阶语言的编译器。例如: 自动并行化编译器经常采用一种高阶语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。

    预处理器(preprocessor)

    作用是通过代入预定义等程序段源程序补充完整。

    编译器前端(frontend)

    前端主要负责解析(parse)输入的源代码,由词法分析器语法分析器协同工作。词法分析器负责把源代码中的‘单词’(Token)找出来,语法分析器把这些分散的单词按预先定义好的语法组装成有意义的表达式,语句 ,函数等等。 例如“a = b + c;”前端词法分析器看到的是“a, =, b , +, c;”,语法分析器按定义的语法,先把他们组装成表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化和处理。

    编译器后端(backend)

    编译器后端主要负责分析,优化中间代码(Intermediate representation)以及生成机器代码(Code Generation)。

    一般说来所有的编译器分析,优化,变型都可以分成两大类:函数内(intraprocedural)还是函数之间(interprocedural)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。

    2. 嵌入式交叉编译过程

    嵌入式软件开发所采用的编译为交叉编译。所谓交叉编译就是在一个平台上生成可以在另一个平台上执行的代码。因此,不同的CPU需要有相应的编译器,而交叉编译就如同翻译一样,把相同的程序代码翻译称不同的CPU对应语言。要注意的是,编译器本身也是程序,也要在与之对应的某一个CPU平台上运行。

                         交叉编译环境 

    一般把进行交叉编译的主机称为宿主机,也就是普通的通用计算机,而把程序实际的运行环境称为目标机,也就是嵌入式系统环境。由于一般通用计算机拥有非常丰富的系统资源、使用方便的集成开发环境和调试工具等,而嵌入式系统的系统资源非常紧缺,没有相关的编译工具,因此,嵌入式系统的开发需要借助宿主机(通用计算机)来编译出目标机的可执行代码。

    由于编译的过程包括编译、链接等几个阶段,因此,嵌入式的交叉编译也包括交叉编译、交叉链接等过程,通常ARM的交叉编译器为arm-elf-gcc,交叉链接器为arm-elf-ld。

     

     交叉编译过程

    3. C/C++程序编译过程

    简单来说,整个过程分为四个阶段:预处理(Pre-Processing)、编译(Compilation)、汇编(Assembling)、链接(Linking)。

     

     4. 纯C语言的编译链接过程

    把编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程。

     

     5. gcc编译

    gcc编译分为四部
    第一步,预编译,将程序中的宏定义等预编译
    第二步,编译,将*.h,*.c等文件编译成为*.o文件
    第三步,汇编
    第四步,连接,将*.o文件连接库,生成可执行文件。

    例如,

    设有a.c,b.c,c.c

    gcc -c a.c
    gcc -c b.c
    gcc -c c.c
    (这样生成a.o b.o c.o)
    gcc -o main a.o b.o c.o
    (这样就生成名为:main的执行档了)
    ./main
    就可以执行

    1. 6.  示例程序

    vi hello.c并写入程序

     

      

     预处理

    gcc -E hello.c -o hello.i

    预编主要前面处理带“#”的指令,如#include、#define等,还要删除注释,添加行号和文件名标识

     

     编译

    gcc -S hello.i -o hello.s

    编译过程是把预处理完的文件进行一系列的词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件

     

     汇编

    gcc -c hello.s -o hello.o

    将代码转换成机器可以执行的指令

     

     连接

    连接是一个复杂的过程,使用ld指令

    ld -static crt1.o crti.o crtbeginT.o hello.o -start -group -lgcc -lgcc_eh -lc -end-group crtend.o crtn.o 

    连接的过程包括按序叠加、相似段合并、符号地址的确定、符号解析与重定位、指令修正、全局构造与解析等等

     运行程序

    ./hello 运行程序,可以看到结构

     

     

    人工智能芯片与自动驾驶
  • 相关阅读:
    FORM触发器执行顺序
    Invoke和BeginInvoke理解
    理解AppDomain
    BackgroundWorker学习笔记
    NLog类库使用探索——编程配置
    NLog类库使用探索——详解配置
    NLog类库的使用探索——认识配置+实习小感悟
    深入探讨WPF的ListView控件
    深入理解IOC模式及Unity框架
    网络通信之 字节序转换原理与网络字节序、大端和小端模式
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/14898008.html
Copyright © 2020-2023  润新知