8086硬件笔记

为了方便学习操作系统,我们必须了解8086的硬件机制。但是在学习的过程中务必要分清主次,即在学习的时候,对于硬件资源应该是“会用就行,简单了解就好”。
8086CPU保护模式是基于两大核心硬件机制而实现的:段机制和页机制。
 要了解段机制我们首先要知道什么是段寄存器。段寄存器是8086CPU提供的形如ds,cs,es等等的寄存器。从下面代码中我们可以看到:段寄存器不能直接赋值。
int main() {
int var = 0;
__asm {
mov ax, ss
mov ds, ax // 将 ss 段选择子代入 ds 段寄存器
mov dword ptr ds:[var], eax // 执行成功!
}
return 0;
}
 执行下面这行代码的时候,它会把 32 位整数 5 写入到地址 0x0012f000 这个位置处。dword 就表示这是一个 double word 宽度的数,一个 word 是 16 bit。
mov dword ptr ds:[0x0012f000], 5
    5被写到了哪里呢?5被存放到ds.base+0012f000所指向的地址空间里,ds.base就是ds中存储的地址。ds.base怎么找的下面再说。    
    段寄存器里面放了什么东西?段寄存器一共96位。其中的16位是可见的,被称为段选择子(selector)。一般来说,选择子包含了三部分内容:
    INDEX:在GDT数组或LDT数组的索引号;
    TI:Table Indicator,这个值为0表示查找GDT,1则查找LDT ;
    RPL:请求特权级。以什么样的权限去访问段。    
    之前复制给ds的值实际上就是选择子,它不是真正的地址,而是ds段的一把钥匙,通过这把钥匙我们可以找到段的所有描述信息。这些钥匙的门就是GDT表,所谓GDT表就是在内存中定义的一个数组。
// 一个 QWORD 是一个 8 字节的整数
QWORD gdt[1024];
 上面这一句代码直接定义了1024个8字节的整数。自已一想,我们除了段选择子还剩64位的段描述符没说,这些描述符正好被填在了这个数组里头。那么一个段描述符到底有哪些描述信息呢?要回答这个问题我们先考虑一下怎么通过选择子找到相应的段描述符。
 假如描述符在线性地址空间中排列如下。
|–地址–|-------------16进制值---------------|
8003f000 0000000000000000 00cf9b000000ffff
8003f010 00cf93000000ffff 00cffb000000ffff
8003f020 00cff3000000ffff 80008b04200020ab
8003f030 ffc093dff0000001 0040f30000000fff
 首先看gdt[1024]这里的索引,[0]号索引代表0000000000000000,注意这里每一个0都是16进制的。那么[3]号索引就是00cffb000000ffff。假如一个段选择子为0x1B,即0b0000 0000 0001 1011,那么我们可以得到段选择子要表述的三大信息:
索引号:0000 0000 0001 1= 3 (查找gdt[3])
RPL: 11b = 3
TI: 0 (查找 GDT 表)
查找到的 GDT 描述符为:gdt[3] = 00cffb000000ffff 这样0x1b这个选择子就和00cffb000000ffff绑定了。段描述符的结构如下所示
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 字节
|76543210|7 6 5 4 3210 |7 65 4 3210|76543210|76543210|76543210|76543210|76543210| 比特
|--------|-|-|-|-|---- |-|–|-|----|--------|--------|--------|--------|--------| 占位
| BASE |G|D|0|A|LIMIT|P|D |S|TYPE|<------- BASE 23-0 ------>|<-- LIMIT 15-0 ->| 含义
| 31-24 | |/| |V|19-16| |P |
|B| |L| | |L |
 BASE: 段基址,由上图中的两部分(BASE 31-24 和 BASE 23-0)组成
 G:LIMIT的单位,该位 0 表示单位是字节,1表示单位是 4KB
 D/B: 该位为 0 表示这是一个 16 位的段,1 表示这是一个 32 位段
 AVL: 该位是用户位,可以被用户自由使用
 LIMIT: 段的界限,单位由 G 位决定。数值上(经过单位换算后的值)等于段的长度(字节)- 1。
 P: 段存在位,该位为 0 表示该段不存在,为 1 表示存在。
 DPL:段权限(这是要访问的目标段的段权限,要和之前的RPL区分)。
 S: 该位为 1 表示这是一个数据段或者代码段。为 0 表示这是一个系统段(比如调用门,中断门等)
 TYPE: 根据 S 位的结果,再次对段类型进行细分。
 先不管这个具体结构怎么用,总的来说,一个段描述符主要表达了三个信息:
 base:段基址(终于找到了!);
    attribute:段的各种信息;
 limit:段长。
attribute = 0xcffb (G = 1 DB = 1 P = 1 DPL = 3 S = 1 TYPE = 1011(非一致代码段,可读已访问过))
base = 0x00000000
limit = 0xffffffff

你可能感兴趣的:(8086硬件笔记)