我想深入了解编译器、连接器和加载器的意义和工作。 参考任何语言,最好是 c + + 。
维基百科应该有一个很好的答案,以下是我的想法:
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]
编译器更改检查源代码中的错误并将其更改为目标代码。这是操作系统运行的代码。
您通常不会在单个文件中编写整个程序,所以链接器链接所有的目标代码文件。
你的程序不会被执行,除非它在主存中
*
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的第一条指令,控制就被转移到这个程序中
a.out
编译器是一种特殊的程序,它处理用特定编程语言编写的语句,并将它们转换成计算机处理器使用的机器语言或“代码”
Compiler 将代码行从编程语言转换为机器语言。
Linker 创建两个程序之间的链接。
Loader 将程序加载到主数据库、程序等的内存中。
链接器和解释器是相互排斥的 解释器逐行获取代码并逐行执行
它将读取可能类型为。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 preprocessing is the first step in the compilation. It handles:
#define
#include
该单元的目的是将 C 源文件转换为纯 C 代码文件。
这个单元有六个步骤:
It combines characters in the source file, to form a "TOKEN". A 标记是一组没有‘ space’、‘ tab’和‘ new line’的字符。 因此,这个编译单元也称为“ TOKENIZER” 注释,生成符号表和重定位表条目。
此单元检查代码中的语法。例如:
{ 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。
这个单元检查报表中的含义。例如:
{ int i; int *p; p = i; ----- ----- ----- }
上面的代码生成了错误“不兼容类型的赋值”。
这个单元独立于 CPU,也就是说,有两种类型的优化
该单位以下列形式优化代码:
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 代码的一部分。
例如:
{ 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; /* ... */ } }
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++ ) { /* ... */ } }
这里,编译器生成程序集代码,以便 经常使用的变量存储在寄存器中。
这里的优化依赖于 CPU。假设有多个 CPU 跳转到代码中,然后它们被转换为:
----- jmp:<addr1> <addr1> jmp:<addr2> ----- -----
The control jumps to the directly.
然后是最后一个阶段的链接(创建可执行文件或库)。 当可执行文件运行时,它所需的库是 Loaded- 。
编译器: 是把高级语言程序翻译成机器语言程序的程序。编译器比汇编器更聪明。它检查各种限制,范围,错误等。但是它的程序运行时间更长,占用了更大的内存。它的速度很慢。因为编译器遍历整个程序,然后将整个程序翻译成机器码。如果一个编译器在一台计算机上运行并为同一台计算机生成机器码,那么它就是自编译器或驻留编译器。另一方面,如果一个编译器在一台计算机上运行,并为其他计算机生成机器码,那么它就是众所周知的交叉编译器。
链接器: 在高级语言中,存储一些内置在头文件或库中的内容。这些库是预定义的,它们包含执行程序所必需的基本函数。这些函数通过一个名为 Linker 的程序链接到这些库。如果链接器没有找到一个函数库,那么它会通知编译器,然后编译器会生成一个错误。编译器自动调用链接器作为编译程序的最后一步。 它不是内置在库中的,它还将用户定义的函数链接到用户定义的库。通常一个较长的程序被划分为称为模块的较小的子程序。这些模块必须结合起来才能执行程序。组合模块的过程由链接器完成。
加载程序: 加载程序是一种将程序的机器代码加载到系统内存中的程序。在计算机中,加载程序是操作系统中负责加载程序的部分。这是启动一个项目过程中必不可少的阶段之一。因为它将程序放入内存并为执行做准备。加载程序包括将可执行文件的内容读入内存。加载完成后,操作系统通过将控制权传递给加载的程序代码来启动程序。所有支持程序加载的操作系统都有加载程序。在许多操作系统中,加载程序永久驻留在内存中。
希望这个能帮到你。
首先,看看这个图表:
(img 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/,你可以看到那里的内存布局。
编译器: 它是一个系统软件,纠正错误的程序,目标文件,消息等
链接器: 它是一个系统软件,它将一个或多个对象文件和可能的一些库代码组合成一些可词汇的库或错误列表
加载程序: 将可执行文件加载到机器主存中的程序
它将源代码转换为目标代码。
连接器 它将多个目标文件组合成一个可执行程序文件。
装弹手 它将可执行文件加载到主存中。