程序的重定位问题(程序装入)
在多道程序环境下,要使程序运行,必须先为程序创建进程。而创建进程的第一件事就是:将 程序和数据 装入内存。如何将一个用户源程序变成可在内存中执行的程序,通常都要进过几个步骤:1.编译:由compiler将源程序编译成若干个目标模块(Object Module);2.链接:由Linker将编译后形成的一组目标模块以及他们所需要的库函数连接在一起,形成一个完整的装入模块(Load Module);3;装入:由Loader将装入模块装入内存。
程序的装入方式一般可分为以下3种:
1.绝对装入方式(Abosolute Loading Mode)
在编译时,如果程序知道将驻留在内存的什么位置,那么,编译程序将产生绝对地址的目标代码。绝对装入方式按照装入模块中的地址,将程序和数据装入内存。装入模块被装入内存后,由于程序中的逻辑地址和实际内存地址完全相同,所以不需要对程序和数据的地址进行修改。
2.可重定位装入方式(Relocation Loading Mode)
绝对装入方式能将目标模块装入到内存中事先指定的位置。在多道程序环境下,编译程序不可能预知所编译的模块应该放在内存的何处,因此, 绝对装入方式只适用于单道程序环境。 在多道程序环境下,所得到的目标模块起始地址通常从0开始,程序中的其他地址都是相对于起始地址0计算的,此时应该采用可重定位装入方式,根据内存当时的情况,将装入模块装入到内存的合适位置。
值得注意的是:在采用重定位装入方式将程序装入内存后,会使装入模块中的所有逻辑地址和内存的物理地址不同,解决方法是:在装入的时候,将装入模块中指令和数据的逻辑地址修改为物理地址,这一过程就叫 重定位 。又因为地址变换是在装入时一次性完成的,以后不会再改变,所以称为 静态重定位 。
3.动态运行时装入方式(Dynamic Run-time Loading)
静态重定位方式可将装入模块装入到内存中任何允许的位置,所以可以用于多道程序环境;但是这种装入方式并 不允许程序运行时在内存中移动位置 。 因为程序一旦移动的话,就必须修改程序和数据的绝对地址。然而,实际情况是,程序在运行的过程中在内存的位置可能经常要改变,此时就应该采用 动态重定位 的方式。
动态重定位的装入程序在把模块装入内存后,并不会立即把模块中的相对地址转换为物理地址,而是 把这种地址转换推迟到程序真正要执行时才进行 。因此,装入内存后的所有地址仍然是相对地址,为了使地址转换不影响指令的执行速度,这种方式需要一个 重定位寄存器来存储模块在内存中的起始地址 。