【计算机组成原理-结构化方法】汇编语言层

时间:2022-09-18 01:17:57

本章是从__链接和加载__这一章扣出来的。

(好,暂停,在这里我要说一说我的想法,进程当然有基地址,然后硬件会给每个加载进内存的程序的代码和数据的地址进行调整。这样便支持了运行时绑定。

可以注意到,出了动态链接库或者说共享库,程序代码不许要保留其他符号,保留的符号必然是DLL或这.a文件里的。

而这样的文件正是链接程序生成的,链接程序为了生成这样的程序需要付出什么代价呢?

每一个目标文件有基地址,代码段和数据段所有使用内存地址是num+pbase的格式。对一个目标文件而言pbase为0,num也肯定都为正。

符号表仍然保留,是为了那些共享库。(头痛,其实还有外部引用问题。)

多个目标文件链接时,将记录基地址,偏移不用重新计算,每个地址不过是num+newpbase的形式。anything worng?)

计算机组成原理-结构化方法提出

链接器按照下面的步骤把不同地址空间的目标模块合并到一个单一的线性地址空间:

(1)构造一张包括所有的目标模块和其长度的表

(2)基于这张表,为每一个目标模块分配一个起始地址。

(3)找到所有引用内存地址的指令,给地址加上一个重定位常量,该常量等于该模块的起始地址。

(4)找到所有引用其他过程的指令,在适当的地方插入这些被引 用的过程。

漂亮,那么tanenbuam认为一个模块的结构是什么呢?

【计算机组成原理-结构化方法】汇编语言层

如上图所示,有标识,入口点表,入口点表是本模块提供给外部的调用,外部引用表是本模块引用外部的代码。

目标模块的第五部分,重定位字典,是必须的吗?假如分为数据段和代码段的话,应该不许要了吧。

疑问:一个mov ax,4[bx]指令怎么重定位呢?bx是基地址。

有两种机制可以用来运行时binging,即内存地址移动带来的问题。

一是使用分页:那么首次加载的时候,所有的内存地址并不改变,而是改变页表。(我希望每一个进程都有一个页目录和一个页表。)

二是使用重定位寄存器。

(当有一个符号没有解释的时候,我怎么确定这个符号是dll中的,还是因为没有写?

NO,你大错特错,头文件包含的有符号。ok。)

当使用动态链接时,源程序中的过程调用被翻译成中间的间接寻址指令,该指令指向相应链接的第一个字,编译器或者在这个字中添入非法地址(要怎么样,这个非法地址不是导致死机,而是导致寻找动态库),或者放入导致陷阱的特素的位模式。

当调用一个不同的断中的过程时,访问非法的地址将产生一个陷阱,该陷阱调用动态链接器。链接器找到非法地址后面的字符串后,在用户目录空间搜索叫这个名字的已经编译的过程。然后给找到的过程分配一个虚拟地址。使用虚拟地址替换掉链接段中的非法地址。然后程序就能正常运行,如下图所示。

【计算机组成原理-结构化方法】汇编语言层