深入理解计算机4
第7章
链接器的存在使得分离编译成为可能。
链接就是将各种代码和数据部分收集起来组合成一个文件的过程。
在开始之前明确一下输入输出:
链接的输入是,汇编生成的二进制可重定位目标程序(包括共享目标文件),即多个.o 文件。
在32位linux系统的输出是
代码段起始位置为0x0848000, _start的地址为0x08480c0,这些位置是固定的。
数据段在接下来的下一个4k对齐的地址处,
heap段在接下来的下一个4k对齐的地址处,
stack段总是从最大的合法用户地址开始,向下增长。
以上这些地址都是虚地址。
ld –o output /caller/main.o /called/swap.o
链接器将_start 作为入口,上述命令能执行是因为默认链接了crt1.o
1 可重定位目标文件
代表elf文件。即main.o, swap.o 等等。可通过readelf 命令查看。
Elf文件中的一些节
.text : 已编译程序的机器代码
.rodata: 只读数据。即一些常量
.data: 已初始化的全局c变量
.bss: 未初始化的全局c变量
.symtab: 在程序中定义和引用的全局变量和引用函数的信息。
2 符号解析
将每个符号引用和一个符号定义联系起来。
解析多重定义的全局符号的规则:
3 重定位
重定位节和符号定义:将所有相同类型的节 合并为同一类型的新的聚合节。如将各个.o文件的.data节合并为一个节。这一步完成后,程序中的每个指令和全局变量都有唯一的运行时存储器地址了。
重定位节中的符号引用:
4 静态链接方式
1) 为每一个库函数创建一个独立的可重定位文件。如printf.o scanf.o 。这种方法要求 应用程序员显式的链接合适的目标模块,显然这个过程耗时且容易出错。
2) 将所有标准库函数放到一个.o文件里。这样任何一个函数的变化都需要重新编译,汇编,做库。
3) 将每个函数编译为独立的目标模块,并根据相关性制作为不同的库文件。
使用静态库时,如果各个库不是独立的,那么必须将他们按依赖性排序。
5动态链接共享库
静态库的缺点是被多次使用的库函数就会有多份冗余拷贝。
动态库在链接阶段库函数没有被复制到程序中,而是程序在运行时由系统加载到内存中,并且允许此模块和内存中的其他程序链接起来。
在unix系列中为.so在windows中为.dll
第8章
中断这个问题应该不陌生,这里只明确两个问题
各个中断源如何向cpu提出中断?
不管是硬件中断还是指令中断,最后都是向可编程中断控制器(这是一个硬件,如8359a)发出一个信号,中断控制器将cpu中的中断寄存器的某一位置为1。
Cpu什么时候,通过什么方式发现中断请求?
Cpu在一条指令执行完毕后,才能响应中断请求。也就是所谓的中断周期。
Cpu是检查其内部的中断请求触发器来确定是否有中断请求的。
至于中断保护恢复现场,判断中断类型,跳转到中断处理程序等问题所有书应该都有交代。
至于剩下的问题,我写将其和第9章写一起。