程序的链接与装入(动、静态重定位)

 原由:

多道程序环境下,程序是并发执行的,所以要使程序运行,必须先为之创建进程,而创建进程的第一件事就是将程序和数据装入内存

目的:

用户程序到内存可执行程序的步骤:

 


下面开始将程序“链接”和“装入”的具体情况:


程序的链接:


源程序经过编译后,得到一组目标模块,再利用“链接程序”将这组目标模块链接起来,形成一个完整的装入模块(即可执行文件

如下图:源程序编译后得到三个目标模块A、B、C,长度分别为L、M、N,链接后形成右侧的装入模块:


链接时需要做两个工作:

Ø  相对地址进行修改(变化以后还是相对地址),地址都变为相对最上层模块的起始地址来计算。

Ø  变化外部调用符号,如CALL B------> JSR“L”


CALL B为调用B模块,JSR“L”为跳转到L行

链接前A和B为两个不同的模块,在A模块中想执行B模块,要使用调用(CALL)语句;链接后A和B为同一模块,若想达到同样地效果,只需在本模块中使用跳转语句(JSR)跳转到想执行的地方即可。


程序的装入:


即将链接好的模块装入内存


逻辑地址与物理地址


       用户程序编译为目标模块后,会对每个模块内部(程序数据等)进行编址,此时编好的地址叫做逻辑地址或相对地址(下面的绝对装入方式除外),都是相对于本模块的起始地址(一般从0开始)计算的。进行链接后某些模块的相对地址会发生变化,地址都变为相对于装入模块的起始地址进行计算。


     通常将内存的实际地址称为物理地址


     

分类

Ø  绝对装入方式

Ø  可重定位装入方式(静态重定位)

Ø  动态运行时装入方式(动态重定位)

解析


(1)绝对装入方式


程序编译时,如果知道程序将驻留在内存的什么位置(起始地址),那么编译生成的目标代码,将采用绝地地址进行编址,即起始地址不从0开始,从上面所知的内存起始地址开始编址。

例如:事先已知用户程序(进程)驻留在从1000号单元处开始的位置,则编译程序所产生的目标模块(即装入模块)便从1000处开始向上扩展:


由于采用的是绝对地址,所以将装入模块直接装入内存即可,无需进行地址变换。

(2)可重定位装入方式(静态重定位)


Ø  出现:

编译时将程序装入指定的内存空间,必须需要程序员熟悉内存的使用情况

绝对装入方式只能将目标模块装入到内存中事先指定的位置。而在多道程序环境下,编译程序不可能预知所编译的目标模块应放在内存的何处

可重定位方式可根据内存的当前情况,将装入模块装入到内存的适当位置

Ø  原理:

源程序编译生成的目标模块都采用相对地址进行编址,即每个模块都从0开始编址,当然链接后的模块也采用相对地址编址


将装入模块装入内存后,模块中的程序和数据等,在内存中都将具有一个物理地址,此物理地址是相对于内存的起始地址进行编址的,所以与原先模块中的逻辑地址(相对于模块的起始地址进行编址)不同,所以为了得到物理地址需要对逻辑地址进行改变。而此地址变化的过程就叫做重定位,又因为地址变换通常是在装入时一次完成的,以后不再改变,故称为静态重定位。如下图:



(3)动态运行时装入方式(动态重定位)


只是把相对地址到绝对地址的转换推迟到程序真正执行时才进行


总结:

原文地址:https://www.cnblogs.com/suncoolcat/p/3358053.html