什么是编译器、连接器、加载器?

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

239355 次浏览

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

  • 编译器: 读取 something. c 源代码,写入 something. o 对象。
  • 连接器: 将几个 * . o 文件连接到一个可执行程序中。
  • 加载程序: 将可执行文件加载到内存并开始运行的代码。
  • 编译器读取、分析代码并将其转换为目标文件或错误消息列表。
  • 链接器将一个或多个对象文件和可能的库代码组合到某个可执行文件、某个库或错误消息列表中。
  • 加载程序将可执行代码读入内存,进行一些地址转换并尝试运行程序,结果产生一个正在运行的程序或错误消息(或两者兼而有之)。

ASCII representation:

[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]

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

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

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

*

虽然它是所有其他计算系统的基本概念,但是它是基于 linux/unix 系统的。

*

LinuxJournal 的 Linkers and Loader 清晰地解释了这个概念。这也解释了经典的 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的第一条指令,控制就被转移到这个程序中

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

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

Linker 创建两个程序之间的链接。

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

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

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

Compiler:

它将读取可能类型为。C 或。等,并将其转换为。被称为目标文件的 o 文件。

连结器:

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

  • 静态链接静态链接
  • 动态链接

装载机:

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


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

=====> 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 preprocessing is the first step in the compilation. It handles:

  1. #define报表。
  2. #include报表。
  3. 条件性陈述。
  4. Macros

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

C 汇编:

这个单元有六个步骤:

1)词汇分析器:

It combines characters in the source file, to form a "TOKEN". A 标记是一组没有‘ space’、‘ tab’和‘ new line’的字符。 因此,这个编译单元也称为“ TOKENIZER” 注释,生成符号表和重定位表条目。

2)句法分析:

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

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


d = a + b - c *   ;
}

The above code will generate the parse error because the equation is not 这个单元通过生成解析器树在内部进行检查 如下:

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

因此,这个单元也称为 PARSER。

3)语义分析器:

这个单元检查报表中的含义。例如:

{
int i;
int *p;


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

上面的代码生成了错误“不兼容类型的赋值”。

4)预优化:

这个单元独立于 CPU,也就是说,有两种类型的优化

  1. 预优化(与 CPU 无关)
  2. 后优化(CPU 依赖)

该单位以下列形式优化代码:

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

一)死码删除:

For ex:

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

Here, the compiler knows the value of 'a' at compile time, therefore it also 知道 if 条件总是为真,因此它消除了 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) Loop optimization:

例如:

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


/*
...
*/


a = 10;


/*
...
*/
}
}

In the above code, if 'a' is local and not used in the loop, then it can be 优化如下:

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

5)代码生成:

这里,编译器生成程序集代码,以便 经常使用的变量存储在寄存器中。

6) Post-Optimization:

这里的优化依赖于 CPU。假设有多个 CPU 跳转到代码中,然后它们被转换为:

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

The control jumps to the directly.

然后是最后一个阶段的链接(创建可执行文件或库)。 当可执行文件运行时,它所需的库是 Loaded- 。

编译器: 是把高级语言程序翻译成机器语言程序的程序。编译器比汇编器更聪明。它检查各种限制,范围,错误等。但是它的程序运行时间更长,占用了更大的内存。它的速度很慢。因为编译器遍历整个程序,然后将整个程序翻译成机器码。如果一个编译器在一台计算机上运行并为同一台计算机生成机器码,那么它就是自编译器或驻留编译器。另一方面,如果一个编译器在一台计算机上运行,并为其他计算机生成机器码,那么它就是众所周知的交叉编译器。

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

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

希望这个能帮到你。

首先,看看这个图表:

(img source->internet)

source->internet

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

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

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

Assembly :-Assembly 代码被翻译成机器代码。

Linking:- If these piece of code needs some other source file to be linked, linker link them to make it a executable file.

在它之后会发生很多过程。是的,你猜到了,这就是加载程序的角色:

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

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

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

链接器: 它是一个系统软件,它将一个或多个对象文件和可能的一些库代码组合成一些可词汇的库或错误列表

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

  • 编译器: 转换完整 用机器语言编程生成 计算机可以在其 完整。
  • 链接器: 实用程序,它接受一个或多个已编译的目标文件,并将它们组合成一个可执行文件或另一个目标文件。
  • Loader: loads the executable code into memory ,创建程序和数据堆栈 ,初始化寄存器 然后开始运行代码。

它将源代码转换为目标代码。

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

装弹手 它将可执行文件加载到主存中。