什么是编译器,链接器,加载器?


Answers:


186
=====> COMPILATION PROCESS <======

                     |
                     |---->  Input is Source file(.c)
                     |
                     V
            +=================+
            |                 |
            | C Preprocessor  |
            |                 |
            +=================+
                     |
                     | ---> Pure C file ( comd:cc -E <file.name> )
                     |
                     V
            +=================+
            |                 |
            | Lexical Analyzer|
            |                 |
            +-----------------+
            |                 |
            | Syntax Analyzer |
            |                 |
            +-----------------+
            |                 |
            | Semantic Analyze|
            |                 |
            +-----------------+
            |                 |
            | Pre Optimization|
            |                 |
            +-----------------+
            |                 |
            | Code generation |
            |                 |
            +-----------------+
            |                 |
            | Post Optimize   |
            |                 |
            +=================+
                     |
                     |--->  Assembly code (comd: cc -S <file.name> )
                     |
                     V
            +=================+
            |                 |
            |   Assembler     |
            |                 |
            +=================+
                     |
                     |--->  Object file (.obj) (comd: cc -c <file.name>)
                     |
                     V
            +=================+
            |     Linker      |
            |      and        |
            |     loader      |
            +=================+
                     |
                     |--->  Executable (.Exe/a.out) (com:cc <file.name> ) 
                     |
                     V
            Executable file(a.out)

C预处理器:-

C预处理是编译的第一步。它处理:

  1. #define 陈述。
  2. #include 陈述。
  3. 条件语句。
  4. 巨集

该单元的目的是将C源文件转换为Pure C代码文件。

C编译:

该单元有六个步骤:

1)词法分析器:

它将源文件中的字符组合起来,形成一个“令牌”。令牌是一组没有“空格”,“制表符”和“换行符”的字符。因此,该编译单元也称为“ TOKENIZER”。它还删除注释,生成符号表和重定位表条目。

2)句法分析器:

该单元检查代码中的语法。例如:

{
    int a;
    int b;
    int c;
    int d;

    d = a + b - c *   ;
}

上面的代码将产生解析错误,因为方程式不平衡。本单元通过如下生成解析器树在内部进行检查:

                            =
                          /   \
                        d       -
                              /     \
                            +           *
                          /   \       /   \
                        a       b   c       ?

因此,该单元也称为PARSER。

3)语义分析器:

该单元检查语句中的含义。例如:

{
    int i;
    int *p;

    p = i;
    -----
    -----
    -----
}

上面的代码生成错误“分配不兼容类型”。

4)预优化:

该单元独立于CPU,即有两种优化类型

  1. 预优化(与CPU无关)
  2. 后优化(取决于CPU)

本单元以以下形式优化代码:

  • I)消除死代码
  • II)子代码消除
  • III)循环优化

I)消除死代码:

例如:

{
    int a = 10;
    if ( a > 5 ) {
        /*
        ...
        */
    } else {
       /*
       ...
       */
    }
}

此处,编译器在编译时知道'a'的值,因此它也知道if条件始终为true。因此,它消除了代码中的else部分。

II)子代码消除:

例如:

{
    int a, b, c;
    int x, y;

    /*
    ...
    */

    x = a + b;
    y = a + b + c;

    /*
    ...
    */
}

可以优化如下:

{
    int a, b, c;
    int x, y;

    /*
     ...
    */

    x = a + b;
    y = x + c;      // a + b is replaced by x

    /*
     ...
    */
}

III)循环优化:

例如:

{
    int a;
    for (i = 0; i < 1000; i++ ) {

    /*
     ...
    */

    a = 10;

    /*
     ...
    */
    }
}

在上面的代码中,如果“ a”是本地的并且未在循环中使用,则可以按以下方式对其进行优化:

{
    int a;
    a = 10;
    for (i = 0; i < 1000; i++ ) {
        /*
        ...
        */
    }
}

5)代码生成:

在这里,编译器生成汇编代码,以便将更常用的变量存储在寄存器中。

6)后优化:

此处的优化取决于CPU。假设如果代码中有多个跳转,则将它们转换为:

            -----
        jmp:<addr1>
<addr1> jmp:<addr2>
            -----
            -----

控件直接跳转到。

然后最后一个阶段是链接(创建可执行文件或库)。运行可执行文件时,将加载其所需的库。


6
我不确定为什么还没有人指出,但是链接器和加载器不在同一步骤。链接是编译的一部分,而加载是运行程序的一部分(之前)。
SimpleGuy

7)汇编器和最重要的8)链接器和9)要求的装载器在哪里?

131
  • 编译器读取,分析代码并将其转换为目标文件或错误消息列表。
  • 链接器将一个或多个目标文件以及可能的某些库代码组合到某个可执行文件,某个库或错误消息列表中。
  • 加载程序将可执行代码读入内存,执行一些地址转换,然后尝试运行该程序,从而导致正在运行的程序或错误消息(或同时出现两者)。

ASCII表示形式:

[Source Code] ---> Compiler ---> [Object code] --*
                                                 |
[Source Code] ---> Compiler ---> [Object code] --*--> Linker --> [Executable] ---> Loader 
                                                 |                                    |
[Source Code] ---> Compiler ---> [Object code] --*                                    |
                                                 |                                    |
                                 [Library file]--*                                    V
                                                                       [Running Executable in Memory]

2
这种解释是直接的。您应该考虑成为一名讲师。谢谢
0.sh

感谢您不回避有关链接器和加载器的答复!

29

希望这对您有所帮助。

首先,通过以下图表:

                         (img source->internet)

