目录
1.Win32的软硬件平台
(重点:实模式和保护模式的地址空间,内存寻址方式,应用程序的内存管理)
1.80X86系列处理器
自1978年6月Intel公司推出它的第一个16位微处理器8086以来,计算机技术就开始进入飞速发展时期。
8086芯片:采用了20条地址线,可以寻址的范围为2^20字节地址即2^10*2^10字节即1MB;
1985年,该公司推出32位的80386处理器。
80386:地址线扩展到32条,直接寻址能力达到4GB (2^32=4* 2^10 * 2^10 * 2^10);
2.80X86处理器的工作模式
80386处理器有三种工作模式:实模式、保护模式、虚拟86模式
1)实模式
实模式和虚拟86模式是为了和8086处理器兼容而设置的。实模式下,80386处理器就相当于一个快速的8086处理器。
80386处理器被复位或加电的时候以实模式启动。
80386处理器在实模式下的存储方式和8086是一样的,由段寄存器的内容*16当做基地址,加上段内的偏移地址形成最终的物理地址。(这个时候他的32位地址线只用了低20位)
补充:(加深理解)
https://www.cnblogs.com/chenwb89/p/operating_system_002.html
在实模式下,80386处理器不能对内存进行分页管理,所以指令寻址的地址就是内存中实际的物理地址。
在实模式下,所有的段都是可读、写和执行的。
实模式下,80386不支持优先级,所有的指令相当于工作在特权级(优先级0),所以它可以执行所有的特权指令,包括读写控制寄存器CR0等。
实际上,80386就是通过在实模式下初始化控制寄存器、GDTR、LSTR、TR等管理寄存器以及页表,然后通过加载CR0使其中的保护模式使能位置位(使能位:就是使功能开启关闭的开关。一般用一位0/1来表示。)而进入保护模式的。
实模式下的中断处理方式和8086处理器相同,也使用中断向量表来定位中断服务程序地址。中断向量表的结构也和8086处理器一样,每4字节组成一个中断向量表,其中包括两个字节的段地址和两个字节的偏移地址。
实模式的80386处理器比8086有什么进步呢?
答:可以使用80386的32位寄存器,用32位的寄存器进行编程,使计算机程序更加简捷,加快执行速度。
很多80386的新增指令使得原来不很方便的操作得以简化。如pushad 和popad指令可以一次把所有8个通用寄存器的值压入或从堆栈中弹出。
2)保护模式
保护模式是80386处理器的主要工作模式。 在此方式下,80386可以寻址4GB的地址空间。同时,保护模式提供了80386先进的 多任务、内存分页管理和优先级保护等机制。
保护模式出现的原因是:保护进程地址空间。
当80386工作在保护模式下的时候,它的所有功能都是可用的。这时80386所有的32根地址线都可供寻址,物理寻址空间高达4GB。
在保护模式下,支持内存分页机制,提供了对虚拟内存的良好支持。
虽然与8086可寻址的1MB地址空间相比,80386可寻址的物理地址空间可谓很大,但实际的微机系统极少安装如此大的物理内存。
所以为了运行大型程序和真正实现多任务,虚拟内存是一种必须的技术。
保护模式下80386支持多任务,可以依靠硬件仅在一条指令中实现任务切换。任务环境的保护工作是由处理器自动完成的。在保护模式下,80386处理器还支持优先级机制,不同程序可以运行在不同的优先级上。
优先级分为4个级别(0级到3级),操作系统运行在高的优先级0上,应用程序则运行在比较低的级别上:配合良好的检查机制后,既可以在任务间实现数据的安全共享也可以很好地隔离各个任务。
从实模式切换到保护模式是通过修改控制寄存器CR0的控制位PE(位0)来实现的。在这之前还需要建立保护模式必须的一些数据表,如全局描述符表GDT和中断描述符表IDT等。
DOS操作系统运行于实模式下,而Windows操作系统运行于保护模式下。
补充:(加深理解)
https://www.cnblogs.com/chenwb89/p/operating_system_002.html
3)虚拟86模式
为了在保护模式下继续提供和8086处理器的兼容,80386又设计了一种虚拟86模式,以便可以在保护模式的多任务条件下,有的任务运行32位程序,有的任务运行MS-DOS程序(16位微软磁盘操作系统)。
虚拟86模式以保护模式为基础,以任务形式在保护模式上执行的,在80386上可以同时支持由多个真正的80386任务和虚拟86模式构成的任务。在虚拟86模式下。80386支持任务切换和内存分页。
在虚拟86模式下,同样支持任务切换、内存分页管理和优先级,但内存的寻址方式和8086相同,也是可以寻址1MB空间。
虚拟86模式采用和8086一样的寻址方式,即用 段寄存器*16+偏移地址=线性地址,寻址空间为1MB。但显然多个虚拟86任务不能同时使用同一位置的1MB地址空间,否则会引起冲突。操作系统利用分页机制将不同的86任务的地址空间映射到不同的物理地址上去,这样每个虚拟86任务看起来都认为自己在使用0~1MB的地址空间。
4)三种模式的转换
5)三种模式的对比
2.Windows内存管理
1)实模式下的寻址方式
实模式下的地址:由段地址和偏移地址两部分组成。段地址放在16位段寄存器中,然后在指令中使用16位的偏移地址寻址。处理器换算时,先将段地址乘以10h,得到段在物理内存中的起始地址;然后再加上16位的偏移地址得到实际的物理地址。
如xxxx:yyyy格式的虚拟地址在内存中的实际位置是xxxx *10h+yyyy。
即:
注意:实模式20根地址线,寻址空间是1M,不支持内存分页,线性地址即为物理地址。
由于段内偏移地址是16位的,因此,线性地址空间由一系列64KB大的段组成(一个地址上存放一个字节)。
产生一个疑问:关于为什么在上面实地址模式要分段?
https://blog.csdn.net/yafeixi/article/details/52189528
8086CPU有20根地址线,最大可寻址内存空间为1MB。而8086的寄存器只有16位,指令指针(IP)和变址寄存器(SI、DI)也是16位的。
用16位的地址寻址1MB空间是不可能的。所以就要把内存分段,也就是把1MB空间分为若干个段,每段不超过64KB,在8086中设置4个16位的段寄存器,用于管理4种段:CS是代码段,DS是数据段,SS是堆栈段,ES是附加段。
把内存分段后,每一个段就有一个段基址,段寄存器保存的就是这个段基址的高16位,
这个16位的地址左移四位(后面加上4个0)就可构成20位的段基址。
2)保护模式下的内存寻址
当80386处理器工作在保护模式和虚拟8086模式的时候,可以使用全部32根地址线访问4GB大的内存。段地址加偏移地址的计算方法显然无法覆盖这么大的范围。
因为80386所有的通用寄存器都是32位的,2^32相当于4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经可以访问到所有的内存地址。
那是不是说,在保护模式下,段寄存器就不再有用了呢?答案不是的。
实际上段寄存器更有用了。
虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。
要解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途。
但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用64位长的数据才能表示。
我们把这64位的属性数据叫做段描述符。
80386的段寄存器是16位的,无法放下保护模式下64位的段描述符。那么如何解决这个问题?
解决办法就是把所有的段描述符顺序放在内存中指定的位置,组成一个段描述符表(Descriptor Table)。
而段寄存器中的16位用来做索引信息,指定这个段的属性用段描述符表的第几个描述符来表示。
这个时候,段寄存器中的信息就不再是段地址了,而是段选择器(Segment Selector)。
可以通过它在描述符表中“选择”一个项目以得到段的全部信息。
既然这样,那么段描述符表放在哪里呢?
80386中引入了两个新的寄存器来管理段描述符表。
一个是 48位 全局描述符表寄存器 GDTR,一个是 16位 的局部描述符表寄存器LDTR。
那么,为什么要有两个描述符表呢?
GDTR 指向的描述符表为全局描述符表 GDT(Global Descriptor Table)。它包含系统中所有任务都可用的段描述符,通常包含描述操作系统所使用的代码段、数据段、堆栈段、堆栈段的描述符、各任务的LDT段等。
全局描述符表只有一个。
LDTR 则指向局部描述符表LDT(Local Descriptor Table)。80386处理器 设计成 每个任务都有一个独立的LDT。 它包含有每个任务的私有的代码段、数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符,如任务门和调用门描述符等。
不同任务的局部描述符表组成不同的内存段,描述这些内存段的描述符当做系统描述符放在全局描述符表中。
和GDTR直接指向内存地址不同,LDTR和CS、DS等段选择器一样只存放索引值,指向局部描述符表中内存段对应的描述符在全局描述符表 中的位置。
随着任务的切换,只要改变LDTR的值,系统当前的局部描述符表LDT也随之切换,这样便于各任务之间数据的隔离。
但GDT并不随着任务的切换而切换。
那么,既然有两个表,段选择器中的索引值应该对应哪个表中的描述符呢?
实际上,16位的段选择器中只有高13位表示索引值,剩下的3个数据位中,第0,1位表示程序的当前优先级RPL;第2位TI位用来表示在段描述符表的位置;
TI=0,表示在GDT中
TI=1,表示在LDT中
LDT
ps:每个任务都有一个LDTR,所以LDTR的索引值对应不同的LDT描述符
···关于实模式和保护模式的分段?
一个是早期实模式下,寄存器16位,地址线20位。为了用16位的寄存器寻址20位的地址,引入了段(segment)的概念,所有的段都在一个地址空间。第二个是保护模式下,段(segmentation)强调的是分割,用来把内存分成不同的地址空间,每个段一个空间,而后通过CPU的MMU(MMU是Memory Management Unit的缩写,中文名是内存管理单元,有时称作分页内存管理单元)转换成实际物理地址。由于程序运行在不同的段里,根本上保护了CPU保护模式下的各个不相关的代码,所谓进程或者作业。
3)内存分页机制
在实模式下寻址的时候,“段寄存器+偏移地址”经过转换计算以后得到的地址是“物理地址”,也就是在物理内存中的实际地址。而保护模式下,“段选择器+偏移地址”转换后的地址被称为“线性地址”而不是“物理地址”。那么,线性地址就是物理地址吗?
答案可能是也可能不是,
这取决于80386的内存分页机制是否被使用。
在单任务的DOS系统中,一个应用程序可以使用所有的空闲内存。程序退出后,操作系统回收所有的碎片内存并且合并成一个大块内存继续供下一个程序使用。内存合并过程中的一个极端情况是当系统中有多个TSR程序时,早装入内存的TSR被卸载后,后装入的TSR会留在内存的中间部位,把空闲内存隔成两个区域。这时应用程序使用的最大内存块只能是这两块内存中较大的一块,无法将它们合并使用。
注:
TSR
终止并驻留 (terminate-and-stay-resident) 的缩写。tsr 程序采用“后台”方式运行。大多数 tsr 程序均有一个预定义的组合键(有时称作“热键”),使您可以在运行其它程序时启用 tsr 程序接口。运行 tsr 程序后,您可以返回其它应用程序,并将 tsr 程序保存在内存中以备后用。
功能:执行后,进入内存,但什么也不做。当你按下其事先设定的激活键后,TSR程序调出,并执行相关功能。
大多是dos下的,比如bios,显卡驱动,dos鼠标驱动,输入法,高端内存分配等等
对于一个多任务的操作系统,内存的碎片化是不能容忍的。否则,经过一段时间后,即使空闲内存的总和很大,也可能出现任何一片内存都小到无法装入执行程序的地步。所以多任务操作系统中碎片内存的合并是个很重要的问题。
80386处理器的分页机制可以很好的解决这个问题。
80386处理器把4KB大小的一块内存当做一“页”内存,每页内存可以根据“页目录”和“页表”,随意映射到不同的线性地址上。这样,就可以将物理地址不连续的内存映射连到一起,在线性地址上视为连续。
在80386处理器中,除了和CR3寄存器(指定当前页目录的地址)相关的指令使用的是物理地址外,其他所有指令都是用线性地址寻址的。
是否启用内存分页机制是由80386处理器新增的CR0寄存器中的位31(PG位)决定的。
如果PG=0,则分页机制不启用,这时所有指令寻址的地址(线性地址)就是系统中实际的物理地址。
当PG=1时,80386处理器进入内存分页管理模式,所有的线性地址要经过页表的映射才得到最后的物理地址。
内存分页管理只能在保护模式下才可以实现,实模式不支持分页机制。但不管在哪种模式下,所有的寻址指令使用的都是线性地址,程序不用关心数据最后究竟存放在物理内存的哪个地方。
页表规定的不仅是地址的映射,同时还规定了页的访问属性,如是否可写、可读、可执行等。比如把代码所在的内存页设置为可读与可执行,那么权限不够的代码向它写数据就会引发保护异常。利用这个机制可以在硬件层次上支持虚拟内存的实现。
回顾:
☆1.保护模式支持内存分段模型。保护模式与实模式的主要区别在于:段寄存器中存放的不再是段基址,而是描述符表的索引。保护模式下对内存的分段是强制的,分页是可选的。
☆2.保护模式下内存寻址时,16位的段寄存器存放的不是段基地址,而是描述符表的索引地址,段内偏移地址长度32位;段描述符是64位,因为需要包含地址空间定义的一些安全属性;