第1章背景知识 让我们在轻松的背景知识介绍中开始win32汇编之旅。本章将对Win32平台的历史和现 状做简要介绍,同时对80386处理器以及 Windows操作系统中涉及win32汇编的基础知识部 分做快速充电。 1.1Wn32的软硬件平台 1.1.180x86系列处理器简史 wn32可以在多种硬件平台上运行,但使用最广泛的硬件平台是基于Inte公司80x86系 列处理器的微型计算机 自1978年6月 Intel公司推出它的第一个16位微处理器8086以来,计算机技术就开始 进入飞速发展的时期。8086芯片的主频为443MHz,集成的晶体管数大约为29万个,运算 器的位长为16位,采用了20条地址线,可以寻址的范围为20个字节地址,即1MB:1982 年,该公司发布了80286处理器,芯片上集成了12万个晶体管,主频提高到了12MHz。 1985年 Intel公司推出32位的80386处理器,芯片上集成的晶体管数为27.5万个,主频 提高到了33MHz,地址线则扩展为32条,直接寻址的能力达到4GB。80386处理器在设计 的时候考虑了多用户及多任务的需要,在芯片中增加了保护模式、优先级、任务切换和片内 的存储单元管理等硬件单元。80386的出现使 Windows和UNIX等多任务的操作系统可以在 PC上运行。直到现在,运行于80x86处理器之上的多任务操作系统都是以80386的运行模式 为基础的。 1989年, Intel公司推出80486处理器,在芯片内集成了浮点处理器和8KB的一级缓存, 片内的晶体管数达到了118万个,并把主频提高到50MHz~66MHz。80486处理器开始使 用流水线技术,即在CPU中由5~6个不同功能的电路单元组成一条指令处理流水线,然后 将一条指令分成5~6步后再由这些电路单元分别执行,由此提高CPU的运算速度。电路单 元的数目就是流水线的深度。为了使计算机中的其他部件不至于成为CPU速度发展的瓶颈 80486处理器开始使用了倍频技术,即让处理器速度(CPU主频)数倍于系统总线速度(外 频)。 从80386开始,在 Intel公司向市场大量推出处理器芯片的同时,其他一些电脑公司和厂 商如AMD和Cyⅸx等,也纷纷投入大量的人力财力进行处理器的开发和研制,并很快把研 制出的产品推向市场。这些CPU芯片和80386芯片兼容,在编程上可以使用和 Intel处理器 相同的指令集。 1993年3月 Intel公司推出80586处理器。由于无法阻止其他公司把自己的兼容产品也 叫做x86,所以把产品取名为 Pentium,并且进行了商标注册,同时启用了中文名称奔腾 Pentium芯片中集成了310万个晶体管,内置16KB缓存,主频有60MHz和66MH两个版
第 1 章 背 景 知 识 让我们在轻松的背景知识介绍中开始 Win32 汇编之旅。本章将对 Win32 平台的历史和现 状做简要介绍,同时对 80386 处理器以及 Windows 操作系统中涉及 Win32 汇编的基础知识部 分做快速充电。 1.1 Win32 的软硬件平台 1.1.1 80x86 系列处理器简史 Win32 可以在多种硬件平台上运行,但使用最广泛的硬件平台是基于 Intel 公司 80x86 系 列处理器的微型计算机。 自 1978 年 6 月 Intel 公司推出它的第一个 16 位微处理器 8086 以来,计算机技术就开始 进入飞速发展的时期。8086 芯片的主频为 4.43 MHz,集成的晶体管数大约为 2.9 万个,运算 器的位长为 16 位,采用了 20 条地址线,可以寻址的范围为 2 20个字节地址,即 1 MB;1982 年,该公司发布了 80286 处理器,芯片上集成了 12 万个晶体管,主频提高到了 12 MHz。 1985 年 Intel 公司推出 32 位的 80386 处理器,芯片上集成的晶体管数为 27.5 万个,主频 提高到了 33 MHz,地址线则扩展为 32 条,直接寻址的能力达到 4 GB。80386 处理器在设计 的时候考虑了多用户及多任务的需要,在芯片中增加了保护模式、优先级、任务切换和片内 的存储单元管理等硬件单元。80386 的出现使 Windows 和 UNIX 等多任务的操作系统可以在 PC 上运行。直到现在,运行于 80x86 处理器之上的多任务操作系统都是以 80386 的运行模式 为基础的。 1989 年,Intel 公司推出 80486 处理器,在芯片内集成了浮点处理器和 8 KB 的一级缓存, 片内的晶体管数达到了 118 万个,并把主频提高到 50 MHz~66 MHz。80486 处理器开始使 用流水线技术,即在 CPU 中由 5~6 个不同功能的电路单元组成一条指令处理流水线,然后 将一条指令分成 5~6 步后再由这些电路单元分别执行,由此提高 CPU 的运算速度。电路单 元的数目就是流水线的深度。为了使计算机中的其他部件不至于成为 CPU 速度发展的瓶颈, 80486 处理器开始使用了倍频技术,即让处理器速度(CPU 主频)数倍于系统总线速度(外 频)。 从 80386 开始,在 Intel 公司向市场大量推出处理器芯片的同时,其他一些电脑公司和厂 商如 AMD 和 Cyrix 等,也纷纷投入大量的人力财力进行处理器的开发和研制,并很快把研 制出的产品推向市场。这些 CPU 芯片和 80386 芯片兼容,在编程上可以使用和 Intel 处理器 相同的指令集。 1993 年 3 月 Intel 公司推出 80586 处理器。由于无法阻止其他公司把自己的兼容产品也 叫做 x86,所以把产品取名为 Pentium,并且进行了商标注册,同时启用了中文名称 奔腾 。 Pentium 芯片中集成了 310 万个晶体管,内置 16 KB 缓存,主频有 60 MHz 和 66 MHz 两个版
本,后来逐步提高,到1995年6月时主频提高到了133MHz。 Pentium处理器采用许多新技 术,其中最重要的变化是采用了超标量体系结构。即将两个同时工作的指令执行部件封装在 同一芯片中,用两条并行的通道来执行指令,这相当于两个CPU同时工作,大大提高了处理 速度。在586时代,AMD和 Cyrix等其他公司也推出了相应档次的CPU,命名为5x86和 1995年11月,ntel公司推出代号为P6的新一代 Pentium pro处理器,中文名称为高 能奔腾。 Pentium pro芯片中集成了550万个晶体管,主频分150MHz~200MHz多个版本 片内集成了3条平行的指令执行通道,相当于3个CPU并行工作,并用超流水线技术将流水 线的深度提高到了14级。P6处理器内置16KB一级高速缓存,并将256KB或512KB的二 级高速缓存芯片与CPU内核芯片同时封装在一个外壳中,缩短了CPU和二级高速缓存之间 的线路走线距离。同时,P6处理器开始使用乱序执行和分支预测技术,这使下一条指令不一 定要等到前一条指令执行完毕后才可以开始。所有这些技术使这种CPU在运行32位指令系 统时的执行效率明显高于上一代 Pentium 随着CPU和操作系统的发展,多媒体技术开始流行,表眀依靠浮点处理器已经不能满足 多媒体音频和视频信号的实时处理任务了。1997年初, Intel公司在 Pentium pro芯片上增加 了专用于多媒体处理的57条指令和8个64位专用寄存器,命名为 Pentium mmX。 Pentium MMX使用了450万个晶体管,最高主频达到了233MHz 1997年5月, Intel公司又向市场推出了 PentiumⅡ芯片,中文名称为奔腾Ⅱ代。 Pentium Ⅱ内集成了750万个晶体管,最高主频达到了300MHz,也具有MMX的功能。这种处理器 将二级高速缓存移到芯片外,以提高芯片成品率。为了照顾低端市场,1998年 Intel公司推 出了除去二级高速缓存的 PentiumⅡ简化版,命令为 Celeron处理器。由于其缺乏片内二级高 速缓存,对速度的影响非常巨大,使 Celeron处理器的实际性能非常低。1998年4月, Intel 公司又把128KB二级高速缓存加回到 Celeron处理器中,命名为 Celeron a处理器。 Celeron A的主频从300MHz开始 1999年, Intel公司推出集成了950万个晶体管,主频为450MHz~500MHz,外频为10 MHz的 PentiumⅢ处理器。这种处理器新增了SSE指令集,提供70条全新的指令,可以大 大提高3D运算、动画片、影像与音效等功能,增强了视频处理和语音识别的功能。这套指 令集主要为浏览wwW网页而设计。 PentiumⅢ处理器在芯片内集成了64KB的一级缓存, 并将512KB的二级缓存安装在外壳卡盒内 2000年11月, Intel公司发布集成4200万个晶体管的 Pentium4处理器,主频达到了14 GH,系统总线速度为400MHz,流水线的深度提高到20级,并增加了SSE2指令集,提供 14条新指令用于提高摄像、多媒体、3D图像和密集运算等方面的速度。时至今日, Intel 公司已经发布了主频超过2GHz的 Pentium4处理器 从第一块微处理器诞生至今,处理器技术发展出不少新的体系结构。从微处理器的指令 系统来看,有两种分支走向,一种是CISC:一种是RSC。CISC即复杂指令系统计算机。从 PC诞生以来,人们一直沿用CISC指令集方式。它的指令不等长,指令的条数比较多,编程 和设计处理器时都较为麻烦。在CSC之后,人们发明了RISC,即精简指令系统。这种指令 系统采用等长的指令,且指令数较少,通过简化指令可以让计算机的结构更为简单,进而提 高运算速度。 Intel的80x86系列处理器看起来属于CISC体系,但实际上,从 Pentium处理器开始
本,后来逐步提高,到 1995 年 6 月时主频提高到了 133 MHz。Pentium 处理器采用许多新技 术,其中最重要的变化是采用了超标量体系结构。即将两个同时工作的指令执行部件封装在 同一芯片中,用两条并行的通道来执行指令,这相当于两个 CPU 同时工作,大大提高了处理 速度。在 586 时代,AMD 和 Cyrix 等其他公司也推出了相应档次的 CPU,命名为 5x86 和 K5 等。 1995 年 11 月,Intel 公司推出代号为 P6 的新一代 Pentium Pro 处理器,中文名称为 高 能奔腾 。Pentium Pro 芯片中集成了 550 万个晶体管,主频分 150 MHz~200 MHz 多个版本。 片内集成了 3 条平行的指令执行通道,相当于 3 个 CPU 并行工作,并用超流水线技术将流水 线的深度提高到了 14 级。P6 处理器内置 16 KB 一级高速缓存,并将 256 KB 或 512 KB 的二 级高速缓存芯片与 CPU 内核芯片同时封装在一个外壳中,缩短了 CPU 和二级高速缓存之间 的线路走线距离。同时,P6 处理器开始使用乱序执行和分支预测技术,这使下一条指令不一 定要等到前一条指令执行完毕后才可以开始。所有这些技术使这种 CPU 在运行 32 位指令系 统时的执行效率明显高于上一代 Pentium。 随着 CPU 和操作系统的发展,多媒体技术开始流行,表明依靠浮点处理器已经不能满足 多媒体音频和视频信号的实时处理任务了。1997 年初,Intel 公司在 Pentium Pro 芯片上增加 了专用于多媒体处理的 57 条指令和 8 个 64 位专用寄存器,命名为 Pentium MMX。Pentium MMX 使用了 450 万个晶体管,最高主频达到了 233 MHz。 1997 年 5 月,Intel 公司又向市场推出了 Pentium II 芯片,中文名称为 奔腾 II 代 。Pentium II 内集成了 750 万个晶体管,最高主频达到了 300 MHz,也具有 MMX 的功能。这种处理器 将二级高速缓存移到芯片外,以提高芯片成品率。为了照顾低端市场,1998 年 Intel 公司推 出了除去二级高速缓存的 Pentium II 简化版,命令为 Celeron 处理器。由于其缺乏片内二级高 速缓存,对速度的影响非常巨大,使 Celeron 处理器的实际性能非常低。1998 年 4 月,Intel 公司又把 128 KB 二级高速缓存加回到 Celeron 处理器中,命名为 Celeron A 处理器。Celeron A 的主频从 300 MHz 开始。 1999 年,Intel 公司推出集成了 950 万个晶体管,主频为 450 MHz~500 MHz,外频为 100 MHz 的 Pentium III 处理器。这种处理器新增了 SSE 指令集,提供 70 条全新的指令,可以大 大提高 3D 运算、动画片、影像与音效等功能,增强了视频处理和语音识别的功能。这套指 令集主要为浏览 WWW 网页而设计。Pentium III 处理器在芯片内集成了 64 KB 的一级缓存, 并将 512 KB 的二级缓存安装在外壳卡盒内。 2000 年 11 月,Intel 公司发布集成 4 200 万个晶体管的 Pentium 4处理器,主频达到了 1.4 GHz,系统总线速度为 400 MHz,流水线的深度提高到 20 级,并增加了 SSE2 指令集,提供 144 条新指令用于提高摄像、多媒体、3D 图像和密集运算等方面的速度。时至今日,Intel 公司已经发布了主频超过 2 GHz 的 Pentium 4 处理器。 从第一块微处理器诞生至今,处理器技术发展出不少新的体系结构。从微处理器的指令 系统来看,有两种分支走向,一种是 CISC;一种是 RISC。CISC 即复杂指令系统计算机。从 PC 诞生以来,人们一直沿用 CISC 指令集方式。它的指令不等长,指令的条数比较多,编程 和设计处理器时都较为麻烦。在 CISC 之后,人们发明了 RISC,即精简指令系统。这种指令 系统采用等长的指令,且指令数较少,通过简化指令可以让计算机的结构更为简单,进而提 高运算速度。 Intel 的 80x86 系列处理器看起来属于 CISC 体系,但实际上,从 Pentium 处理器开始
都已不是单纯的CISC体系了。因为它们引入了很多RSC体系里的先进技术来大幅度提高性 能。但是,好马也得配好鞍没有软件支持的CPU再快也不是好CPU。为了兼容已有的 软件,80x86系列处理器也不得不背上沉重的历史包袱。如CPU的位长还是停留在32位 在寄存器、运行模式与内存管理模式等方面还是继承了早期的80386模式:80386以后的处 理器虽然增加了不少新指令,但大多用于多媒体扩展,其中很少有和操作系统密切相关的指 令。所以,如果不涉及3D及密集运算方面的运算,仅从操作系统的角度看,这些处理器只 能算是一个快速的80386处理器而己。 1.1.2 Windows的历史 win32指的是32位的 Windows系操作系统。 Microsoft公司有一系列的 Window操作系 统,下面先简单介绍 Windows的历史 谈到 Windows的历史就不能不谈MS-DOS的历史。MS-DOS的技术源自CPM操作系 统。1973年,第一个8位磁盘操作系统CP/M出现,这种操作系统有较好的层次结构,它利 用BIoS隔离硬件和操作系统的其他模块,有很好的可移植性和易用性。在此基础上,西雅 图计算机公司于1978年开始开发QDOS,此后又成功研制出16位微型机的实验性操作系统 86-DOS 也正是在这段时期,IBM公司正在开发基于8086处理器的 IBM PC,急需一个配套的操 作系统,但和CPM开发者之间的谈判不是很顺利,于是 Microsoft乘虚而入。 Microsoft没 有足够的时间开发新的操作系统,于是找到了西雅图计算机公司,双方达成了由 Microsoft 经销86-DOS操作系统的协议。以86-DOS操作系统为基础, Microsoft很快开发出MS-DOS1.0 版本。1981年8月, MS-DOS1.0和 IBM PC一起发布。 MS-DOS1.0还不支持硬盘和分层目录结构,文件管理中继承了CPM操作系统的许多功 能,但仅支持单面软盘。到了1983年,为了支持带硬盘的PC/XT计算机,经过较大地改造 并吸取了UNIX的很多优点后,MS-DOS升级到20版本,可以支持32MB大小的硬盘分区 1984年,MS-DOS升级到30版本,开始支持12MB软盘,用于PCAT计算机。1986年 为了支持3.5英寸软盘,MS-DOS升级到3.2版本 1987年,为了兼容IBM和PS/2个人计算机,MS-DOS升级到3.3版,这也是最流行的 DOS版本。1990年, Microsoft推出MS-DOS50,开始支持288MB的软盘,并可以把部分 系统代码放到高端内存运行,空出低端内存供应用程序使用,同时将磁盘单个分区的支持容 量提高到了2GB 直到MS-DOS的最后版本622为止,绝大多数的PC上运行的就是这个字符界面的操 作系统。当时要想玩转DOS,必须有专业计算机知识,不然 Bad command or filename之 类的提示随处可见,对此一般用户还真会不知所措。所以,虽然界面简陋却令人兴奋的 Windows10于1985年11月正式发布时,还是为沉闷的屏幕带来了一丝清新,毕竞它使非 专业的人员使用计算机变得容易。在增强了键盘和鼠标接口后,1987年微软又推出 Windows20版。由于当时的硬件和DOS功能的限制, Windows并不实用,所以这两个版本 并不成功。 Windows20版发布不久,nte公司的80386处理器发布, Microsoft推出使用80386 处理器86模式的 Windows2.1,即 Windows286 在接下来的时间里,基于 Intel80x86微处理器的IBM兼容机已经快速普及,这给 Microsoft开发新的 Windows系统提供了发展空间和市场。 Microsoft公司对 Windows的内存
都已不是单纯的 CISC 体系了。因为它们引入了很多 RISC 体系里的先进技术来大幅度提高性 能。但是,好马也得配好鞍 没有软件支持的 CPU 再快也不是好 CPU。为了兼容已有的 软件,80x86 系列处理器也不得不背上沉重的历史包袱。如 CPU 的位长还是停留在 32 位; 在寄存器、运行模式与内存管理模式等方面还是继承了早期的 80386 模式;80386 以后的处 理器虽然增加了不少新指令,但大多用于多媒体扩展,其中很少有和操作系统密切相关的指 令。所以,如果不涉及 3D 及密集运算方面的运算,仅从操作系统的角度看,这些处理器只 能算是一个快速的 80386 处理器而已。 1.1.2 Windows 的历史 Win32 指的是 32 位的 Windows 系操作系统。Microsoft 公司有一系列的 Windows 操作系 统,下面先简单介绍 Windows 的历史。 谈到 Windows 的历史就不能不谈 MS-DOS 的历史。MS-DOS 的技术源自 CP/M 操作系 统。1973 年,第一个 8 位磁盘操作系统 CP/M 出现,这种操作系统有较好的层次结构,它利 用 BIOS 隔离硬件和操作系统的其他模块,有很好的可移植性和易用性。在此基础上,西雅 图计算机公司于 1978 年开始开发 QDOS,此后又成功研制出 16 位微型机的实验性操作系统 86-DOS。 也正是在这段时期,IBM 公司正在开发基于 8086 处理器的 IBM PC,急需一个配套的操 作系统,但和 CP/M 开发者之间的谈判不是很顺利,于是 Microsoft 乘虚而入。Microsoft 没 有足够的时间开发新的操作系统,于是找到了西雅图计算机公司,双方达成了由 Microsoft 经销86-DOS操作系统的协议。以86-DOS操作系统为基础,Microsoft很快开发出MS-DOS 1.0 版本。1981 年 8 月,MS-DOS 1.0 和 IBM PC 一起发布。 MS-DOS 1.0 还不支持硬盘和分层目录结构,文件管理中继承了 CP/M 操作系统的许多功 能,但仅支持单面软盘。到了 1983 年,为了支持带硬盘的 PC/XT 计算机,经过较大地改造 并吸取了 UNIX 的很多优点后,MS-DOS 升级到 2.0 版本,可以支持 32 MB 大小的硬盘分区。 1984 年,MS-DOS 升级到 3.0 版本,开始支持 1.2 MB 软盘,用于 PC/AT 计算机。1986 年, 为了支持 3.5 英寸软盘,MS-DOS 升级到 3.2 版本。 1987 年,为了兼容 IBM 和 PS/2 个人计算机,MS-DOS 升级到 3.3 版,这也是最流行的 DOS 版本。1990 年,Microsoft 推出 MS-DOS 5.0,开始支持 2.88 MB 的软盘,并可以把部分 系统代码放到高端内存运行,空出低端内存供应用程序使用,同时将磁盘单个分区的支持容 量提高到了 2 GB。 一直到 MS-DOS 的最后版本 6.22 为止,绝大多数的 PC 上运行的就是这个字符界面的操 作系统。当时要想玩转 DOS,必须有专业计算机知识,不然 Bad command or filename 之 类的提示随处可见,对此一般用户还真会不知所措。所以,虽然 界面简陋却令人兴奋 的 Windows 1.0 于 1985 年 11 月正式发布时,还是为沉闷的屏幕带来了一丝清新,毕竟它使非 专业的人员使用计算机变得容易。在增强了键盘和鼠标接口后,1987 年微软又推出了 Windows 2.0 版。由于当时的硬件和 DOS 功能的限制,Windows 并不实用,所以这两个版本 并不成功。Windows 2.0 版发布不久,Intel 公司的 80386 处理器发布,Microsoft 推出使用 80386 处理器 V86 模式的 Windows 2.1,即 Windows/286。 在接下来的时间里,基于 Intel 80x86 微处理器的 IBM 兼容机已经快速普及,这给 Microsoft 开发新的 Windows 系统提供了发展空间和市场。Microsoft 公司对 Windows 的内存
管理和图形界面做了重大改进,在1990年5月份推出了 Windows3.0,可以支持 Intel 80286/386486微处理器的保护模式,并可以访问达16MB的内存。 Windows30一面世便在 商业上取得了惊人的成功,从而一举奠定了 Microsoft在操作系统上的垄断地位。1992年4 月, Microsoft推出了更稳定的 Windows3.1,可以支持 True Type字体。 Windows3.1是16位 Windows中最流行的版本 1993年5月, Microsoft发布了具备安全性和稳定性特征的32位操作系统 Windows nt 11,主要针对网络和服务器市场。NT代表新技术( New Technology)。NT3.1l是 Windows系列中使用32位编程模式的第一个版本。它充分利用80386及以上处理器的平面 地址空间和保护模式等新技术,并可以移植到 Alpha,MPS和 Power PC等不同的处理器平 台上运行。 随后, Microsoft借 Windows东风,于1995年8月推出新一代操作系统 Windows95(又 名 Chicago) Windows95实现了很友好的用户界面,支持即插即用功能,支持主流多媒体设 备和 DirectX编程接口,成为 Microsoft发展史上的一个里程碑,也是操作系统发展史上的一 个里程碑。从此, Windows9x便取代了 Windows3.x和MS-DOS操作系统,成为个人计算机 平台的主流操作系统 1998年 Microsoft又发布了使用更方便的 Windows98。本来 Windows98是 Microsoft最 后一款基于Winx内核的操作系统,并打算将下一代的操作系统建立在更加稳定的 Windows NT内核上,也就是 Windows nt50。但是在开发过程中, Microsoft意识到基于NT内核的 系统不可能提供足够的多媒体支持,于是继续开发了基于Win9内核的 Windows Me。虽然 其性能并不比 Windows98有很大提高,但在操作界面上有了更人性化的改进 在操作系统的分类上, Microsoft根据家庭个人用户和商业办公用户的不同需求,分别提 供 Window9x和 Windows nt系列, Windows9注重用户界面及其他易用性特征,而NT系 列则在纯32位内核的稳定性和可靠性等企业级特征上下功夫:另一方面,特别针对不同规模 商业用户的需求, Windows nt系列分为工作站版和服务器版等多个版本。在 Windows9x系 列上,从 Windows95OSR2版起, Microsoft先后发布了 Windows98, Windows98SE和 Windows me3个面向家庭和个人用户的PC操作系统,并把I浏览器集成在PC操作系统中; 而在商用操作系统领域,继 Windows nt3.l之后, Microsoft相继发布了 Windows nt3.5和 40两代操作系统,并在NT40上采用了 Windows95式的用户界面。2000年,微软发布采 用纯32位内核并照顾了家庭消费类应用软件的 Windows nt50,即 Windows2000。至此 Microsoft的两个系列操作系统终于开始统 为了利用MS-DOS时代大量的应用程序,保持向下的兼容性, Windows9x的内核模块 还有许多地方使用16位程序,但在编程上,支持32位的编程模式。 Windows nt系列和 Windows%x系列操作系统都支持Win32API( Application Programming Interface),即 Windows 32位应用程序编程接口,Win32API为应用程序提供了大量的系统功能调用,通过Win32API 调用 Windows系统相当于在Ms-DOS中通过中断方式调用系统功能。就像DOS汇编程序中 随处可见的INT2Ih指令一样, Windows应用程序中Win32API也随处可见。 1.1.3Win32平台的背后 Wintel联盟 Windows是伴随着 Intel80x86系列处理器从弱小逐渐成为霸主的。在20世纪90年代, lnte80x86系列处理器更新换代最快的时期也就是 Microsoft的 Windows系列最红的时期
管理和图形界面做了重大改进,在 1990 年 5 月份推出了 Windows 3.0,可以支持 Intel 80286/386/486 微处理器的保护模式,并可以访问达 16 MB 的内存。Windows 3.0 一面世便在 商业上取得了惊人的成功,从而一举奠定了 Microsoft 在操作系统上的垄断地位。1992 年 4 月,Microsoft 推出了更稳定的 Windows 3.1,可以支持 True Type 字体。Windows 3.1 是 16 位 Windows 中最流行的版本。 1993 年 5 月,Microsoft 发布了具备安全性和稳定性特征的 32 位操作系统 Windows NT 3.11,主要针对网络和服务器市场。 NT 代表 新技术 (New Technology)。NT 3.11 是 Windows 系列中使用 32 位编程模式的第一个版本。它充分利用 80386 及以上处理器的平面 地址空间和保护模式等新技术,并可以移植到 Alpha,MIPS 和 Power PC 等不同的处理器平 台上运行。 随后,Microsoft 借 Windows 东风,于 1995 年 8 月推出新一代操作系统 Windows 95(又 名 Chicago)。Windows 95 实现了很友好的用户界面,支持即插即用功能,支持主流多媒体设 备和 DirectX 编程接口,成为 Microsoft 发展史上的一个里程碑,也是操作系统发展史上的一 个里程碑。从此,Windows 9x 便取代了 Windows 3.x 和 MS-DOS 操作系统,成为个人计算机 平台的主流操作系统。 1998 年 Microsoft 又发布了使用更方便的 Windows 98。本来 Windows 98 是 Microsoft 最 后一款基于 Win 9x 内核的操作系统,并打算将下一代的操作系统建立在更加稳定的 Windows NT 内核上,也就是 Windows NT 5.0。但是在开发过程中,Microsoft 意识到基于 NT 内核的 系统不可能提供足够的多媒体支持,于是继续开发了基于 Win 9x 内核的 Windows Me。虽然 其性能并不比 Windows 98 有很大提高,但在操作界面上有了更人性化的改进。 在操作系统的分类上,Microsoft 根据家庭个人用户和商业办公用户的不同需求,分别提 供 Window 9x 和 Windows NT 系列,Windows 9x 注重用户界面及其他易用性特征,而 NT 系 列则在纯 32 位内核的稳定性和可靠性等企业级特征上下功夫;另一方面,特别针对不同规模 商业用户的需求,Windows NT 系列分为工作站版和服务器版等多个版本。在 Windows 9x 系 列上,从 Windows 95 OSR2 版起,Microsoft 先后发布了 Windows 98,Windows 98 SE 和 Windows Me 3 个面向家庭和个人用户的 PC 操作系统,并把 IE 浏览器集成在 PC 操作系统中; 而在商用操作系统领域,继 Windows NT 3.11 之后,Microsoft 相继发布了 Windows NT 3.5 和 4.0 两代操作系统,并在 NT 4.0 上采用了 Windows 95 式的用户界面。2000 年,微软发布采 用纯 32 位内核并照顾了家庭消费类应用软件的 Windows NT 5.0,即 Windows 2000。至此, Microsoft 的两个系列操作系统终于开始统一。 为了利用 MS-DOS 时代大量的应用程序,保持向下的兼容性,Windows 9x 的内核模块 还有许多地方使用 16 位程序,但在编程上,支持 32 位的编程模式。Windows NT 系列和 Windows 9x 系列操作系统都支持 Win32 AP(I Application Programming Interface),即 Windows 32 位应用程序编程接口,Win32 API 为应用程序提供了大量的系统功能调用,通过 Win32 API 调用 Windows 系统相当于在 MS-DOS 中通过中断方式调用系统功能。就像 DOS 汇编程序中 随处可见的 INT 21h 指令一样,Windows 应用程序中 Win32 API 也随处可见。 1.1.3 Win32 平台的背后 Wintel 联盟 Windows 是伴随着 Intel 80x86 系列处理器从弱小逐渐成为霸主的。在 20 世纪 90 年代, Intel 80x86 系列处理器更新换代最快的时期也就是 Microsoft 的 Windows 系列最红的时期
在这个时期, Windows标志和 Intel Inside标志几乎是每一台桌面PC上都有的烙印。 Microsoft 和 Intel公司一软一硬,完全统治着全球PC机的市场,成为整个PC时代的象征,被世人称 为 Wintel联盟。 从20世纪80年代起,当时规模甚小的 Microsoft和lnte正式携手,逐步垄断了计算机 产业硬件与软件的主要领域。每当 Microsoft推出功能更强的软件后, Intel处理器的需求量就 上升;同样,当 Intel生产出速度更快的处理器后, Microsoft的软件因有了更好的平台而显得 更易用。 Intel有多快的CPU, Microsoft就有相应的、庞大的软件来支持它。 Microsoft的应 用程序不管有多庞大,需要多快的速度, Intel的新处理器又总能满足它。业界也必须出奇一 致地放弃原有的软硬件平台,转到新平台上去。因为,谁跟不上 Wintel的步伐,谁就极有可 能被淘汰出局。 Wintel联盟不仅是针对竞争对手的联盟,它还是迫使用户升级的同盟。在升级的循环中, 多数用户往往为了一个应用而被迫升级整个系统。Inte有多快的CPU, Microsoft就有多花 哨、多庞大的操作系统与之相配合。操作系统的升级即意味着应用软件的全面升级,而应用 软件的升级则意味着用户整个系统必须升级。如果用户还在原有的系统上工作,那么就再也 得不到新软件的支持了,因为,所有的应用软件公司都不愿意在过时的操作系统上投资开发 自己的应用软件。大家都有体会,运行 Windows95很快的 Pentium lI250把 Windows98 装上去,立刻慢了下来,等到升级到了 PentiumⅢ/450, Windows98运行起来很快了, Windows 2000又出来了,快速的PⅢ又成了老牛。在又一轮的升级下,CPU爬到了1GHz以上, 等到 Windows2000运行起来很舒畅了,再试一下 Windows xp,用户升级的欲望又出来了! 让客户口袋里的银子永远不会有满的一天。 时钟走过2000年, Wintel联盟已呈衰减之势。Sun,IBM, Oracle, Linux,垄断和司法 部等名词让 Microsoft感到头痛;AMD的速龙和钻龙处理器也让 Intel手忙脚乱。 Microsoft 和Intl在利益上的冲突也越来越公开化,整个业界都感受到了 Wintel联盟将土崩瓦解的气息 不管业界风起云涌也好,一片死寂也好, Intel80x86平台和 Windows是桌面计算机上最 流行的配置已是不争的事实。为了自由和创新,我们可以去学习 Linux,但在更多的时候, 学会Win32编程是不得已的选择,即使是全世界的计算机中只剩50%在运行 Windows Windows程序员仍然有广阔的用武之地,这也算是无奈之际给自己一个理由吧! 1.2 Windows的特色 对于使用者来说,关于 Windows的特色毋须多言,下面的几个特点足以使它广泛流行: ●图形用户界面(GUI, Graphic User Interface的缩写词) Windows最重要的特色, 用户由此摆脱了字符界面操作系统必须死记的键盘命令和令人一头雾水的屏幕提示,改为以 鼠标为主可以直接和屏幕上所见即所得的东西进行交流。 致的用户界面使初学者便于使用,大部分的 Windows程序界面看起来都是差不 多的,都有菜单和标题栏等,掌握一个程序后就很容易尝试新的程序 ●多任务是非常重要的特色,用户可以同时运行多个程序,一边工作一边听MP3 显然是很吸引人的。另一个好处是用户可以在不同的程序之间传送数据。 但对于程序员来说,更关心隐藏在底下的东西, Windows究竞提供了什么便利?用Win32 开发程序方便吗?对程序员来说,更关心 Windows的以下特征:
在这个时期,Windows 标志和 Intel Inside 标志几乎是每一台桌面 PC 上都有的烙印。Microsoft 和 Intel 公司一软一硬,完全统治着全球 PC 机的市场,成为整个 PC 时代的象征,被世人称 为 Wintel 联盟。 从 20 世纪 80 年代起,当时规模甚小的 Microsoft 和 Intel 正式携手,逐步垄断了计算机 产业硬件与软件的主要领域。每当 Microsoft 推出功能更强的软件后,Intel 处理器的需求量就 上升;同样,当 Intel 生产出速度更快的处理器后,Microsoft 的软件因有了更好的平台而显得 更易用。Intel 有多快的 CPU,Microsoft 就有相应的、庞大的软件来支持它。Microsoft 的应 用程序不管有多庞大,需要多快的速度,Intel 的新处理器又总能满足它。业界也必须出奇一 致地放弃原有的软硬件平台,转到新平台上去。因为,谁跟不上 Wintel 的步伐,谁就极有可 能被淘汰出局。 Wintel 联盟不仅是针对竞争对手的联盟,它还是迫使用户升级的同盟。在升级的循环中, 多数用户往往为了一个应用而被迫升级整个系统。Intel 有多快的 CPU,Microsoft 就有多花 哨、多庞大的操作系统与之相配合。操作系统的升级即意味着应用软件的全面升级,而应用 软件的升级则意味着用户整个系统必须升级。如果用户还在原有的系统上工作,那么就再也 得不到新软件的支持了,因为,所有的应用软件公司都不愿意在过时的操作系统上投资开发 自己的应用软件。大家都有体会,运行 Windows 95 很快的 Pentium II/250 把 Windows 98 一 装上去,立刻慢了下来,等到升级到了 Pentium III/450,Windows 98 运行起来很快了,Windows 2000 又出来了, 快速 的 PIII 又成了老牛。在又一轮的升级下,CPU 爬到了 1 GHz 以上, 等到 Windows 2000 运行起来很舒畅了,再试一下 Windows XP,用户升级的欲望又出来了! 让客户口袋里的银子永远不会有满的一天。 时钟走过 2000 年,Wintel 联盟已呈衰减之势。Sun,IBM,Oracle,Linux,垄断和司法 部等名词让 Microsoft 感到头痛;AMD 的速龙和钻龙处理器也让 Intel 手忙脚乱。Microsoft 和Intel在利益上的冲突也越来越公开化,整个业界都感受到了Wintel联盟将土崩瓦解的气息。 不管业界风起云涌也好,一片死寂也好,Intel 80x86 平台和 Windows 是桌面计算机上最 流行的配置已是不争的事实。为了自由和创新,我们可以去学习 Linux,但在更多的时候, 学会 Win32 编程是不得已的选择,即使是全世界的计算机中只剩 50%在运行 Windows。 Windows 程序员仍然有广阔的用武之地,这也算是无奈之际给自己一个理由吧! 1.2 Windows 的特色 对于使用者来说,关于 Windows 的特色毋须多言,下面的几个特点足以使它广泛流行: ● 图形用户界面(GUI,Graphic User Interface 的缩写词) Windows最重要的特色, 用户由此摆脱了字符界面操作系统必须死记的键盘命令和令人一头雾水的屏幕提示,改为以 鼠标为主可以直接和屏幕上所见即所得的东西进行交流。 ● 一致的用户界面 使初学者便于使用,大部分的 Windows 程序界面看起来都是差不 多的,都有菜单和标题栏等,掌握一个程序后就很容易尝试新的程序。 ● 多任务 是非常重要的特色,用户可以同时运行多个程序,一边工作一边听 MP3 显然是很吸引人的。另一个好处是用户可以在不同的程序之间传送数据。 但对于程序员来说,更关心隐藏在底下的东西,Windows 究竟提供了什么便利?用 Win32 开发程序方便吗?对程序员来说,更关心 Windows 的以下特征:
●大量的函数调用Win32支持上千种函数的调用,几乎涉及所有的方面,程序员可 以把更多的时间放在程序的逻辑结构和用户界面上 和设备的无关性win32程序并不直接访问屏幕、打印机和键盘等硬件设备, Windows虚拟了所有的硬件。只要有硬件的设备驱动程序,这个硬件就可以使用,应用程序 并不需要关心硬件的具体型号。与DOS编程中需要针对不同的显示卡和打印机等编写很多 的驱动程序来比,这个特性对程序员的帮助是巨大的 ●内存管理由于内存分页和虚拟内存的使用,每个程序都可以使用4GB的地址空 间,DOS编程时必须考虑的640KB内存问题已经成为历史。 1.3必须了解的东西 1.3.180x86处理器的工作模式 80386处理器有3种工作模式:实模式、保护模式和虚拟86模式。实模式和虚拟86模 式是为了和8086处理器兼容而设置的。在实模式下,80386处理器就相当于一个快速的8086 处理器。保护模式是80386处理器的主要工作模式。在此方式下,80386可以寻址4GB的地 址空间,同时,保护模式提供了80386先进的多任务、内存分页管理和优先级保护等机制。 为了在保护模式下继续提供和8086处理器的兼容,80386又设计了一种虚拟86模式,以便 可以在保护模式的多任务条件下,有的任务运行32位程序,有的任务运行MS-DOS程序 在虚拟86模式下,同样支持任务切换、内存分页管理和优先级,但内存的寻址方式和8086 相同,也是可以寻址lMB的空间 由此可见,80386处理器的3种工作模式各有特点且相互联系。实模式是80386处理器 工作的基础,这时80386当做一个快速的8086处理器工作。在实模式下可以通过指令切换到 保护模式,也可以从保护模式退回到实模式。虚拟86模式则以保护模式为基础,在保护模式 和虚拟86模式之间可以互相切换,但不能从实模式直接进入虚拟86模式或从虚拟86模式直 接退到实模式 实模式 80386处理器被复位或加电的时候以实模式启动。这时候处理器中的各寄存器以实模式 的初始化值工作。80386处理器在实模式下的存储器寻址方式和8086是一样的,由段寄存器 的内容乘以16当做基地址,加上段内的偏移地址形成最终的物理地址,这时候它的32位地 址线只使用了低20位。在实模式下,80386处理器不能对内存进行分页管理,所以指令寻址 的地址就是内存中实际的物理地址。在实模式下,所有的段都是可以读、写和执行的。 实模式下80386不支持优先级,所有的指令相当于工作在特权级(优先级0),所以它可 以执行所有特权指令,包括读写控制寄存器CR0等。实际上,80386就是通过在实模式下初 始化控制寄存器,GDTR,LDTR,IDIR与TR等管理寄存器以及页表,然后再通过加载CRO 使其中的保护模式使能位置位而进入保护模式的。实模式下不支持硬件上的多任务切换 实模式下的中断处理方式和8086处理器相同,也用中断向量表来定位中断服务程序地 址。中断向量表的结构也和8086处理器一样,每4个字节组成一个中断向量,其中包括两个 字节的段地址和两个字节的偏移地址
● 大量的函数调用 Win32 支持上千种函数的调用,几乎涉及所有的方面,程序员可 以把更多的时间放在程序的逻辑结构和用户界面上。 ● 和设备的无关性� Win32 程序并不直接访问屏幕、打印机和键盘等硬件设备, Windows 虚拟了所有的硬件。只要有硬件的设备驱动程序,这个硬件就可以使用,应用程序 并不需要关心硬件的具体型号。与 DOS 编程中需要针对不同的显示卡和打印机等编写很多 的驱动程序来比,这个特性对程序员的帮助是巨大的。 ● 内存管理 由于内存分页和虚拟内存的使用,每个程序都可以使用 4 GB 的地址空 间,DOS 编程时必须考虑的 640 KB 内存问题已经成为历史。 1.3 必须了解的东西 1.3.1 80x86 处理器的工作模式 80386 处理器有 3 种工作模式:实模式、保护模式和虚拟 86 模式。实模式和虚拟 86 模 式是为了和 8086 处理器兼容而设置的。在实模式下,80386 处理器就相当于一个快速的 8086 处理器。保护模式是 80386 处理器的主要工作模式。在此方式下,80386 可以寻址 4 GB 的地 址空间,同时,保护模式提供了 80386 先进的多任务、内存分页管理和优先级保护等机制。 为了在保护模式下继续提供和 8086 处理器的兼容,80386 又设计了一种虚拟 86 模式,以便 可以在保护模式的多任务条件下,有的任务运行 32 位程序,有的任务运行 MS-DOS 程序。 在虚拟 86 模式下,同样支持任务切换、内存分页管理和优先级,但内存的寻址方式和 8086 相同,也是可以寻址 1 MB 的空间。 由此可见,80386 处理器的 3 种工作模式各有特点且相互联系。实模式是 80386 处理器 工作的基础,这时 80386 当做一个快速的 8086 处理器工作。在实模式下可以通过指令切换到 保护模式,也可以从保护模式退回到实模式。虚拟 86 模式则以保护模式为基础,在保护模式 和虚拟 86 模式之间可以互相切换,但不能从实模式直接进入虚拟 86 模式或从虚拟 86 模式直 接退到实模式。 1. 实模式 80386 处理器被复位或加电的时候以实模式启动。这时候处理器中的各寄存器以实模式 的初始化值工作。80386 处理器在实模式下的存储器寻址方式和 8086 是一样的,由段寄存器 的内容乘以 16 当做基地址,加上段内的偏移地址形成最终的物理地址,这时候它的 32 位地 址线只使用了低 20 位。在实模式下,80386 处理器不能对内存进行分页管理,所以指令寻址 的地址就是内存中实际的物理地址。在实模式下,所有的段都是可以读、写和执行的。 实模式下 80386 不支持优先级,所有的指令相当于工作在特权级(优先级 0),所以它可 以执行所有特权指令,包括读写控制寄存器 CR0 等。实际上,80386 就是通过在实模式下初 始化控制寄存器,GDTR,LDTR,IDTR 与 TR 等管理寄存器以及页表,然后再通过加载 CR0 使其中的保护模式使能位置位而进入保护模式的。实模式下不支持硬件上的多任务切换。 实模式下的中断处理方式和 8086 处理器相同,也用中断向量表来定位中断服务程序地 址。中断向量表的结构也和 8086 处理器一样,每 4 个字节组成一个中断向量,其中包括两个 字节的段地址和两个字节的偏移地址
从编程的角度看,除了可以访问80386新增的一些寄存器外,实模式的80386处理器和 8086有什么进步呢?其实最大的好处是可以使用80386的32位寄存器,用32位的寄存器进 行编程可以使计算程序更加简捷,加快了执行速度。比如在8086时代用16位寄存器来完成 32位的乘法和除法时,要进行的步骤实在是太多了,于是考试时出这一类的题目就成了老师 们的最爱,所以那时候当学生做梦都想着让寄存器的位数快快长,现在梦想终于成真了,用 32位寄存器一条指令就可以完成(问题是老师们也发现了这个投机取巧的办法,为了达到让 学生们基础扎实的目的,也把题目换成了64位的乘法和除法,所以现在晚上做的梦换成了寄 存器忽然长到了64位);其次,80386中增加的两个辅助段寄存器FS和GS在实模式下也可 以使用,这样,同时可以访问的段达到了6个而不必考虑重新装入的问题:最后,很多80386 的新增指令也使一些原来不很方便的操作得以简化,如80386中可以使用下述指令进行数组 访问: mov Cx,.[eax+ebx*2+数组基地址] 这相当于把数组中下标为eax和ebx的项目放入cx中;cbx*2中的2可以是1,2,4 或8,这样就可以支持8位到64位的数组。而在8086处理器中,实现相同的功能要进行 次乘法和两次加法。另外, pushad和 popad指令可以一次把所有8个通用寄存器的值压入或 从堆栈中弹出,比起用下面的指令分别将8个寄存器入栈要快了很多 push b op ebx 当然,使用了这些新指令的程序是无法拿回到8086处理器上去执行的,因为这些指令的 编码在8086处理器上是未定义的。 2.保护模式 当80386工作在保护模式下的时候,它的所有功能都是可用的。这时80386所有的32 根地址线都可供寻址,物理寻址空间高达4GB。在保护模式下,支持内存分页机制,提供了 对虚拟内存的良好支持。虽然与8086可寻址的1MB物理地址空间相比,80386可寻址的物 理地址空间可谓很大,但实际的微机系统不可能安装如此大的物理内存。所以,为了运行大 型程序和真正实现多任务,虚拟内存是一种必需的技术。 保护模式下80386支持多任务,可以依靠硬件仅在一条指令中实现任务切换。任务环境 的保护工作是由处理器自动完成的。在保护模式下,80386处理器还支持优先级机制,不同 的程序可以运行在不同的优先级上。优先级一共分0~34个级别,操作系统运行在最高的优 先级0上,应用程序则运行在比较低的级别上;配合良好的检查机制后,既可以在任务间实 现数据的安全共享也可以很好地隔离各个任务。从实模式切换到保护模式是通过修改控制寄 存器CR0的控制位PE(位0)来实现的。在这之前还需要建立保护模式必需的一些数据表, 如全局描述符表GDT和中断描述符表IDT等 DOS操作系统运行于实模式下,而 Windows操作系统运行于保护模式下
从编程的角度看,除了可以访问 80386 新增的一些寄存器外,实模式的 80386 处理器和 8086 有什么进步呢?其实最大的好处是可以使用 80386 的 32 位寄存器,用 32 位的寄存器进 行编程可以使计算程序更加简捷,加快了执行速度。比如在 8086 时代用 16 位寄存器来完成 32 位的乘法和除法时,要进行的步骤实在是太多了,于是考试时出这一类的题目就成了老师 们的最爱,所以那时候当学生做梦都想着让寄存器的位数快快长,现在梦想终于成真了,用 32 位寄存器一条指令就可以完成(问题是老师们也发现了这个投机取巧的办法,为了达到让 学生们基础扎实的目的,也把题目换成了 64 位的乘法和除法,所以现在晚上做的梦换成了寄 存器忽然长到了 64 位);其次,80386 中增加的两个辅助段寄存器 FS 和 GS 在实模式下也可 以使用,这样,同时可以访问的段达到了 6 个而不必考虑重新装入的问题;最后,很多 80386 的新增指令也使一些原来不很方便的操作得以简化,如 80386 中可以使用下述指令进行数组 访问: mov cx,[eax + ebx * 2 + 数组基地址] 这相当于把数组中下标为 eax 和 ebx 的项目放入 cx 中;ebx * 2 中的 2 可以是 1,2,4 或 8,这样就可以支持 8 位到 64 位的数组。而在 8086 处理器中,实现相同的功能要进行一 次乘法和两次加法。另外,pushad 和 popad 指令可以一次把所有 8 个通用寄存器的值压入或 从堆栈中弹出,比起用下面的指令分别将 8 个寄存器入栈要快了很多: push eax push ebx ... pop ebx pop eax 当然,使用了这些新指令的程序是无法拿回到 8086 处理器上去执行的,因为这些指令的 编码在 8086 处理器上是未定义的。 2. 保护模式 当 80386 工作在保护模式下的时候,它的所有功能都是可用的。这时 80386 所有的 32 根地址线都可供寻址,物理寻址空间高达 4 GB。在保护模式下,支持内存分页机制,提供了 对虚拟内存的良好支持。虽然与 8086 可寻址的 1 MB 物理地址空间相比,80386 可寻址的物 理地址空间可谓很大,但实际的微机系统不可能安装如此大的物理内存。所以,为了运行大 型程序和真正实现多任务,虚拟内存是一种必需的技术。 保护模式下 80386 支持多任务,可以依靠硬件仅在一条指令中实现任务切换。任务环境 的保护工作是由处理器自动完成的。在保护模式下,80386 处理器还支持优先级机制,不同 的程序可以运行在不同的优先级上。优先级一共分 0~3 4 个级别,操作系统运行在最高的优 先级 0 上,应用程序则运行在比较低的级别上;配合良好的检查机制后,既可以在任务间实 现数据的安全共享也可以很好地隔离各个任务。从实模式切换到保护模式是通过修改控制寄 存器 CR0 的控制位 PE(位 0)来实现的。在这之前还需要建立保护模式必需的一些数据表, 如全局描述符表 GDT 和中断描述符表 IDT 等。 DOS 操作系统运行于实模式下,而 Windows 操作系统运行于保护模式下
3.虚拟86模式 虚拟86模式是为了在保护模式下执行8086程序而设置的。虽然80386处理器已经提供 了实模式来兼容8086程序,但这时8086程序实际上只是运行得快了一点,对CPU的资源还 是独占的。在保护模式的多任务环境下运行这些程序时,它们中的很多指令和保护模式环境 格格不入,如段寻址方式、对中断的处理和O操作的特权问题等。为了在保护模式下工作 而丢弃这些程序的代价是巨大的。设想一下,如果 Windows或80386处理器推出的时候宣布 不能运行以前的MS-DOS程序,那么就等于放弃了一个巨大的软件库, Windows以及80386 处理器可能就会落得和苹果机一样的下场,这是 Microsoft和ntel都不愿看到的。所以,80386 处理器又设计了一个虚拟86模式。 虚拟86模式是以任务形式在保护模式上执行的,在80386上可以同时支持由多个真正的 80386任务和虚拟86模式构成的任务。在虚拟86模式下,80386支持任务切换和内存分页 在 Windows操作系统中,有一部分程序专门用来管理虚拟86模式的任务,称为虚拟86管理 程序 既然虚拟86模式以保护模式为基础,它的工作方式实际上是实模式和保护模式的混合 为了和8086程序的寻址方式兼容,虚拟86模式采用和8086一样的寻址方式,即用段寄存器 乘以16当做基址再配合偏移地址形成线性地址,寻址空间为1MB。但显然多个虚拟86任 务不能同时使用同一位置的1MB地址空间,否则会引起冲突。操作系统利用分页机制将不 同虚拟86任务的地址空间映射到不同的物理地址上去,这样每个虚拟86任务看起来都认为 自己在使用0~1MB的地址空间。 8086代码中有相当一部分指令在保护模式下属于特权指令,如屏蔽中断的cli和中断返 回指令iet等。这些指令在8086程序中是合法的。如果不让这些指令执行,8086代码就无 法工作。为了解决这个问题,虚拟86管理程序采用模拟的方法来完成这些指令。这些特权指 令执行的时候引起了保护异常。虚拟86管理程序在异常处理程序中检查产生异常的指令,如 果是中断指令,则从虚拟86任务的中断向量表中取出中断处理程序的入口地址,并将控制转 移过去;如果是危及操作系统的指令,如ci等,则简单地忽略这些指令,在异常处理程序返 回的时候直接返回到下一条指令。通过这些措施,8086程序既可以正常地运行下去,在执行 这些指令的时候又觉察不到已经被虚拟86管理程序做了手脚。MS-DOS应用程序在 Windows操作系统中就是这样工作的。 132 Windows的内存管理 在这一节中,读者可以解决初学win32汇编的两个大疑问: 1.Win32汇编中,每个程序都可以用4GB的内存吗? 2.win32汇编源代码中为什么看不到CS,DS,ES和SS等段寄存器的使用? 1.DOS操作系统的内存安排 win32编程相对于DOS编程最大的区别之一就是内存的使用。 先来回顾一下DOS操作系统的内存使用,如图1.1所示。DOS操作系统运行于实模式 中,由于8086处理器的寻址范围只有1MB,当时把系统硬件使用的内存安排在高端,地址 是从A00Oh(即640KB)开始的384KB中,其中有用于显示的视频缓冲区和BOS的地址
3. 虚拟 86 模式 虚拟 86 模式是为了在保护模式下执行 8086 程序而设置的。虽然 80386 处理器已经提供 了实模式来兼容 8086 程序,但这时 8086 程序实际上只是运行得快了一点,对 CPU 的资源还 是独占的。在保护模式的多任务环境下运行这些程序时,它们中的很多指令和保护模式环境 格格不入,如段寻址方式、对中断的处理和 I/O 操作的特权问题等。为了在保护模式下工作 而丢弃这些程序的代价是巨大的。设想一下,如果 Windows 或 80386 处理器推出的时候宣布 不能运行以前的 MS-DOS 程序,那么就等于放弃了一个巨大的软件库,Windows 以及 80386 处理器可能就会落得和苹果机一样的下场,这是 Microsoft 和 Intel 都不愿看到的。所以,80386 处理器又设计了一个虚拟 86 模式。 虚拟 86 模式是以任务形式在保护模式上执行的,在 80386 上可以同时支持由多个真正的 80386 任务和虚拟 86 模式构成的任务。在虚拟 86 模式下,80386 支持任务切换和内存分页。 在 Windows 操作系统中,有一部分程序专门用来管理虚拟 86 模式的任务,称为虚拟 86 管理 程序。 既然虚拟 86 模式以保护模式为基础,它的工作方式实际上是实模式和保护模式的混合。 为了和 8086 程序的寻址方式兼容,虚拟 86 模式采用和 8086 一样的寻址方式,即用段寄存器 乘以 16 当做基址再配合偏移地址形成线性地址,寻址空间为 1 MB。但显然多个虚拟 86 任 务不能同时使用同一位置的 1 MB 地址空间,否则会引起冲突。操作系统利用分页机制将不 同虚拟 86 任务的地址空间映射到不同的物理地址上去,这样每个虚拟 86 任务看起来都认为 自己在使用 0~1 MB 的地址空间。 8086 代码中有相当一部分指令在保护模式下属于特权指令,如屏蔽中断的 cli 和中断返 回指令 iret 等。这些指令在 8086 程序中是合法的。如果不让这些指令执行,8086 代码就无 法工作。为了解决这个问题,虚拟 86 管理程序采用模拟的方法来完成这些指令。这些特权指 令执行的时候引起了保护异常。虚拟 86 管理程序在异常处理程序中检查产生异常的指令,如 果是中断指令,则从虚拟 86 任务的中断向量表中取出中断处理程序的入口地址,并将控制转 移过去;如果是危及操作系统的指令,如 cli 等,则简单地忽略这些指令,在异常处理程序返 回的时候直接返回到下一条指令。通过这些措施,8086 程序既可以正常地运行下去,在执行 这些指令的时候又觉察不到已经被虚拟 86 管理程序做了手脚。MS-DOS 应用程序在 Windows 操作系统中就是这样工作的。 1.3.2 Windows 的内存管理 在这一节中,读者可以解决初学 Win32 汇编的两个大疑问: 1. Win32 汇编中,每个程序都可以用 4 GB 的内存吗? 2. Win32 汇编源代码中为什么看不到 CS,DS,ES 和 SS 等段寄存器的使用? 1. DOS 操作系统的内存安排 Win32 编程相对于 DOS 编程最大的区别之一就是内存的使用。 先来回顾一下 DOS 操作系统的内存使用,如图 1.1 所示。DOS 操作系统运行于实模式 中,由于 8086 处理器的寻址范围只有 1 MB,当时把系统硬件使用的内存安排在高端,地址 是从 A0000h(即 640 KB)开始的 384 KB 中,其中有用于显示的视频缓冲区和 BIOS 的地址
空间。而在内存低端,安排了中断向量表和 BIOS数据区:剩下从500h开始到AO0总 00000h 中断向量表 00400h 共不到640KB的内存是操作系统和应用程序 BOS数据区 00500h 所能够使用的:应用程序不可能使用这640KB DOS数据区 系统程序 以外的内存。这就是著名的640KB限制 (DOS的驻留部分、驱动程序等) 但即使在这640KB中,DOS操作系统又占领 可用空间 了低端的一部分内存,最后剩下600KB左右 Ao0OOh 图形模式视频缓冲区 的内存才是应用程序真正可以用的。如果系统 BootH 单色字符模式视频缓冲区 中有内存驻留程序存在,那么应用程序还要和 Cooch 彩色字符模式视频缓冲区 这些TSR程序共同分享这段内存空间 GA BIOS地址 当80386处理器推出后,可以寻址的内存 ROM扩展、系统BOS地址 范围达到了4GB,利用XMS驱动程序可以访 64KB高端内存 问到所有的4GB地址空间。但16位的段寻址 方式限制了DOS程序,可见的内存范围还 图1.1DOS操作系统的内存安排 是停留在0000到 FFFFOh+64KB的范围内,所有高于1MB的扩展内存只能通过XMS驱 动程序当做数据交换使用,程序的执行空间并没有什么增加 2.80386的内存寻址机制 Windows的内存管理和DOS的内存管理有很大的不同,在了解 Windows的内存管理模 式之前,需要对80386保护模式下内存分页机制有些了解。为了做个对比,先来看实模式下 的内存寻址方式,即DOS下的寻址方式,如图1.2所示。 filth(IMB 地址xxx:yy yyy 000h XXXX xxxxOh 16位的 段寄存器 00000h 物理内存 图12实模式下的内存寻址方式 在实模式下,一个完整的地址由段地址和偏移地址两部分组成。段地址放在16位的段寄 存器中,然后在指令中用16位的偏移地址寻址。处理器换算时先将段地址乘以10h,得到段 在物理内存中的起始地址;然后加上16位的偏移地址得到实际的物理地址。如xwyy格 式的虚拟地址在内存中的实际位置是xxx10h+yyyo 当80386处理器工作在保护模式和虚拟8086模式的时候,可以使用全部32根地址线访
空间。而在内存低端,安排了中断向量表和 BIOS 数据区;剩下从 500h 开始到 A0000h 总 共不到 640 KB 的内存是操作系统和应用程序 所能够使用的;应用程序不可能使用这 640 KB 以外的内存。这就是著名的 640KB 限制 。 但即使在这 640 KB 中,DOS 操作系统又占领 了低端的一部分内存,最后剩下 600 KB 左右 的内存才是应用程序真正可以用的。如果系统 中有内存驻留程序存在,那么应用程序还要和 这些 TSR 程序共同分享这段内存空间。 当 80386 处理器推出后,可以寻址的内存 范围达到了 4 GB,利用 XMS 驱动程序可以访 问到所有的 4 GB 地址空间。但 16 位的段寻址 方式限制了 DOS 程序, 可见 的内存范围还 是停留在 00000h 到 FFFF0h+64 KB 的范围内,所有高于 1 MB 的扩展内存只能通过 XMS 驱 动程序当做数据交换使用,程序的执行空间并没有什么增加。 2. 80386 的内存寻址机制 Windows 的内存管理和 DOS 的内存管理有很大的不同,在了解 Windows 的内存管理模 式之前,需要对 80386 保护模式下内存分页机制有些了解。为了做个对比,先来看实模式下 的内存寻址方式,即 DOS 下的寻址方式,如图 1.2 所示。 64KB fffffh(1MB) xxxx0h 00000h 物理内存 16 位的 段寄存器 x10h 0000h yyyyh ffffh 地址 xxxx:yyyy xxxx 图 1.2 实模式下的内存寻址方式 在实模式下,一个完整的地址由段地址和偏移地址两部分组成。段地址放在 16 位的段寄 存器中,然后在指令中用 16 位的偏移地址寻址。处理器换算时先将段地址乘以 10h,得到段 在物理内存中的起始地址;然后加上 16 位的偏移地址得到实际的物理地址。如 xxxx:yyyy 格 式的虚拟地址在内存中的实际位置是 xxxx 10h+yyyy。 当 80386 处理器工作在保护模式和虚拟 8086 模式的时候,可以使用全部 32 根地址线访 64KB 高端内存 ROM 扩展、系统 BIOS 地址 VGA BIOS 地址 彩色字符模式视频缓冲区 单色字符模式视频缓冲区 图形模式视频缓冲区 可用空间 系统程序 (DOS 的驻留部分、驱动程序等) DOS 数据区 BIOS 数据区 中断向量表 00000h 00400h 00500h A0000h B0000h B8000h C0000h C8000h FFFFFh 图 1.1 DOS 操作系统的内存安排
问4GB大的内存。段地址加偏移地址的计算方法显然无法覆盖这么大的范围。但计算一下 就可以发现,实际上和8086同样的限制己经不复存在,因为80386所有的通用寄存器都是 32位的,2的32次方相当于4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经 可以访问到所有的内存地址 这是不是说,在保护模式下,段寄存器就不再有用了呢?答案是否定的。实际上段寄存 器更有用了,虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可 以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。要 解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途 但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用64位长的数据才能表 示。我们把这64位的属性数据叫做段描述符( Segment Descriptor) 80386的段寄存器是16位的,无法放下保护模式下64位的段描述符。如何解决这个新 的问题呢?解决办法是把所有段的段描述符顺序放在内存中的指定位置,组成一个段描述符 表( Descriptor Table);而段寄存器中的16位用来做索引信息,指定这个段的属性用段描述 符表中的第几个描述符来表示。这时,段寄存器中的信息不再是段地址了,而是段选择器 ( Segment Selector)。可以通过它在段描述符表中选择一个项目以得到段的全部信息。 既然这样,段描述符表放在那里呢?80386中引入了两个新的寄存器来管理段描述符表 个是48位的全局描述符表寄存器GDTR,一个是16位的局部描述符表寄存器LDIR。那 么,为什么有两个描述符表寄存器呢? GDIR指向的描述符表为全局描述符表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位T位用 来表示在段描述符的位置:T=0表示在GDT中,T1=1表示在LDT中 以图1.3为例,在保护模式下,同样以 xxxX. yyyyyyyy格式表示一个虚拟地址。单单凭 段选择器中的数值xxx根本无法反映出段的基址在哪里。对于这个地址,首先要看xxx的 TI位是否为0,如果是的话,则先从GDTR寄存器中获取GDT的基址(图中的步骤①),然 后在GDT中以段选择器xw的高13位当做位置索引得到段描述符(步骤②)。段描述符包 含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(步骤③);如果xx的 ∏I位为1的话就更复杂了,这表示段描述符在LDT中,这时第一步的操作还是从GDTR寄 存器中获取GDT的基址(步骤①),并且要从LDTR中获取LDT所在段的位置索引(步骤
问 4 GB 大的内存。段地址加偏移地址的计算方法显然无法覆盖这么大的范围。但计算一下 就可以发现,实际上和 8086 同样的限制已经不复存在,因为 80386 所有的通用寄存器都是 32 位的,2 的 32 次方相当于 4G,所以用任何一个通用寄存器来间接寻址,不必分段就已经 可以访问到所有的内存地址。 这是不是说,在保护模式下,段寄存器就不再有用了呢?答案是否定的。实际上段寄存 器更有用了,虽然在寻址上不再有分段的限制问题,但在保护模式下,一个地址空间是否可 以被写入,可以被多少优先级的代码写入,是不是允许执行等涉及保护的问题就出来了。要 解决这些问题,必须对一个地址空间定义一些安全上的属性。段寄存器这时就派上了用途。 但是涉及属性和保护模式下段的其他参数,要表示的信息太多了,要用 64 位长的数据才能表 示。我们把这 64 位的属性数据叫做段描述符(Segment Descriptor)。 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 中。 以图 1.3 为例,在保护模式下,同样以 xxxx:yyyyyyyy 格式表示一个虚拟地址。单单凭 段选择器中的数值 xxxx 根本无法反映出段的基址在哪里。对于这个地址,首先要看 xxxx 的 TI 位是否为 0,如果是的话,则先从 GDTR 寄存器中获取 GDT 的基址(图中的步骤①),然 后在 GDT 中以段选择器 xxxx 的高 13 位当做位置索引得到段描述符(步骤②)。段描述符包 含段的基址、限长、优先级等各种属性,这就得到了段的起始地址(步骤③);如果 xxxx 的 TI 位为 1 的话就更复杂了,这表示段描述符在 LDT 中,这时第一步的操作还是从 GDTR 寄 存器中获取 GDT 的基址(步骤○1' ),并且要从 LDTR 中获取 LDT 所在段的位置索引(步骤