我想深入了解编译器、链接器和加载器的含义和工作原理。参考任何语言,最好是c++。
发布于 2014-02-21 02:04:05
=====> 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预处理是编译的第一步。它处理:
#define statements.#include statements.该单元的目的是将C源文件转换为纯C代码文件。
C编译:
单元中有六个步骤:
1)词法分析器:
它将源文件中的字符组合在一起,形成一个"TOKEN“。标记是一组不包含“空格”、“制表符”和“换行”的字符。因此,这个编译单元也被称为"TOKENIZER“。它还删除注释,生成符号表和重定位表条目。
2)语法分析器:
此单元检查代码中的语法。对于ex:
{
int a;
int b;
int c;
int d;
d = a + b - c * ;
}上面的代码将生成解析错误,因为方程式不平衡。此单元通过生成解析器树进行内部检查,如下所示:
=
/ \
d -
/ \
+ *
/ \ / \
a b c ?因此,这个单元也被称为解析器。
3)语义分析器:
本单元检查语句中的含义。对于ex:
{
int i;
int *p;
p = i;
-----
-----
-----
}上面的代码生成错误“分配不兼容的类型”。
4)预优化:
此单元独立于CPU,即有两种类型的优化
此单元以以下形式优化代码:
循环i)死代码elimination
I)消除死码:
对于ex:
{
int a = 10;
if ( a > 5 ) {
/*
...
*/
} else {
/*
...
*/
}
}在这里,编译器在编译时知道'a‘的值,因此它也知道if条件总是真的。因此,它消除了代码中的else部分。
II)子码消除:
对于ex:
{
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)循环优化:
对于ex:
{
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>
-----
-----控件直接跳转到。
最后一个阶段是链接(创建可执行文件或库)。运行可执行文件时,会加载它所需的库。
发布于 2010-10-22 20:34:22
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]发布于 2015-04-03 17:47:55
希望这对你有更多的帮助。
首先,看一下这个图表:
(img source->internet)

您创建一段代码并保存文件(源代码),然后
Preprocessing:顾名思义,它不是编译的一部分。它们指示编译器在实际编译之前进行所需的预处理。您可以将此阶段称为文本替换或解释由#表示的特殊预处理器指令。
Compilation :编译是用一种语言编写的程序被翻译成另一种目标语言的过程。如果有一些错误,编译器将检测到并报告它们。
汇编 :-汇编代码被翻译成机器码。你可以称汇编器为一种特殊类型的编译器。
Linking:如果这些代码需要链接其他源文件,则链接器将它们链接起来,使其成为可执行文件。
在它之后会发生很多过程。是的,你猜对了,这里就是装载器的角色:
Loader:它将可执行代码加载到内存中;创建程序和数据堆栈,初始化寄存器。
一点额外的信息:- http://www.geeksforgeeks.org/memory-layout-of-c-program/,你可以在那里看到内存布局。
https://stackoverflow.com/questions/3996651
复制相似问题