进程—内存段机制
开始阅读之前可以先看看The Curse of Segments
1.x86的硬件段机制
1.1 段机制的引入
就在8086CPU出现之前,地址总线已经是16位(64KB)的了,在刚开始,段的引入是为了解决“地址总线的宽度大于寄存器的宽度”这个问题。例如8086的寄存器只有16位,但是地址总线却有20位(1MB),为了使程序能利用到1MB的物理内存空间却又不对寄存器长度作出改变(内存容量扩大,成本基本保存不变),Intel在8086中引入了段机制。
8086提供了四个段寄存器 CS, DS, SS, 和ES ,从缩写的含义来看,这四个寄存器分别表示当前运行进程的code segment (CS), data segment (DS),stack segment (SS), 和一个用户自定义的段 (ES),操作系统可以同时跟踪一个进程的四个段。
1.2 段机制汇编
从纯硬件的角度来讨论段机制对汇编程序员的影响:
x86寻址模式之register indirect addressing modes:
The 80x86 CPUs let you access memory indirectly through a register using the register indirect addressing modes. There are four forms of this addressing mode on the 8086, best demonstrated by the following instructions:
mov al, [bx] //将DS:bx地址中的字节拷贝到al中 mov al, [bp] //将SS:bp地址中的字节拷贝到al中 mov al, [si] //将DS:si地址中的字节拷贝到al中 mov al, [di] //将DS:di地址中的字节拷贝到al中
As with the x86 [bx] addressing mode, these four addressing modes reference the byte at the offset found in the bx, bp, si, or di register, respectively. The [bx], [si], and [di] modes use the ds segment by default. The [bp] addressing mode uses the stack segment (ss) by default.
You can use the segment override prefix symbols if you wish to access data in different segments. The following instructions demonstrate the use of these overrides:
mov al, cs:[bx] mov al, ds:[bp] mov al, ss:[si] mov al, es:[di]
Intel refers to [bx] and [bp] as base addressing modes and bx and bp as base registers (in fact, bp stands for base pointer). Intel refers to the [si] and [di] addressing modes as indexed addressing modes (si stands for source index, di stands for destination index). However, these addressing modes are functionally equivalent. This text will call these forms register indirect modes to be consistent.
更多寻址模式请参考Art of Assembly: Chapter Four- The 80x86 Addressing Modes。
很显然,没有操作系统对内存进行管理,硬件段机制主要是用来扩展内存,每一条访存指令执行之前不会检查内存访问是否合理,也就不存在保护机制,段的共享也无法实现。
1.3 实模式下硬件怎么计算地址的呢?
1.3.1 汇编代码
1.在编写汇编代码时,将程序组织成不同的段。每一个段内的数据的地址都是相对于段的可重定位的相对偏移地址。从而一个程序的地址空间是一个二维的(x, y),一个维度表示段(0~x),另一个维度表示段内偏移(0~y)。
在x86硬件段机制下,使用段寄存器进行的地址引用(eg.
mov al, [bx]
)可以用< segment, offset >的二元对来表示,其中segment表示段,offset表示段内偏移。在实模式时(real mode),segment就是段寄存器的值,所以< segment:offset >就是物理地址。 segment为16bit,offset是16bit,通过地址运算segment:offset得到一个20位的地址< segment:offset >,这个地址运算的计算按下图方式进行:
![]()
可以看到,段基址是16(4位)的倍数,一共可以取