80386 和 保护模式
- 格式:doc
- 大小:364.50 KB
- 文档页数:19
内存寻址的三种模型1. 地址的种类首先明确一下逻辑地址和线性地址这两个概念:1. 逻辑地址2. 线性地址3. 物理地址1.1 逻辑地址:逻辑地址是编译器生成的,我们使用在linux环境下,使用C语言指针时,指针的值就是逻辑地址。
对于每个进程而言,他们都有一样的进程地址空间,类似的逻辑地址,甚至很可能相同。
1.2 线性地址:线性地址是由分段机制将逻辑地址转化而来的,如果没有分段机制作用,那么程序的逻辑地址就是线性地址了。
1.3 物理地址物理地址是CPU在地址总线上发出的电平信号,要得到物理地址,必须要将逻辑地址经过分段,分页等机制转化而来。
2. 三种寻址模型x86体系结构下,使用的较多的内存寻址模型主要有三种:1. 实模式扁平模型real mode flat model2. 实模式分段模型real mode segment model3. 保护模式扁平模型protected mode flat model下面是对这三种模型的描述实模式和保护模式相对,实模式运行于20位地址总线,保护模式则启用了32位地址总线,地址使用的是虚拟地址,引入了描述符表;虽然二者都引入了段这样一个概念,但是实模式的段是64KB固定大小,只有16KB个不同的段,CS,DS等存储的是段的序号(想想为什么?)。
保护模式则引入了GDT和LDT段描述符表的数据结构来定义每个段。
扁平模型和分段模型相对,区别在于程序的线性地址是共享一个地址空间还是需要分成多个段,即为多个程序同时运行在同一个CS,DS的范围内还是每个程序都拥有自己的CS,DS:前者(flat)指令的逻辑地址要形成线性地址,不需要切换CS,DS;后者的逻辑地址,必须要经过段选择子去查找段描述符,切换CS,DS,才能形成线性地址。
3. 实模式扁平模型该模式只有在386及更高的处理器中才能出现!80386的实模式,就是指CPU可用的地址线只有20位,能寻址0~1MB的地址空间。
80386简介(一)==============linux的早期版本,也是本课讲解的版本,是在80386上实现的,需要对该CPU先有个粗浅的了解。
重点是保护模式的几个概念。
注意:操作系统是管理硬件的程序,CPU的设计者与操作系统设计者的相互依赖是很强的。
80386是INTEL 1985年推出的CPU芯片,是80x86系列中第一个32位微处理器。
80386的内部和外部数据总线都是32位。
地址总线也是32位,可寻址高达4GB内存。
80386具有实模式、保护模式、虚86(V86)等三种工作方式。
系统加电时自动处于实模式,当操作系统初始化完成,操作系统可将其设为保护模式。
1实模式实模式是为了兼容于8086。
只使用20位地址总线,可寻址1M内存,物理地址=左移4位的段地址+偏移地址,等等,这些内容在“组成原理”中都过。
实模式寻址能力有限,而且不能为操作系统内核提供安全保护,比如它没有管态、目态。
没有为多道程序提供必要的支持,比如没有进程空间的隔离功能。
2保护模式可以使用32位地址总线,可寻址高达4GB内存(含虚存)。
但当时的386电脑一般只配1-8M内存,虚存也很小,有些硬盘本身的容量就不够4G。
保护模式和实模式都使用内存段、中断,但二者有很多不同。
在实模式中内存被划分成段,每个段的大小为64KB,这样段地址可以用16位表示。
有几个段寄存器(CS、DS、SS和ES),物理地址=左移4位的段地址+偏移地址。
而在保护模式下,段是通过一系列被称之为"描述符表"的表所定义的。
段寄存器存储的是指向这些表的指针,段长也不再固定为64位,而是可变的。
用于定义内存段的表有两种:全局描述符表(GDT)和局部描述符表(LDT)。
“描述符”是一个32位的地址指针。
GDT是一个段描述符数组,其中包含所有应用程序都可以使用的基本描述符。
每一个操作系统只定义一个GDT。
LDT也是段描述符的一个数组。
与GDT不同,LDT是一个段,每一个正在运行的进程都有一个自己的LDT。
Intel80386CPUIntel 80386 CPU簡單了解運⾏模式⼀般CPU只有⼀种运⾏模式,能够⽀持多个程序在各⾃独⽴的内存空间中并发执⾏,且有⽤户特权级和内核特权级的区分,让⼀般应⽤不能破坏操作系统内核和执⾏特权指令。
80386处理器有四种运⾏模式:实模式、保护模式、SMM模式和虚拟8086模式。
这⾥对涉及ucore的实模式、保护模式做⼀个简要介绍。
实模式:这是个⼈计算机早期的8086处理器采⽤的⼀种简单运⾏模式,当时微软的MS-DOS操作系统主要就是运⾏在8086的实模式下。
80386加电启动后处于实模式运⾏状态,在这种状态下软件可访问的物理内存空间不能超过1MB,且⽆法发挥Intel 80386以上级别的32位CPU的4GB内存管理能⼒。
实模式将整个物理内存看成分段的区域,程序代码和数据位于不同区域,操作系统和⽤户程序并没有区别对待,⽽且每⼀个指针都是指向实际的物理地址。
这样⽤户程序的⼀个指针如果指向了操作系统区域或其他⽤户程序区域,并修改了内容,那么其后果就很可能是灾难性的。
保护模式:保护模式的⼀个主要⽬标是确保应⽤程序⽆法对操作系统进⾏破坏。
实际上,80386就是通过在实模式下初始化控制寄存器(如GDTR,LDTR,IDTR与TR等管理寄存器)以及页表,然后再通过设置CR0寄存器使其中的保护模式使能位置位,从⽽进⼊到80386的保护模式。
当80386⼯作在保护模式下的时候,其所有的32根地址线都可供寻址,物理寻址空间⾼达4GB。
在保护模式下,⽀持内存分页机制,提供了对虚拟内存的良好⽀持。
保护模式下80386⽀持多任务,还⽀持优先级机制,不同的程序可以运⾏在不同的特权级上。
特权级⼀共分0~3四个级别,操作系统运⾏在最⾼的特权级0上,应⽤程序则运⾏在⽐较低的级别上;配合良好的检查机制后,既可以在任务间实现数据的安全共享也可以很好地隔离各个任务。
內存架構地址是访问内存空间的索引。
⼀般⽽⾔,内存地址有两个:⼀个是CPU通过总线访问物理内存⽤到的物理地址,⼀个是我们编写的应⽤程序所⽤到的逻辑地址(也有⼈称为虚拟地址)。
Intel 80386 微处理器的存储器管理一、存储器的管理存储器的管理是一种硬件机制,微处理器在总线地址上对物理存储器进行寻址。
但是,为了给程序提供比物理存储器容量更大的空间,就引入了虚拟存储器的概念,它在外存(比如磁盘)的支持来下实现,通常所说的虚拟地址称为逻辑地址。
对80386来说,既有段的管理又有页的管理。
对段和页的管理属于操作系统的职责,80386从硬件上提供管理机制。
二、Intel 80386 微处理器的三种工作方式三种工作方式:实地址方式,虚地址保护方式,虚拟8086方式。
1. 实地址方式80386在硬件复位后处于该模式下,只能使用32位地址总线的低20位地址,寻址空间为1MB。
此时他就是一个8086/8088微处理器,不同的是它不仅可以运行8086/8088的全部指令,还可以运行32位的运算类指令。
系统初始化区在FFFFFFF0H-FFFFFFFFH存储区内。
设置此方式是为了与8086兼容,也可从实地址方式转变到保护虚地址方式。
物理地址由8386芯片地址引线送出的低的20位地址码,经过存储器译码后选择一个存储单元进行读写,物理地址可用5位的十六进制来表示20位的地址。
储器地址分段是把1MB 的存储器空间分成若干段,每段的容量最大为64KB,每个段首地址的高16位二进制代码就是该段的段号(称段基地址)。
存储器采用分段管理后,段地址存放在段寄存器CS、DS、SS、ES中,对段寄存器设置不同的值来使微处理器的段寄存器指向存储器中不同的段。
偏移地址是相对于某段首地址的段内偏移量。
物理地址的形成,把段地址左移4 位得到段基地址,再加上偏移地址值就形成了20 位的物理地址。
计算表示方式如下:段地址×10H+偏移地址=物理地址80386在实地址方式下的地址转换如图一:2.虚地址保护方式当Intel 80386/486 的控制寄存器CR0 的最低位为PE(Protection Enable)保护模式允许位,用来启动CPU进入虚地址保护方式。
1用二进制好处?答:二进制数在电气元件中容易实现、容易运算,在电子学中具有两种稳定状态以代表0和1。
而需要由0和1来代表的量很多。
如:电压的高和低,电灯的亮和灭,电容的充电和放电,脉冲的有和无,晶体管的导通和截止等。
电路中把正负极(高低电平)分别用0,1或者1,0来表示。
就用这些0,1,或者它们的组合,例如001,00,011,100,111等等来传递信息或命令。
总之,二进制在电路上很容易实现,然后把它作为基础可以扩展成四进制,八进制,十六进制等等,来实现更多的功能。
2.RET,CALL,IRET:答CALL: CPU先将下一条指令的地址压入堆栈保护起来,然后再将子陈旭入口地址赋给IP(或CS,IP),以便转到子程序执行。
RET:一般安排在程序末尾,执行RET时,CPU将堆栈顶部保留的返回地址弹到IP(或CS,IP),这样既可返回到CALL的下一条指令,继续执行主程序。
IRET:从中断服务子程序返回到被中断的程序继续执行。
先将堆栈中的断点地址弹道IP ,CS,接着将INT指令执行时压入堆栈的标志弹道标志寄存器,回复中断前的标志状态。
3堆栈和堆栈指针的区别堆栈式内存中的一个特定的区域,用以存放寄存器或者存储器中暂时不用又必须保存的数据,我们可以将堆栈看做是一个小存储器但不能随意存储。
Sp为堆栈指针寄存器,他在堆栈操作中存放栈顶偏移地址,永远指向堆栈的栈顶,在访问堆栈时作为指向堆栈的指针,在压入操作之前sp-2,弹出一个字,sp+2.4说明伪指令和机器指令的区别?机器指令是功能性语句,能够实现一定的操作功能,能够被翻译成机器代码;伪指令语句是指示性语句,只是为汇编程序在翻译成汇编语言时提供相关信息,并不产生机器代码。
5接口电路与系统总线相连时为什么要遵循“输入要经三态,输出要锁存”的原则?接口电路是介于主机和外设之间的一种缓冲电路,它使外设与总线隔离,起缓冲、暂存数据的作用。
因为数据总线是各种设备以及存储器传送数据的公共总线,任何设备都不允许长期占用数据总线,而仅允许被选中的设备在读/写周期中享用数据总线,这就需要接口电路为输入设备提供三态缓冲作用,只在读/写周期中为被选中的设备开放与系统数据总线的连接,即输入要经三态;另外,通过对CPU的输出总线周期的分析,相对于普通外设而言,CPU的输出周期很短,即#WR信号有效电平持续时间很短,无数据锁存能力的输出设备要在很短的时间内接收数据并驱动是几乎不可能的,所以需加锁存器锁存数据,在输出总线周期结束后,保持该数据提供外设使用,以协调主机和外设间数据传送速度不匹配的矛盾,即输出要锁存6请说明80386、80486CPU在存储器管理机制上有哪三种工作模式?80386有三种工作模式:实模式、保护模式和虚拟86模式。
INTEL 80383 程序员参考手册第十章初始化当RESET引脚有信号后,80386的某些寄存器被设置为预定义值。
这些预定义值对于执行引导程序来说已经足够了,但是为了利用处理器的所有特性,软件必须做一些额外的初始化工作。
10.1 复位后的处理器状态EAX的内容取决于上电自检的结果。
自检由复位结束后外部声明BUSY#来决定。
如果自检通过,EAX为零。
非零值表示80386的某些单元出错。
如果不要求自检,则EAX的值未定义。
复位后,DX包含部件标识符和版本号,如图10-1所示。
DH为3,表示80386。
DL包含一个唯一的代表版本等级的标识符。
控制寄存器0(CR0)中的值如图10-2所示。
如果配置了(取决于上电复位后ERROR#引脚的状态)80387,CR0的ET位被置位。
如果ET被复位,则说明配置了80287或者没有协处理器。
对于后面的两种情况,需要在软件中做测试加以区分。
其他寄存器和标志位设置如下:EFLAGS =00000002HIP =0000FFF0HCS selector =000HDS selector =0000HES selector =0000HSS selector =0000HFS selector =0000HGS selector =0000HIDTR:base =0所有没有提到的寄存器为未定义。
这些设置暗示处理器开始了实地址模式,中断被关闭。
10.2 实地址模式的软件初始化在实地址模式下,为了获得该模式下的所有特性,一些结构必须被初始化。
10.2.1 堆栈在堆栈段寄存器装载之前,任何使用堆栈的指令都不能执行。
SS必须指向内存中的某个区域。
10.2.2 中断表中断在80386的初始化状态为不可用状态;然而,当异常或不可屏蔽中断(NMI)发生时,处理器仍然会试图访问中断表。
初始化软件应该执行一下某个动作:●把IDTR中的上限值改为零。
这将导致在有异常或不可屏蔽中断发生的时候导致宕机。
80386 和保护模式___William LiuIntel CPU 一般可以运行在两种模式之下,即实模式和保护模式。
早期的 Intel CPU ( 8086 , 8088 )只能工作在实模式之下,系统中只能运行单个任务,而且只能使用实地址模式。
对于 Intel 80386 以上的芯片则还可以运行在 32 位的保护模式之下。
在保护模式之下的 CPU 可以支持多任务;支持 4GB 的物理内存;支持 64TB 的虚拟内存;支持内存的页式管理和段式管理以及支持特权级。
本文档将首先介绍 Intel 80386 CPU 的几个内部寄存器,然后再由浅入深的分别介绍保护模式下的段式管理,页式管理,虚拟内存,多任务以及特权级管理等几个方面。
Intel 80386 CPU 的内部寄存器这一部分先大致介绍一下 386 的内部寄存器,具体细节在后面的几节中再详细说明。
一般来说, CPU 设计用来系统编程的系统寄存器包括如下几类:•标志寄存器 (EFLAGS)•内存管理寄存器 (GDTR , LDTR , IDTR , TR)•控制寄存器 (CR0 , CR1 , CR2 , CR3 , CR4)•兼容 8086 通用寄存器( EAX , EBX , ECX , EDX )•兼容 8086 段寄存器( CS , DS , ES , SS , FS , GS )•兼容 8086 数据寄存器( ESI , EDI , EIP , ESP )下面分别加以介绍:1) 标志寄存器 EFLAGS :跟 8086/8088 的 FLAGS 大致差不多。
只不过位宽由 16bit 变成了 32bit ,负责的状态标志也多了一些。
见图一所示:图一: EFLAGS 的结构其中系统标志: VM -虚拟 8086 模式; RF -恢复标志; NT -任务嵌套标志;IOPL - I/O 特权级标志; IF -中断允许标志。
2) 内存管理寄存器:一共有 4 个,用于分段内存管理,都是用于存放指针的,只是所指的再内存单元中的内容有所不同。
GDTR 全局描述符表寄存器( Global Descriptor Table Register ),存放的是一个指向内存单元列表的指针,用于指向全局段描述表( GDT ),如图二所示。
共 48bit ,高 32bit 是 GDT 的基址,低 16bit 描述 GDT 的长度。
由于每项 8Byte ,所以共可以有 2^(16)/8=2^13 项。
IDTR 中断描述符表寄存器( Interrupt Descriptor Table Register ),存放的是也一个指向内存单元列表的指针,用于指向全局中断描述符表( IDT ),如图二所示。
跟 GDTR 一样,共 48bit 。
LDTR 局部描述符表寄存器( Local Descriptor Table Register ),存放的是LDT 的段选择字。
用于从 GDT 中索引出当前任务的局部描述符表( LDT ),如图二所示。
共 16bit ,高 13bit 刚好可以索引到 GDT 的最大限长。
TI 位置1 , RPL 是请求特权级( Request Privilege Level )用于特权检查。
TR 任务寄存器( Task Register ),跟 LDTR 一样,存放的是任务状态段 TSS ( Task State Segment )的段选择字。
用于从 GDT 中索引出当前任务的 TSS ,如图二所示。
共 16bit 。
图二:系统内存管理寄存器3) 系统控制寄存器:386 CPU 共四个,分别是 CR0 、 CR1 、 CR2 、 CR3 , 486 以后又增设了 CR4 。
如图三所示。
其中, CR0 是用于系统整体的控制。
CR1 保留。
CR2 用于保存页面转换时出错的线性地址。
CR3 存放页目录基址。
CR4 用于各种 CPU 级联相关。
图三:系统控制寄存器需要注意的几个位是:PE : CR0 的 0bit , Protect Enable 。
使能 386 的保护模式。
PG : CR0 的 31bit , Paging 。
386 进入保护模式之后,启动分页机制。
Page-Directory Base : CR3 的 12 - 31bit 存放页目录首地址。
每个任务只能唯一一个Page-Fault Linear Address : CR2 线性地址错误。
可以用于虚拟内存中4) 与 8086 兼容的系列寄存器:所有通用寄存器 EAX , EBX , ECX , EDX 和所有数据寄存器 EIP , ESP ,ESI , EDI 除了数据位由原来的 16bit 编程 32bit 外,功能基本没有变化。
当然为了保持对 16 位机的支持,你同样可以使用 AX , AH , AL , IP , SP ,SI , DI 等等至于段寄存器 CS , DS , ES , FS , GS , SS 。
你会发现名字都没有变化,事实上大小也是 16bit ,只是增加了几个。
事实上, 386 在运行实模式时这些段寄存器跟 8086 是完全一样的。
在运行于保护模式下时,他们同样用来指示段的地址,只不过里面存放的是段选择符,通过在 LDT 或者 GDT 中检索,间接的指示段地址。
保护模式下的段式管理段式管理的目的是根据段基址值和段内数据的偏移值,生成数据在内存中的线性地址。
在实模式中该线性地址既是实际的物理地址;在保护模式下,如果用户选择了使用分页管理机制,那么该线性地址还要经过页式变换才能生成最后的物理地址。
我们知道在实模式下:物理地址=线性地址=段基址值(由段寄存器给出)× 16 +偏移地址但是在保护模式下,就没有这么简单了 :P在保护模式下,用户要使用段式管理,必须至少维护好一张 GDT 列表(通过 GDTR 来指示),和若干张 LDT 列表(可以没有)。
如果我们要访问数据段中偏移值为 XX (放于 ESI 中)的变量。
CPU 的操作过程如下:1 ) CPU 首先读取 DS 中的段选择字。
注意这里 DS 中存放的不再是段基址了,而是保护模式下的段选择字,格式如图四所示(是不是觉得跟 LDTR 和 TR 的格式一样 ^_^ )图四,段选择字的格式(共 16 位)这里, RPL 是请求特权级( Request Privilege Level )用于特权检查,如果段寄存器是 CS 那么这里的 RPL 也叫 CPL ( Current Privilege Level )表示当前任务的特权级别。
TI 位为 1 时检索 GDT 表,为 0 时检索 LDT 表。
Index 是索引号。
比如 CS = 0x80 表示,当前任务的特权级别为 0 ,对应于GDT 表中的第 1 项。
(在 linux 中,这里放的是系统内核代码段的描述符)2 ) CPU 通过分析上述的段选择字,找到位于 GDT 或者 LDT 中相应的段描述符。
80386 共有四种段描述符和3 种门描述符。
分类如下:注意:门描述符我们将在后面介绍保护模式下的中断时再介绍各种描述符长度都为 8Byte ,格式如下图五所示:图五:各种段描述符和门描述符S = 0 表示是系统段。
1 表示是存储段Segment Limit 共 20bit ,表示相应段的长度,单位参考 G 标志Base Address 共 32bit ,表示相应段的基址G = 1 表示 limit 的单位是 4KB , 0 表示 limit 的单位是 1BP = 1 表示当前段存在于内存中,用户可以读写。
0 表示当前段不存在,用户访问时会产生一个 #NP 的异常。
可以用来实现虚拟内存。
Type 各个字段的意义如下:段类型Type 说明Type 说明S=1 S=0数据段0 只读0 未定义1 只读、已访问 1 可用 286TSS2 读 / 写 2 LDT3 读 / 写、已访问 3 忙的 286TSS4 只读、向下扩展 4 286 调用门5 只读、向下扩展、已访问 5 任务门6 读 / 写、向下扩展 6 286 中断门7 读 / 写、向下扩展、已访问7 286 陷阱门代码段8 只执行8 未定义9 只执行、已访问9 可用 386TSSA 执行 / 读 A 未定义B 执行 / 读、已访问 B 忙的 386TSSC 只执行、一致码段 C 386 调用门D 只执行、一致码段、已访问 D 未定义E 执行 / 读、一致码段 E 386 中断门F 执行 / 读、一致码段、已访问F 386 陷阱门这里我们主要关注 S = 1 的情况,也即数据段或者代码段。
S = 0 的情况后面会介绍到。
3 ) CPU 通过加载数据段断或者代码段的描述符,获取到相应段的基址。
4 )将获得的基址跟偏移地址相加得到所需变量的线性地址。
整个过程如下图六和图七:图六:选择字中 TI = 1 ,从 GDT 中检索的情况图七:选择字中 TI = 0 ,从 LDT 中检索的情况最后要强调的是,这里生成的 32 位线性地址并不一定是最后的物理地址。
在linux 和 windows 下都需要进行分页转换之后,才能生成真正的物理地址。
保护模式下的页式管理在 80386 下页式管理是可选的。
如果同时设置了 CR0 的 PE 位和 PG 位,则启动了分页机制。
将 32 位线性地址变换为物理地址,从地址总线上输出。
先介绍几个概念:页框(帧)( Page Frame )、页表( Page Table )、页表项( Page-Table Entries )以及页转换高速缓存。
•页框:物理内存中,地址连续的 4KB 单元,大小固定,且以 4KB 地址对齐。
简称页。
•页表:本身占一页内存。
用于存放页框的索引。
因为每个页框用 32bit 来索引,所以一个页表最多可以索引 1K 个页框。
一个任务中最多可以有 1K 个页表•页表项:页表中的元素。
用来索引页框。
格式如下图八:图八,页表项的格式由于页框是与 4KB 地址对齐的,也即页框首地址的低 12 位为零。
所以只需要知道高 20 位即可索引到对应的页框。
•页目录表:和页表相似,只不过使用来索引页表的。
相应地可以用来索引 1K 个页表。
一个任务中只能有一个页目录表。
通过 CR3 索引页目录表项:页目录表中的元素。
用来索引页表。
格式如下图九:图九:页目录项的格式注意:上面页目录项和页表项的格式中:1 . P ( present ) 1 表示该页或页表存在于内存中,可以进行页面转换。
0 表示该页不在内存中,访问时会产生页错误异常( page-fault , #PF )如果出现页错误异常,一般来说操作系统的缺页中断异常处理程序应该:•从磁盘将该页拷贝入内存空间•将该页加载到页表项或者页目录项中。