概要
程序执行过程中,一共经历了四步,最终生成可执行的目标文件hello,这四个步骤分别是:预处理,编译,汇编,链接。
预处理:预处理器(cpp)预处理就是把程序中引用文件,插入到当前文本文件中,比如开头的#include <stdio.h>,包含了stdio.h文件,预处理命令就会读取stdio.h文件的内容,把它插入到当前的hello.c文件中,生成一个叫hello.i的文件;
编译:编译器(ccl) 编译这个阶段就比较重要了,我们平常使用的高级语言有很多种,C,C++,Java……,每种语言书写表达的方式不尽相同,如何把这些不同的语言统一转换成一种格式,让计算机理解他们要做的都是同一件事情呢?那就要靠编译器了!这里不同的语言使用的编译器也不相同,但要实现的功能是一致的。编译器中存在一个叫做“汇编语言程序”的东西,汇编语言大概是最接近机器语言的了,编译器要做的事情,就是把预处理完毕的hello.i文件翻译成汇编语言,生成的文件叫做hello.s;
汇编:汇编器(as)要做的就是把编译生成的汇编语言,翻译成机器能读懂的二进制语言,叫做hello.o;
链接:链接器(ld)看上图中代码调用了一个printf()函数,这是C编译器中的标准C库中的一个函数,单独保存在一个已经预编译好的printf.o文件中,链接器要做的就是把printf.o文件合并到我们的hello.o文件中,最终生成了可执行文件hello;
程序的装入和链接
编译程序:将用户源代码编译成若干个目标模块;
链接程序:将一组目标模块及它们所需要的库函数链接在一起,形成一个完整的装入模块
装入程序:将装入模块装入内存。
程序的装入
逻辑地址空间(或地址空间):由程序中逻辑地址组成的地址范围。
【注意】用户程序经编译之后的每个目标模块都以0为基地址顺序编址,这种地址称为相对地址
绝对地址(物理地址):内存中各物理存储单元的地址是从统一的基地址顺序编址,这种地址称为绝对地址
绝对装入方式
1. 逻辑地址与实际地址相同
2. 要求程序员熟悉内存的使用情况
3. 通常在程序中采用符号地址
可重定位装入方式
目标模块从0编址,其它地址相对于起始地址计算
重定位:装入时对目标程序中指令和数据的修改过程。
动态运行时装入方式
动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址都仍是相对地址。
程序的链接
静态链接方式
在程序运行之前,先将各目标模块及它们所需的库函数,链接成一个完整的装配模块,以后不再拆开。我们把这种事先进行链接的方式称为静态链接方式。
装入时动态链接
用户源程序经编译后所得的目标模块,是在装入内存时边装入边链接的,即在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存。
运行时动态链接
在执行过程中,当发现一个被调用模块尚未装入内存时,立即由OS去找到该模块并将之装入内存,把它链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和被链接到装入模块上,这样不仅可加快程序的装入过程,而且可节省大量的内存空间。