2011年12月7日星期三

intel架构中声名狼藉的分段机制早已被现代系统抛弃

本章最后的话题是关于Intel架构中声名狼藉的分段系统。除了一些遗留下来的ex-Bu
rroughs Unisys大型主机系统外,x86系列是唯一仍在普遍使用的分段架构。但是由于它非
常的流行,我们不得不处理它。但是就像我们将要简要讨论的那样,32位操作系统不怎么
使用分段机制,在老一些的系统和流行的16位嵌入式x86系列中分段机制被广泛的引用。
最初的8086是Intel颇为流行的8位8080和8085微处理器的后继版本。8080具有16
位地址空间,这使得8086的设计者在保持对16位地址空间的兼容和提供更大的地址空间之
间进退维谷。他们最终妥协了,方法是提供多个16位的地址空间。每个16位的地址空间就
是我们知道的段。
一个运行中的x86程序由四个段寄存器定义了四个活动段。CS寄存器定义了代码段,
用来指示指令获取的位置。DS寄存器定义了数据段,用来指示多数数据被读取和存储的位
置。SS寄存器定义了栈段,这对PUSH和POP指令的操作数是有用的,程序的返回地址会通
过call和return指令被压入和弹出栈中,以EBP或ESP为基址寄存器可以完成对任何数据
的引用。ES寄存器定义了扩展段,会被一些新的字串操作指令所用到。386和之后的芯片还
定义了2个新的段寄存器FS和GS。通过段覆盖,对任何数据的引用都可以定向到某一个特
定的段。例如,指令MOV EAX,CS:TEMP可以从代码段(而不是数据段)的位置TEMP获取一个
数值。FS和GS段仅在段“覆盖(segment override)”时使用。
段值可以有相同的。多数程序会将DS和SS设置为相同的数值,这样对栈变量和全局变
量的指针可以交换使用。有一些小程序会将四个段寄存器设置成相同的值,这样可以提供我
们所知道被称为“微小(tiny)”模式的地址空间。
在8086和186上,体系结构定义了一种段数值与内存地址之间的固定映射方法,即将
段数值左移4位。例如段数值为0x123的段从内存地址0x1230处开始。这种简单的寻址方式
也被称为“实模式”。程序员经常将一个段可以寻址的16字节的内存单元非正式的称为“
段落(paragraphs)”。
286引入了保护模式,操作系统可以将段映射到实际内存的任何位置,并可以通过将段
标注为“不存在”而实现基于段的虚拟内存。每个段可以被标识为可执行、可读或可读写,
以提供段级的保护机制。386将保护模式扩展到32位,这样每个段最大可以到4GB而不是仅
有的64KB。
对于16位寻址,除了最小的程序外其它的都要处理分段的地址。修改段寄存器中的内
容是比较慢的,在486上相比与修改通用寄存器内容所需的1个时钟周期,修改段寄存器需
要9个时钟周期。因此,程序和程序员都费了很大的周折将数据和代码挤入尽可能少的段中
以尽量避免更换段寄存器中的内容。链接器通过提供“聚集”功能将相关的代码或数据收集
到一个段中,来为这个过程提供帮助。代码和数据的指针,可以是仅使用偏移量的近(near)
类型,也可以是同时需要段和偏移量的远(far)类型。
编译器可以为那些决定代码或数据地址缺省是近类型还是远类型的多种内存模式生成
对应的代码。小(small)模式代码中所有的指针都是近类型,且仅有一个代码段和数据段。
大(large)模式代码有多个代码和数据段,所有的指针缺省都是远类型。编写有效分段的
代码是很有技巧的,而且已经有其它文档很好的对其阐述了。
分段的寻址会对链接器提出重要的需求。程序中的每一个地址都要有一个段址和段内
偏移量。目标文件含有多个被链接器装入各种段中的代码块。运行在实模式下的程序必须将
程序内的段进行标注好让程序被加载时被重定位到实际的段位置。在保护模式下执行的程序
更需要标注出数据将被加载到哪个段且对每个段采取怎样的保护(代码,只读数据,可读写
数据)。
虽然386同时支持32位段和286的16位段的所有特性,但多数32位程序根本就不使用
段。386中也加入了分页机制,可以提供分段机制的多数实用优点,并且没有性能损失,也
没有编写额外段操作代码的麻烦。多数386操作系统在微小(tiny)模式下运行应用程序,
由于386下的段已经不再那么小了所以他有一个更为人知的名字叫做扁平(flat)模式。他
们会创建单独的代码段和数据段,每个都有4GB长并且都映射到完整的32位分页地址空间
上。即使应用程序只使用一个段,这个段也可以有整个地址空间这么大。
386可以在一个程序内同时使用16位和32位的段,对少数操作系统也可以做到,例如
Windows95和Windows98就利用了这个功能。Windows95和Windows98可以在一个共享的16
位地址空间内运行旧的Windows3.1代码,同时新的32位程序运行在各自的微小模式地址空
间中,并将16位地址空间映射过来以允许相互调用。

没有评论:

发表评论