来源->互联网

您编写一段代码并保存文件(源代码),然后

预处理:-顾名思义,它不是编译的一部分。它们指示编译器在实际编译之前进行必要的预处理。您可以将此阶段称为“文本替换”或解释由#表示的特殊预处理程序指令。

编译:-编译是一个过程,其中用一种语言编写的程序被翻译成另一种目标语言。如果有错误,编译器将检测到并报告。

汇编:-汇编代码被翻译成机器代码。您可以将汇编器称为特殊类型的编译器。

链接:-如果这些代码段需要链接其他一些源文件,则链接器将它们链接起来以使其成为可执行文件。

之后有很多过程发生。是的,您猜测加载器的作用就在这里:

加载程序:-将可执行代码加载到内存中;程序和数据堆栈已创建,寄存器已初始化。

小小额外信息:-http: //www.geeksforgeeks.org/memory-layout-of-c-program/,您可以在那看到内存布局。


15

编译器:它是一个将高级语言程序转换为机器语言程序的程序。编译器比汇编器更智能。它检查各种限制,范围,错误等。但是它的程序运行时间更多,并且占用了内存的较大部分。它的速度慢。因为编译器会遍历整个程序,然后将整个程序转换为机器代码。如果编译器在计算机上运行并为同一台计算机生成机器代码,则称为自编译器或常驻编译器。另一方面,如果编译器在计算机上运行并为其他计算机生成机器代码,则称为交叉编译器。

链接器:在高级语言中,存储了一些内置的头文件或库。这些库是预定义的,并且包含对执行程序必不可少的基本功能。这些功能通过名为Linker的程序链接到库。如果链接器找不到函数库,则它会通知编译器,然后编译器将生成错误。编译器自动调用链接器,作为编译程序的最后一步。它不是内置库,它还将用户定义的函数链接到用户定义的库。通常,将较长的程序分为称为模块的较小子程序。并且必须将这些模块组合才能执行程序。组合模块的过程由链接器完成。

加载程序:加载程序是将程序的机器代码加载到系统内存中的程序。在计算中,加载程序是操作系统的一部分,负责加载程序。这是启动程序过程中的重要阶段之一。因为它将程序存储到内存中并为执行做准备。加载程序涉及将可执行文件的内容读取到内存中。加载完成后,操作系统通过将控制权传递给加载的程序代码来启动程序。所有支持程序加载的操作系统都具有加载程序。在许多操作系统中,加载程序永久地驻留在内存中。


14

维基百科应该有一个很好的答案,这是我的想法:

  • 编译器:读取something.c源代码,写入something.o对象。
  • 链接器:将多个* .o文件连接到一个可执行程序中。
  • 加载程序:将可执行文件加载到内存并开始运行的代码。

4

*

关于基于linux / unix的系统的解释,尽管它是所有其他计算系统的基本概念。

*

LinuxJournal的链接器和加载器清楚地解释了此概念。它还说明了经典名称a.out是如何出现的。(汇编输出)

快速总结

c program --> [compiler] --> objectFile --> [linker] --> executable file (say, a.out)

我们得到了可执行文件,现在将此文件提供给您的朋友或需要此软件的客户:)

当他们运行此软件时,说在命令行./a.out中输入

execute in command line ./a.out --> [Loader] --> [execve] --> program is loaded in memory

一旦程序被加载到存储器中,控制就通过使PC(程序计数器)指向第一个指令来转移到该程序。 a.out


4

编译器:

它将读取可能是.c或.cpp等类型的源文件,并将其转换为称为目标文件的.o文件。

连结器:

它将可能为多个源文件生成的几个.o文件合并为一个可执行文件(GCC中的ELF格式)。链接有两种类型:

  • 静态链接
  • 动态链接

装载机:

将可执行文件加载到计算机主存储器的程序。


有关Linux中程序执行的这三个阶段的详细研究,请阅读


1

编译器更改检查您的源代码是否有错误,并将其更改为目标代码。这是操作系统运行的代码。

您通常不会在单个文件中编写整个程序,因此链接器会链接所有目标代码文件。

您的程序将不会执行,除非它在主内存中


1
  • 编译器:将人类可理解的格式转换为机器可理解的格式
  • 链接器:将机器可理解的格式转换为操作系统可理解的格式
  • 加载程序:实际上是将程序加载并运行到RAM中的实体

链接器和解释器是互斥的解释器,逐行获取代码并逐行执行代码。


1
  • 编译器:一种语言翻译器,它将完整的程序转换为机器语言,以生成计算机可以整体处理的程序。
  • 链接器:实用程序,它接收一个或多个编译的目标文件并将它们组合为一个可执行文件或另一个目标文件。
  • 加载程序:将可执行代码加载到内存中,创建程序和数据堆栈,初始化寄存器并启动代码运行。

1

编译器 将源代码转换为目标代码。

链接器 将多个目标文件组合为一个可执行程序文件。

加载程序 将可执行文件加载到主存储器中。


1
我认为您的答案已在过去10年中现有的14个高质量答案中得到了很大的覆盖
Nicolas Gervais


0

编译器将代码行从编程语言转换为机器语言。

链接器在两个程序之间创建链接。

加载程序将程序加载到主数据库,程序等的内存中。


-1

编译器:这是一个系统软件,可以纠正程序,目标文件,消息等错误

链接器:这是一个系统软件,它将一个或多个目标文件以及可能的某些库代码组合到某些可引用的库或错误列表中

加载程序:将可执行文件加载到计算机主存储器的程序

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.