【问题标题】:What is compiler, linker, loader?什么是编译器、链接器、加载器?
【发布时间】:2011-04-29 03:22:08
【问题描述】:

我想深入了解编译器、链接器和加载器的含义和工作原理。 参考任何语言,最好是 c++。

【问题讨论】:

标签: compiler-construction linker terminology loader


【解决方案1】:
=====> 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. 条件语句。

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

C编译:

单元中有六个步骤:

1) 词法分析器:

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

2) 句法分析器:

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

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

    d = a + b - c *   ;
}

上面的代码会产生解析错误,因为等式不是 均衡。该单元通过将解析器树生成为 如下:

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

因此这个单元也被称为解析器。

3) 语义分析器:

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

{
    int i;
    int *p;

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

以上代码生成错误“Assignment of incompatible type”。

4) 预优化:

这个单元独立于CPU,即有两种优化方式

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

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

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

I) 死码消除:

例如:

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

这里,编译器在编译时就知道 'a' 的值,因此它也 知道 if 条件始终为真。因此它消除了其他 部分代码。

二)子代码消除:

例如:

{
    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

    /*
     ...
    */
}

三)循环优化:

例如:

{
    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>
            -----
            -----

控件直接跳转到。

最后一个阶段是链接(创建可执行文件或库)。 当可执行文件运行时,它需要的库被加载。

【讨论】:

  • 我不知道为什么还没有人指出,但是链接器和加载器不在同一个步骤。链接是编译的一部分,而加载是(之前)运行程序的一部分。
  • 被问到的 7) Assembler 和最重要的 8) Linker 和 9) Loader 在哪里?
  • @SimpleGuy “编译”和“链接”不是分开的概念吗?我认为通常人们使用“构建”一词来指代编译和链接等。
【解决方案2】:
  • 编译器读取、分析代码并将其转换为目标文件或错误消息列表。
  • 链接器将一个或多个目标文件和可能的一些库代码组合到某个可执行文件、某个库或错误消息列表中。
  • 加载程序将可执行代码读入内存,进行一些地址转换并尝试运行程序,从而导致程序正在运行或出现错误消息(或两者兼有)。

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]

【讨论】:

  • 这个解释是直截了当的。你应该考虑成为一名讲师。谢谢
  • 感谢您不回避回答有关链接器和加载器的问题!
【解决方案3】:

希望这对您有所帮助。

首先,看一下这张图:

(img source->internet)

你制作一段代码并保存文件(源代码),然后

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

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

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

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

在它之后发生了许多过程。是的,你猜对了,加载器的作用就在这里:

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

Little Extra info :- http://www.geeksforgeeks.org/memory-layout-of-c-program/ ,你可以看到那里的内存布局。

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        *

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

        *

        来自 LinuxJournal 的Linkers and Loaders 清晰地解释了这个概念。它还解释了经典名称 a.out 的来历。 (汇编器输出)

        快速总结,

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

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

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

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

        一旦程序加载到内存中,通过使 PC(程序计数器)指向 a.out 的第一条指令,控制权就会转移到该程序

        【讨论】:

          【解决方案7】:

          编译器:

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

          链接器:

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

          • 静态链接
          • 动态链接

          加载器:

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


          如需详细了解 Linux 程序执行的这三个阶段,请read this

          【讨论】:

            【解决方案8】:
            • 编译器:将人类可以理解的格式转换为机器可以理解的格式
            • 链接器:将机器可理解的格式转换为操作系统可理解的格式
            • Loader : 是实际将程序加载并运行到 RAM 中的实体

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

            【讨论】:

              【解决方案9】:

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

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

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

              【讨论】:

                【解决方案10】:

                编译器将代码行从编程语言翻译成机器语言。

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

                A Loader将程序加载到主数据库、程序等内存中

                【讨论】:

                  【解决方案11】:
                  • 编译器:一种语言翻译器,可将完整的 用机器语言编程产生一个 计算机可以处理的程序 完整。
                  • 链接器:实用程序,它采用一个或多个编译的目标文件并将它们组合成一个可执行文件或另一个目标文件。
                  • 加载器:将可执行代码加载到内存中 , 创建程序和数据栈 , 初始化寄存器 并开始运行代码。

                  【讨论】:

                    【解决方案12】:

                    编译器是一种特殊的程序,它处理以特定编程语言编写的语句并将它们转换为计算机处理器使用的机器语言或“代码”

                    【讨论】:

                      【解决方案13】:

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

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

                      加载器 它将可执行文件加载到主内存中。

                      【讨论】:

                      • 我认为过去 10 年现有的 14 个高质量答案已经基本涵盖了您的答案
                      【解决方案14】:

                      编译器:它是一个系统软件,用于纠正程序、目标文件、消息等的错误

                      链接器:它是一种系统软件,它将一个或多个目标文件和可能的一些库代码组合成一些可执行的一些库或错误列表

                      Loader:将可执行文件加载到机器主内存的程序

                      【讨论】:

                        猜你喜欢
                        • 2011-04-19
                        • 2017-10-11
                        • 1970-01-01
                        • 2016-06-10
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-08-11
                        • 2014-02-26
                        • 2011-12-17
                        相关资源
                        最近更新 更多