环保网站建设方案,商务网站的功能,宿迁网站优化,制作手机网站什么软件下载接上一篇。
7.3 地址无关代码 对于现代机器来说#xff0c;引入地址无关代码并不麻烦#xff0c;我们展示下各种模型的地址引用方式#xff1a; 1. 模块内部函数调用 2. 模块内部的数据访问#xff0c;如全局变量、静态变量。 3. 模块外部的函数调用#xff0c;跳转。 4.… 接上一篇。
7.3 地址无关代码 对于现代机器来说引入地址无关代码并不麻烦我们展示下各种模型的地址引用方式 1. 模块内部函数调用 2. 模块内部的数据访问如全局变量、静态变量。 3. 模块外部的函数调用跳转。 4. 模块外部的数据访问。 当编译器在编译 pic.c 时它实际上并不能确定变量b和函数ext是模块外部的还是模块内部的因为它们有可能被定义在同一个共享对象的其他目标文件中。由于没法确定编译器只能把它们都当作模块外部的函数和变量来处理。MSVC编译器提供了_declspecdllimport编译器扩展来表示一个符号是模块内部的还是模块外部的。 1. 模块内部函数调用 同一模块中的函数地址相对固定寻址相对简单些使用的是相对寻址不需要重定位。 这条指令中的后4个字节是目的地址相对于当前指令的下一条指令的偏移即0xFFFFFFE8Little-endian。0xFFFFFFE8是-24的补码形式即 bar 的地址为0x804835c-240x8048344。那么只要bar和foo的相对位置不变这条指令是地址无关的。即无论模块被装载到哪个位置这条指令都是有效的。这种相对地址的方式对于jmp指令也有效。 2. 模块内部数据访问 模块内部访问也是相对寻址。一个模块前面一般是若干个页的代码后面紧跟着若干个页的数据这些页之间的相对位置是固定的也就是说任何一条指令与它需要访问的模块内部数据之间的相对位置是固定的那么只需要相对于当前指令加上固定的偏移量就可以访问模块内部数据了。现代的体系结构中数据的相对寻址往往没有相对与当前指令地址PC的寻址方式所以ELF用了一个很巧妙的办法来得到当前的PC值然后再加上一个偏移量就可以达到访问相应变量的目的了。得到PC值的方法很多我们来看看最常用的一种也是现在ELF的共享对象里面用的一种方法 3. 模块间数据访问 模块间数据访问相对麻烦些因为地址要等到装载时才能确定。比如上面例子中的变量b它被定义在其他模块中并且该地址在装载时才能确定。我们前面提到要使得代码地址无关基本的思想就是把跟地址相关的部分放到数据段里面很明显这些其他模块的全局变量的地址是跟模块装载地址有关的。ELF的做法是在数据段里面建立一个指向这些变量的指针数组也被称为全局偏移表Global Offset TableGOT当代码需要引用该全局变量时可以通过GOT中相对应的项间接引用它的基本机制如图7-7所示。 当需要访问b时程序会先找到GOT然后根据GOT中的变量所对应的项找到变量的目标地址。链接器在装载模块的时候会查找每个变量所在地址然后将各个项填入GOTGOT。
未完待续