思勤无邪

上学时,因我年龄最小,个头也最小,上课时,就像大猩猩堆里的猴一般。如今,这猴偶尔也把最近的一些情况写在这里。

   :: 首页 :: 联系 :: 聚合  :: 管理
  132 Posts :: 1 Stories :: 178 Comments :: 0 Trackbacks

公告

     吾日常三省吾身,曰思、曰勤、曰无邪。

积分与排名

  • 积分 - 157114
  • 排名 - 142

最新随笔

最新评论

阅读排行榜

评论排行榜

第 1 章 背景知识
1.1 Win32的软硬件平台
1.2 Windows的特色
1.3 必须了解的东西
1.3.1 80x86处理器的工作模式
    80386处理器有3种工作模式:实模式、保护模式和虚拟86模式。
    保护模式是80386处理器的主要工作模式。在此方式下,80386可以寻址4 GB的地址空间,同时,保护模式提供了8038的多任务、内存分页管理和优先级保护等机制。
    虚拟86模式是为了在保护模式下提供和8086处理器的兼容,在虚拟86模式下,同样支持任务切换、内存分页管理和优先级,但内存的寻址方式和8086相同,也是可以寻址1MB的空间。
    1. 实模式
    80386处理器被复位或加电的时候以实模式启动。80386处理器在实模式下的存储器寻址方式和8086是一样的,由段寄存器的内容乘以16当做基地址,加上段内的偏移地址形成最终的物理地址,这时候它的32位地址线只使用了低20位。在实模式下,80386处理器不能对内存进行分页管理,所以指令寻址的地址就是内存中实际的物理地址。在实模式下,所有的段都是可以读、写和执行的。实模式下80386不支持优先级,所有的指令相当于工作在特权级(优先级0),所以它可以执行所有特权指令。
    2. 保护模式
    当80386工作在保护模式下的时候,它的所有功能都是可用的。这时80386所有的32根地址线都可供寻址,物理寻址空间高达4 GB。在保护模式下,支持内存分页机制,提供了对虚拟内存的良好支持。在保护模式下,80386处理器还支持优先级机制。优先级分4个级别(0级~3级),操作系统运行在最高的优先级0上,应用程序则运行在比较低的级别上。
    DOS操作系统运行于实模式下,而Windows操作系统运行于保护模式下。
    3. 虚拟86模式
    虚拟86模式是为了在保护模式下执行8086程序而设置的。虽然80386处理器已经提供了实模式来兼容8086程序,但这时8086程序实际上只是运行得快了一点,对CPU的资源还是独占的。虚拟86模式是以任务形式在保护模式上执行的,在80386上可以同时支持由多个真正的80386任务和虚拟86模式构成的任务。在虚拟86模式下,80386支持任务切换和内存分页。在Windows操作系统中,有一部分程序专门用来管理虚拟86模式的任务,称为虚拟86管理程序。为了和8086程序的寻址方式兼容,虚拟86模式采用和8086一样的寻址方式,即用段寄存器乘以16当做基址再配合偏移地址形成线性地址,寻址空间为1 MB。但显然多个虚拟86任务不能同时使用同一位置的1 MB地址空间,否则会引起冲突。操作系统利用分页机制将不同虚拟86任务的地址空间映射到不同的物理地址上去,这样每个虚拟86任务看起来都认为自己在使用0~1 MB的地址空间。
1.3.2 Windows的内存管理
    1. DOS操作系统的内存安排
    DOS操作系统运行于实模式中,由于8086处理器的寻址范围只有1 MB,当时系统硬件使用的存储器地址被安排在高端,地址是从A0000h(即640 KB)开始的384 KB中,其中有用于显示的视频缓冲区和BIOS的地址空间。而在内存低端,安排了中断向量表和BIOS数据区;剩下从500h开始到A0000h总共不到640 KB的内存是操作系统和应用程序所能够使用的;应用程序不可能使用这640 KB以外的内存。这就是著名的“640KB限制”。

DOS Memory.JPG

    2. 80386的内存寻址机制
    因为80386所有的通用寄存器都是32位的,232相当于4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经可以访问到所有的内存地址。这是不是说,在保护模式下,段寄存器就不再有用了呢?答案是否定的。虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。要解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途。但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用64位长的数据才能表示。我们把这64位的属性数据叫做段描述符(Segment Descriptor)。把所有段的段描述符顺序放在内存中的指定位置,组成一个段描述符表(Descriptor Table);而段寄存器中的16位用来做索引信息,指定这个段的属性用段描述符表中的第几个描述符来表示。这时,段寄存器中的信息不再是段地址了,而是段选择器(Segment Selector)。可以通过它在段描述符表中“选择”一个项目以得到段的全部信息。
    80386中引入了两个新的寄存器来管理段描述符表。一个是48位的全局描述符表寄存器GDTR,一个是16位的局部描述符表寄存器LDTR。GDTR指向的描述符表为全局描述符表GDT(Global Descriptor Table)。它包含系统中所有任务都可用的段描述符,通常包含描述操作系统所使用的代码段、数据段和堆栈段的描述符及各任务的LDT段等;全局描述符表只有一个。
    LDTR则指向局部描述符表LDT(Local Descriptor Table)。80386处理器设计成每个任务都有一个独立的LDT。它包含有每个任务私有的代码段、数据段和堆栈段的描述符,也包含该任务所使用的一些门描述符,如任务门和调用门描述符等。
    3. 80386的内存分页机制
    80386处理器把4 KB大小的一块内存当做一“页”内存,每页物理内存可以根据“页目录”和“页表”,随意映射到不同的线性地址上。这样,就可以将物理地址不连续的内存的映射连到一起,在线性地址上视为连续。页表可以指定一个页面并不真正映射到物理内存中。这样,访问这个页的指令会引发页异常错误。这时,处理器会自动转移到页异常处理程序中去。操作系统可以在异常处理程序中将硬盘上的虚拟内存读到内存中并修改页表重新映射,然后重新执行引发异常的指令。这样指令可以正常执行下去。
    4. Windows的内存安排
    如果把虚拟内存暂时先视为物理内存的一部分,从物理内存的层次看,Windows操作系统和DOS一样,也是所有的内容共享内存。但是从应用程序代码的层次看,也就是说从分页映射后线性地址的层次看,内存的安排却不是这个样子。因为Windows是一个分时的多任务操作系统,CPU时间被分成一个个的时间片后分配给不同程序轮流使用,在一个程序的时间片中,和这个程序执行无关的东西(如其他程序的代码和数据)并不需要映射到线性地址中去。在物理内存中,操作系统和系统DLL的代码需要供每个应用程序调用,所以在所有的时间片中都必须被映射;用户程序只在自己所属的时间片内被映射;而用户DLL则有选择地被映射。假设程序A和程序C都要用到xxx.dll,那么物理内存中xxx.dll的代码在图中的时间片1和n中被映射,其他的时间片就不需要映射,当然,物理内存中只需要一份xxx.dll的代码。
    ● 每个应用程序都有自己的4 GB的寻址空间。该空间可存放操作系统、系统DLL和用户DLL的代码,它们之中有各种函数供应用程序调用。再除去其他的一些空间,余下的是应用程序的代码、数据和可以分配的地址空间。
    ● 不同应用程序的线性地址空间是隔离的。虽然它们在物理内存中同时存在,但在某个程序所属的时间片中,其他应用程序的代码和数据没有被映射到可寻址的线性地址中,所以是不可访问的。从编程的角度看,程序可以使用4 GB的寻址空间,而且这个空间是“私有”的。
    ● DLL程序没有自己“私有”的空间。它们总是被映射到其他应用程序的地址空间中,当做其他应用程序的一部分运行。原因很简单,如果它不和其他程序同属一个地址空间,应用程序该如何调用它呢?
    5. 从Win32汇编的角度看内存寻址
    Win32汇编中的内存访问为用户程序的代码段、数据段和堆栈段全部预定义好了段描述符。这些段的起始地址为0,限长为ffffffff,所以用它们可以直接寻址全部的4 GB地址空间。程序开始执行的时候,CS,DS,ES和SS都已经指向了正确的描述符,在整个程序的生命周期内,程序员不必改动这些段寄存器,也不必关心它们的值究竟是多少(实际上是想改也改不了)。
    1.3.3 Windows的特权保护
    1. 80386的中断和异常
    8086或80386实模式下中断和异常的处理过程:实模式下的中断和异常服务程序地址存放在中断向量表中。中断向量表位于物理内存00000h开始的400h字节中,共支持100h个中断向量;每个中断向量是一个xxxx:yyyy格式的地址,占用4字节。当发生n号异常或n号中断,或者执行到int n指令的时候,CPU首先到内存n×4的地方取出服务程序的地址aaaa:bbbb;然后将标志寄存器、中断时的CS和IP压入堆栈,接着转移到aaaa:bbbb处执行;在服务程序最后遇到iret的时候,CPU从堆栈中恢复标志寄存器,然后取出CS和IP并返回。
    在保护模式下,中断或异常处理往往从用户代码切换到操作系统代码中执行。由于保护模式下的代码有优先级之分,为了使高优先级的代码能够安全地被低优先级的代码调用,保护模式下增加了“门”的概念。“门”指向某个优先级高的程序所规定的入口点,所有优先级低的程序调用优先级高的程序只能通过门重定向,进入门所规定的入口点。保护模式下的中断和异常等服务程序也要从“门”进入,80386的门分为中断门、自陷门和任务门几种。
    在保护模式下要表示一个中断或异常服务程序的信息需要用8个字节,包括门的种类以及xxxx:yyyyyyyy格式的入口地址等。这组信息叫做“中断描述符”。保护模式下把所有的中断描述符放在一起组成“中断描述符表”IDT(Interrupt Descriptor Table)。IDT不再放在固定的地址00000h处,而是采用可编程设置的方式,支持的中断数量也可以设置。为此80386处理器引入了一个新的48位寄存器IDTR。IDTR的高32位指定了IDT在内存中的基址(线性地址),低16位指定了IDT的长度,相当于指定了可以支持的中断数量。
    2. 80386的保护机制
    保护机制主要由下列几方面组成:
    ● 段的类型检查——段的类型是由段描述符指定的,主要属性有是否可执行,是否可读和是否可写等。而CS,DS和SS等段选择器是否能装入某种类型的段描述符是有限制的。如不可执行的段不能装入CS;不可读的段不能装入DS与ES等数据段寄存器;不可写的段不能装入SS等。如果段类型检查通不过,则处理器会产生一般性保护异常或堆栈异常。
    ● 页的类型检查——除了可以在段级别上指定整个段是否可读写外,在页表中也可以为每个页指定是否可写。对于特权级下的执行代码,所有的页都是可写的。但对于1,2和3级的代码,还要根据页表中的R/W项决定是否可写,企图对只读的页进行写操作会产生页异常。
    ● 访问数据时的级别检查——优先级低的代码不能访问优先级高的数据段。80386的段描述符中有一个DPL域(描述符优先级),表示这个段可以被访问的最低优先级。而段选择器中含有RPL域(请求优先级),表示当前执行代码的优先级。只有DPL在数值上大于或等于RPL值的时候,该段才是可以访问的,否则会产生一般性保护异常。
    ● 控制转移的检查——在处理器中,有很多指令可以实现控制转移,如jmp,call,ret,int和iret等指令。但优先级低的代码不能随意转移到优先级高的代码中,所以遇到这些指令的时候,处理器要检查转移的目的位置是否合法。
    ● 指令集的检查——有两类指令可以影响保护机制。第一类是改变GDT,LDT,IDT以及控制寄存器等关键寄存器的指令,称为特权指令;第二类是操作I/O端口的指令以及cli和sti等改变中断允许的指令,称为敏感指令。试想一下,如果用户级程序可以用sti禁止一切中断(包括时钟中断),那么整个系统就无法正常运行,所以这些指令的运行要受到限制。特权指令只能在优先级0上才能运行,而敏感指令取决于eflags寄存器中的IOPL位。只有IOPL位表示的优先级高于等于当前代码段的优先级时,指令才能执行。
    ● I/O操作的保护——I/O地址也是受保护的对象。因为通过I/O操作可以绕过系统对很多硬件进行控制。80386可以单独为I/O空间提供保护,每个任务有个TSS(任务状态段)来记录任务切换的信息。TSS中有个I/O允许位图,用来表示对应的I/O端口是否可以操作。某个I/O地址在位图中的对应数据位为0则表示可以操作;如果为1则还要看eflags中的IOPL位,这时只有IOPL位表示的优先级高于等于当前代码段的优先级,才允许访问该I/O端口。
    3. Windows的保护机制
posted on 2006-12-21 13:07 思勤无邪 阅读(2025) 评论(1)  编辑 收藏 引用 所属分类: 业余时间学习周计划

Feedback

# re: Windows环境下32位汇编语言程序设计(第2版)学习笔记1_第一章 背景知识 2007-02-06 11:02 wanglixin
aa  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理