保护模式编程

合集下载

IA-32卷3:经典系统编程指南[1、2、3、5章节]

IA-32卷3:经典系统编程指南[1、2、3、5章节]

IA-32 Intel®架构软件开发人员手册 卷3:系统编程指南(中文版-部分)前言现在开放源代码逐渐成为趋势的环境下,获取高水平的源代码的途径越来越容易,尤其是涉及操作系统的源代码,受到越来越多的有志于研究底层的开发人员的青睐。

然而操作系统(内核)源代码具有规模大、专业性强、涉及的知识面广的特点,大部分首次接触内核源代码的人感觉不少部分尤其是与硬件平台相关部分(任务切换、内存管理等方面)难以理解,而这些难以理解的部分却又往往是操作系统的核心部分。

对于造成操作系统代码难以理解的原因有多个方面,主有对操作系统若干理论、概念理解不深,这可以通过阅读操作系统相关书籍来弥补。

目前比较经典的操作系统书籍有多种,各有各的特色,有纯理论的,也有理论与实践相结合的。

“工欲善其事,必先利其器”在开始探究操作系统源代码之前,仔细深入的研究这些基本概念、基本理论是十分必要的。

然而这些还是不够的,除了理解操作系统概念理论之外,对于操作系统运行的硬件的了解也是非常必要的。

而目前缺乏x86平台权威资料,流行的教材都讲的比较基础,而与操作系统设计与开发方面相关的信息,讲得普遍比较少甚至少有涉及,而intel官方出的三卷手册就目前来讲是最全面、最权威的x86平台资料了,由于是官方版本是英文版,所以在很大程度上限制了它的流行,即使平时查阅相关资料时,也大都只是参考它的部分章节而对其全貌仍未了解。

这三卷各有特色,其中卷3主要是指针对与操作系统设计方面并鉴于目前情况,产生了首先将手册之卷3翻译为中文的念头,但是由于它篇幅很大(PDF版本有780页之巨)仅个人力量很难完成,所以借助于网络平台,召集大家共同分担完成,在此也非常感谢赵博士为大家提供了那么好的交流平台。

目前已经分配的翻译任务如下:第1章关于本手册第2章 系统架构概况 我(lijshu)基本已经译完,就是目前这个文件:-) 第3章 保护模式下的内存管理由sportsman 负责翻译第4章 保护机制 由sportsman 负责翻译第5章 中断和异常处理由wykr3879 负责翻译第6章 任务管理 由wykr3879 负责翻译第7章 多处理器管理由Timeless 负责翻译第8章高级可编程中断控制器由beyond 负责翻译第9章处理器管理与初使化由极速时空 负责翻译第10章 内存高速缓冲存储器控制 由engumen负责翻译其余的部分还没有落实,希望有兴趣、有精力的参加进来,让我们共同完成这个项目!由于翻译是一件非常不容易的工作,尤其是达到“信、达、雅”的地步更就难了,译稿只能尽最大能力保持准确把握原文的意思,但是由于每个人能力及对原文的理解不同,因此对于译稿肯定有很多有待商榷的地方,甚至是错误的地方,因此请大家指出来,便于进一步修改、完善译稿,以供大家飨用。

[说明]td-pitd新一代32位微机原理实验箱、微机接口技术实验系统

[说明]td-pitd新一代32位微机原理实验箱、微机接口技术实验系统

TD-PITD+ 新一代32位微机教学实验系统西安唐都科教仪器公司最新推出“TD-PITD+32位微机教学实验系统”,该系统基于PCI总线扩展卡扩展出80x86系统总线,支持“80x86微机原理及接口技术”、“基于Windows系统的微机原理及接口技术”实验教学和IA-32微机系统应用开发,完全解决了以往各种PCI总线扩展实验设备存在的各种问题,诸如容易死机,不易维护,实验内容少,中断、DMA、存储器扩展等实验开不了或开不全,在Windows 环境中主要实验都不能开展等等。

所以唐都32位微机教学实验系统已成为高校“80x86微机原理及接口技术”和“”微机应用及开发”等课程实验教学的不二选择。

一、支持基于80x86的16/32位微机原理及接口技术教学体系(一)全面支持基于80x86的16/32位微机原理及接口技术的实验教学系统全面支持“基于80x86的16/32位微机原理及接口技术”的实验教学,从而可使各学校由原来的“基于DOS系统的16位微机原理及接口技术”的实验教学顺利提升到“基于80x86的16/32位微机原理及接口技术”实验教学的新层次。

“基于80x86的16/32位微机原理及接口技术”实验教学体系包括:80x86实模式微机原理及接口技术(16位微机原理及其程序设计、32位指令及其程序设计、微机接口技术及其应用)和80x86保护模式微机原理及接口技术(保护模式原理及其程序设计、虚拟存储管理及存储器扩展)。

其中“8259中断控制实验”包括8259单一中断源实验、8259优先级中断实验、8259级联中断实验,“8237DMA传送实验”包括存储器到存储器、存储器到I/O之间的DMA传送实验,“存储器扩展实验”包括8/16/32位静态存储器扩展实验和Flash ROM存储器实验。

(二)Windows环境下的汇编语言和C语言源程序调试软件专为在Windows系统环境下支持80x86微机原理及接口技术的实验教学设计了一套高度可视化的先进集成开发环境,在该环境下可支持80x86汇编或C语言源语言级的编程和调试,支持实验平台上扩展的接口芯片及设备的I/O操作、中断以及DMA方式操作的编程及调试,支持实验平台上存储器的内存扩展的编程操作及调试,完全解决了基于PC微机的Windows环境下,如何通过PCI总线扩展方式,来完整开展80x86微机接口技术的实验教学问题。

保护模式下寻址(易懂)

保护模式下寻址(易懂)

保护模式下寻址(易懂)保护模式下寻址(易懂):网上看到的一强帖,不转不行了,牛人啊,把这段代码拿捏的相当到位括号中是我的加注段机制轻松体验[内存寻址]实模式下的内存寻址:让我们首先来回顾实模式下的寻址方式段首地址×16+偏移量=物理地址为什么要×16?因为在8086CPU中,地址线是20位,但寄存器是16位的,最高寻址64KB,它无法寻址到1M内存。

于是,Intel设计了这种寻址方式,先缩小4位成16位放入到段寄存器,用到时候,再将其扩大到20位,这也造成了段的首地址必须是16的倍数的限制。

保护模式下分段机制的内存寻址:保护模式下分段机制是利用一个称作段选择符的偏移量,从而到描述符表找到需要的段描述符,而这个段描述符中就存放着真正的段的物理首地址,再加上偏移量一段话,出现了三个新名词:1、段选择子2、描述符表3、段描述符我们现在可以这样来理解这段话:有一个结构体类型,它有三个成员变量:段物理首地址段界限段属性内存中,维护一个该结构体类型的是一个数组。

而分段机制就是利用一个索引,找到该数组对应的结构体,从而得到段的物理首地址,然后加上偏移量,得到真正的物理地址。

公式:xxxx:yyyyyyyy其中,xxxx也就是索引,yyyyyyyy是偏移量(因为32位寄存器,所以8个16进制)xxxx存放在段寄存器中。

现在,我们来到过来分析一下那三个新名词。

段描述符,一个结构体,它有三个成员变量:1、段物理首地址2、段界限3、段属性我们再来重温一遍描述符表,也就是一个数组,什么样的数组呢?是一个段描述符组成的数组。

接下来看看段选择子:段选择子,也就是数组的索引,但这时候的索引不在是高级语言中数组的下标,而是我们将要找的那个段描述符相对于数组首地址(也就是全局描述表的首地址)偏移位置。

就这么简单,如图:图中,通过Selector(段选择子)找到存储在Descriptor Table(描述符表)中某个Descriptor(段描述符),该段描述符中存放有该段的物理首地址,所以就可以找到内存中真正的物理段首地址SegmentOffset(偏移量):就是相对该段的偏移量物理首地址+偏移量就得到了物理地址本图就是DATA但这时,心细的朋友就发现了一个GDTR这个家伙还没有提到!我们来看一下什么是GDTR ?Global Descriptor Table Register(全局描述符表寄存器)但是这个寄存器有什么用呢?大家想一下,段描述符表现在是存放在内存中,那CPU是如何知道它在哪里呢?所以,Intel 公司设计了一个全局描述符表寄存器,专门用来存放段描述符表的首地址,以便找到内存中段描述符表。

汇编语言基础知识

汇编语言基础知识

汇编语言基础知识汇编语言是直接在硬件之上工作的编程语言,首先要了解硬件系统的结构,才能有效地应用汇编语言对其编程,因此,本章对硬件系统结构的问题进行部分探讨,首先介绍了计算机的基本结构、Intel 公司微处理器的发展、计算机的语言以及汇编语言的特点,在此基础上重点介绍寄存器、内存组织等汇编语言所涉及到的基本知识。

1.1 微型计算机概述微型计算机由中央处理器(Central Processing Unit ,CPU )、存储器、输入输出接口电路和总线构成。

CPU 如同微型计算机的心脏,它的性能决定了整个微型计算机的各项关键指标。

存储器包括随机存储器(Random Access Memory ,RAM )和只读存储器(Read Only Memory ,ROM )。

输入输出接口电路用来连接外部设备和微型计算机。

总线为CPU 和其他部件之间提供数据、地址和控制信息的传输通道。

如图1.1所示为微型计算机的基本结构。

外部设备存储器输入输出接口电路中央处理器CPU地址总线数据总线控制总线图1.1 微型计算机基本结构特别要提到的是微型计算机的总线结构,它使系统中各功能部件之间的相互关系变为各个部件面向总线的单一关系。

一个部件只要符合总线结构标准,就可以连接到采用这种总线结构的系统中,使系统功能得到扩展。

数据总线用来在CPU 与内存或其他部件之间进行数据传送。

它是双向的,数据总线的位宽决定了CPU 和外界的数据传送速度,8位数据总线一次可传送一个8位二进制数据(即一个字节),16位数据总线一次可传送两个字节。

在微型计算机中,数据的含义是广义的,数据总线上传送的不一定是真正的数据,而可能是指令代码、状态量或控制量。

地址总线专门用来传送地址信息,它是单向的,地址总线的位数决定了CPU 可以直接寻址的内存范围。

如CPU 的地址总线的宽度为N ,则CPU 最多可以寻找2N 个内存单元。

控制总线用来传输控制信号,其中包括CPU送往存储器和输入输出接口电路的控制信号,如读信号、写信号和中断响应信号等;也包括其他部件送到CPU的信号,如时钟信号、中断请求信号和准备就绪信号等。

TD-PIT+用户手册

TD-PIT+用户手册

TD-PIT+32位微机原理与接口技术用户手册西安唐都科教仪器公司Copyright Reserved 2005版权声明本用户手册的版权归西安唐都科教仪器开发有限责任公司所有,保留一切权利。

非经本公司书面许可,任何单位和个人不得擅自摘抄、复制本用户手册的部分或全部,并以任何形式传播。

西安唐都科教仪器开发有限责任公司,2001-2005(C),All right reserved.TD-PIT+实验系统用户手册©版权所有非经许可严禁复制技术支持邮箱:service@唐都公司网址:/目录第1章 TD-PIT+实验系统概述 (1)1.1 系统功能及特点 (1)1.2 系统构成 (2)1.3 TD-PIT+系统主要实验项目 (4)第2章 TD-PIT+实验系统的配置与安装 (7)2.1 系统配置 (7)2.2 TD-PIT+实验系统硬件安装 (7)2.3 TD-PIT+实验系统软件安装 (9)2.4 注意事项 (14)第3章 TD-PIT+实验系统的硬件环境 (15)3.1 概述 (15)3.2 系统总线单元电路 (15)3.3 实验平台单元电路 (16)第4章 Tddebug集成操作软件 (25)4.1 主菜单说明 (25)4.2 保护模式调试窗口说明 (25)4.3 实模式调试窗口说明 (31)4.4 微机接口技术实验操作说明 (33)第5章驱动程序开发软件环境设置 (35)5.1 WDM驱动程序开发环境的建立 (35)5.2 SoftICE调试环境的建立 (38)附录1 TD-PIT+实验系统附带光盘说明 (41)附录2 TD-PIT+实验系统单元分布图 (43)第1章TD-PIT+实验系统概述随着现代计算机技术的迅速发展,以Intel 80x86、奔腾及其以上的高级微处理器为核心的微机应用系统日益增多,各大专院校对32位微机实验教学的开展也日益加强。

为适应计算机教育的发展和各高校这种强烈的需要,西安唐都科教仪器公司在首创TD-PIT系列32位微机教学实验系统基础之上,不断创新和完善。

内存管理与保护模式

内存管理与保护模式

内存管理与保护模式本实验讨论x86采用的内存管理模式:从分段实模式到分段保护模式,再到分页虚拟内存管理,并介绍进入保护模式、启动分页机制、以及获取内存大小的基本方法。

1 x86的内存管理内存的分段(segmentation)管理符合程序的逻辑结构,利于程序的保护和动态控制。

分页(paging)则最适合虚拟内存的管理需要。

目前主流操作系统的内存管理采用的是分页方法(如类Unix),也有采用段页式的(如Wiondows)。

Intel 8086支持不带保护功能的分段内存管理,80286开始引入带保护功能的分段内存管理,80386又引入了支持虚拟内存的分页内存管理,但其分页是建立在分段基础上的。

IA-32和x64处理器,都支持段页式内存管理。

1.1 实模式Intel的16位处理器8086,采用的是分段内存管理,CPU中有CS、DS、SS和ES四个16位段寄存器,作为基地址,分别用于生成代码、数据、堆栈和其他段的物理地址:20位物理地址= 16位段寄存器值*16(或左移4位)+ 16位偏移量寻址空间只有(220=)1MB,最大段长为(216=)64KB。

因为这样的CPU只能生成和访问真实的物理内存地址,所以被称为实地址模式(real-address mode),简称为实模式(real mode)。

不过这种分段方法并不是现代的分段技术,没有提供任何内存保护功能,不能阻止内存的越界访问。

而且8086 CPU也没有提供任何特权分级,谁都可以任意改变CS、DS和SS 寄存器中的值,从而可以执行/访问内存任何地址的指令/数据,完全没有安全可言。

因此在8086 CPU上,是不可能构建现代操作系统的。

1.2 保护模式1982年推出的16位的80286处理器,在x86体系中首次引入了(分段式的)内存保护机制,称之为保护模式(protected mode)。

不过80286的保护模式只支持24位的地址空间(最多只能访问16MB内存)和16位的界限大小(最大段长为216=64KB或216+8=224=16MB),且只能从实模式进入保护模式,而不能从保护模式返回实模式。

Linux0.11——从实模式到保护模式

Linux0.11——从实模式到保护模式

Linux0.11——从实模式到保护模式综述最近在阅读Linux 0.11的源码时,对于setup.s⽂件中设置GDT表的部分不是很理解,后来经过刘国军⽼师的指点,结合赵炯博⼠的《Linux内核完全注释》的第四章《80X86保护模式及其编程》,对于保护模式有了⼀些粗浅的了解和认识。

备忘。

本⽂章主要讲解保护模式的寻址机制与setup.s中的切换部分。

保护模式保护模式运⾏在80286及其之后的所有CPU上,但是为了保证向前兼容性,正常的CPU在启动时并不会默认进⼊保护模式,⽽是会进⼊实模式,随后通过⼀系列设定转⼊保护模式。

在16位实模式下,CPU寻址时使⽤16位段寄存器的内容乘以16当作段基地址,加上16位段偏移地址形成20位的物理地址,所以最⼤寻址仅为1MB字节,最⼤段长度64KB。

在实模式下,所有的段都是可以任意访问的,即任意读、写和执⾏。

虽然在80286点CPU上已经出现了保护模式,但是其寄存器的位宽仍然是16位,只不过其地址线由20位扩⼤到了24位,寻址空间随即扩⼤到了16MB。

真正的32位保护模式出现在80386上,其地址总线和寄存器都是32位宽的,因此寻址空间扩⼤到了4GB。

保护模式下,CPU寻址主要有两种模式,⼀是分段模式,⼆是分段和分页相结合,分页⽆法单独出现。

保护模式的分段模式为每⼀段增加了段属性来限制⽤户程序对内存中⼀些段的操作。

在全局描述符表(GDT)中,每个段的表项存储了⼀个段的基本属性,例如段的基地址、段的界限、段的类型(代码段、数据段)、段的执⾏权限等。

分页模式的出现使得程序员可以编写远远⼤于内存的程序⽽⽆需担⼼内存的容量,在该模式下,内存被划分为“页”存储,磁盘的⼀部分⽤作虚拟内存,当应⽤程序执⾏时需要的某些代码或数据所在的页不在内存中时,CPU就会产⽣⼀个缺页异常,从磁盘中将所需的页调⼊内存中后恢复执⾏,在应⽤程序看来,所需的代码或数据仿佛⼀直存在内存上。

重要数据结构在保护模式中,有⼏个长得很像的名字⼀直是我们⼼头噩梦:GDT、GDTR、LGDT、LDT、LDTR、LLDT……事实上,并不是那么难区分。

保护模式知识

保护模式知识

保护模式知识序!对于学习任何编程语言的朋友来说掌握CPU的操作模式都是一件非常重要的事,其中就数保护模式这部分最重要了,现在关于保护模式的中文资料就只有杨季文先生那一家还算全面,但有些人还是觉得看不太懂,为此我就写了这篇文章,看看是否对您的胃口!一、保护模式概述顾名思义,就是对程序的运行加以保护。

我们知道在实模式下通常只能寻址1M的内存空间,且只能是单任务,就是说同一时间不能有两个任务被激活。

从8086/8088的20根地址线,80286的24根地址线到80386的32根地址线,直至今天Puntium4已经发展到了36根地址线,它们分别可以寻址1M、16M、4G、64G的内存空间,然而在实模式下,通常的寻址范围还是1M。

也就是对于在纯DOS下运行的Puntium4也只能是一个快速的8086。

前面已经说了,保护模式就是对程序的运行加以保护,所以说保护模式较实模式的增强的最主要体现还不是寻址能力而是对多任务的支持,所提到的保护就是对不同任务间和同一任务内的程序加以保护,使它们的运行不受对方“有意”或“无意”影响,但同时也要对两个任务都要用到的部分代码实现共享。

另外一个重要的增强就是对虚拟存储器的支持,从一定意义上说可以使程序设计人员不必考虑物理内存的大小。

有了新的模式,当然要有大量的新增寄存器的支持,学习这些寄存器也是学习保护模式的关键.新增寄存器如下:注:不可见的寄存器用红色标明,在后面会有讲解.以上这些都是要在后面讲到的,并且还会讲一下扩展的保护模式和扩展的V86模式!三个重要的系统表GDT、LDT和IDT首先说明的是,这三个表是在内存中由操作系统或系统程序员所建,并不是固化在哪里,所以从理论上是可以被读写的。

这三个表都是描述符表.描述符表是由若干个描述符组成,每个描述符占用8个字节的内存空间,每个描述符表内最多可以有8129个描述符.描述符是描述一个段的大小,地址及各种状态的.描述符表有三种,分别为全局描述符表GDT、局部描述符表LDT和中断描述符表IDT。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第1章保护模式编程一如果想更深、更亲近的了解电脑软件。

那么学习cpu是你的必选!! 386是CPU史的一大转折点,那386做基础课是最好不过了。

那么我们将开始进行学习之旅!!!大家跟我一块学习吧,呵呵!!!1.1 准备工作l1、NASM 编译环境(当然Masm 也可以但是用它来写COM程序比较麻烦)l2、虚拟机Virtual PC(Windows平台,执行比较快,即模拟又虚拟硬件)、WMWarve(WIndows平台虚拟硬件,)、Bochs(支持Windows平台、也支持在Linux平台上运行有RPM版本的)我们这些生长在Windows这棵大树下的朋友们,还是用Virtual PC吧.。

l3、写虚拟启动镜像文件的程序:不知道我观察的对不对?用Nasm 编译一个bin 然后将它转换为img 镜像文件的时候。

只要文件大小符合软驱的标准就能启动。

那么就代表a.bin 与a.img 文件的内容一模样就是文件大小不一样!我是不太了解镜像文件格式.我用的是Virtual PC。

1.2 开始接触引导程序1.2.1 Com文件Com文件是纯二进制的文件,也是直接与Cpu交换的顺序指令文件。

Com文件的大小是有限制的,不能超过64KB.因为8086时代的CPU地址线是20位的,20位能表达的数值也就是fffffh(1MB )。

而寄存器最高也只是16位,无法用5个F的形式来表达地址,所以用CS(段基地址)*16:IP(偏移地址)来寻址!80386后通用寄存器都得到了32位扩展! 而Cpu地址线也得到了32位的扩展。

引导程序前期是需要进入实模式的,因为这是硬件上的限制是IA32的限制。

386cpu只有两种模式: 实模式与保护模式!!!!,,1.2.2 引导程序引导程序也是有限制的,这个限制是靠Bios处理的,开机后Bios经过自检后,会从软驱或者硬盘的0面0磁道1扇区搜寻一个程序文件。

该文件的数据必需是等于512Byte,并且以aa55h结尾的(高高低低)。

那么bios会认为它是引导程序,这个时候就会把该512byte 装载到内存7c00开始处。

然后将主控权交给程序的第一行代码。

那么这个时候程序脱离Bios的控制。

Cpu将执行程序的代码.1.2.3 写一个引导程序引导程序可以说是非常简单:1、boot.asm(nasm 的源文件如下);-----------------------欲编译,这里改成100h就是com程序-------------------------------------------%define _BOOT_DEBUG_ ;做调试的时候用100h%ifdef _BOOT_DEBUG_org 0100h%elseorg 07c00h ; 告诉编译器以下代码段将从07c00h内存地址处开始%endifmov ax,cs ;让数据段与附加段寄存器跟代码段一样,因为COM代码数据是混合.mov ds,axmov es,axcall _HelloWorld ;让程序显示一个HelloWorldjmp $ ;$表示当前地址无限循环_HelloWorld:mov ax,strHello ;取得字符串的地址mov bp,ax ;给堆栈基寄存器mov cx,strLenmov ax,1301H ;ah代表功能号mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮mov dx,0001h ;显示的行与列int 10h ;bios 10h显示中断retstrHello: db "Hello World"strLen equ $ - strHellotimes 510-($-$$) db 0 ; times重复定义510-($-$$)个$$ 表示段的起始地址dw 0xAA55那么引导程序完成了,用nasm boot.asm -o 就可以运行看效果.,如改成引导程序只需把%define _DEBUG_BOOT_注释然后nasm boot.asm -o a.bin然后用工具将a.bin 转换成软驱大小的镜像文件载入虚拟机启动就可以.第2章保护模式编程二8086到80386的跳转,80386与8086在硬件上的区别在这就不说了!!那么80386与8086在软件逻辑上面的区别就是:8086是实模式,而80386 不仅包括实模式,而且还可以进入保护模式!!!保护模式不仅不受64KB内存寻址的限制,而且还拥有4GB的寻址空间。

这是因为386扩展了20地址线,将它扩展成32位了(32位能表达的字节数就是4GB).此时的段寄存器不再是段基地了,而被叫做是选择子,存放的是一个段描述符的索引值.而我们的通用寄存器与EIP 也是32位的,可以表达4GB地址!不过计算机开机后,CPU默认是实模式。

这就需要我们编程手动转换到386.那么我们该怎么去做呢:2.1 【准备GDT (全局描述符表)】首先我们需要准备GDT结构体,它是386保护模式必须的东西。

全局描述符寄存器GDTR 指向的是所有段描述符表的信息.前面提到得段选择子索引,指得就是指向段描述符的索引.段描述符是8个字节的结构体、里面存放着段的段界限、段基址、段属性等信息.LDTR寄存器是指向局部某一个段的描述符表。

段描述符表结构体用一个宏来表示(注意段1 2表示同一个段描述内容被分开来放的): 【段基址】32位、表示物理地址【段界限】20位、表示段的总长度这里并不是地址,而是段的字节长度。

【段属性】12位. 系统、门、数据等属性%macro Descriptor 3 ; 有三个参数:【段基址】、【段界限】、【段属性】dw %2 & 0FFFFh ; 段界限1 (2 字节)dw %1 & 0FFFFh ; 段基址1 (2 字节)db (%1 >> 16) & 0FFh ; 段基址1 (1 字节)dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性1 + 段界限2 + 属性2 (2 字节)db (%1 >> 24) & 0FFh ; 段基址2 (1 字节)%endmacro ; 共8 字节看似很简单的结构体理解起来可不是那么简单!【Descriptor结构体】有8个字节。

1、【第1、2字节】组合(word) 表示该段的[段界限①], dw %2 & 0FFFFh ;引用第二个参数去掉高16位2、【第3、4、5字节】组合表示该段的[段基址①],dw %1 & 0FFFFh ;先得到第一个参数(段基址)低WORD。

3、接着把第5个字节赋值,db (%1 >> 16) & 0FFh 去掉第3第4个字节的内容.再把剩下的字节赋值4、【第6个字节】是与【第7个字节】组合的内容可就更复杂了:【第6个字节】的内容:【7(p) 6(DPL) 5(DPL) 4(S) 3(Type) 2(Type) 1(Type) 0(Type)】0-3位表示:[段属性]、说明存储段描述符所描述的存储段的具体属性。

4位表示:说明描述符的类型, 对于存储段描述符而言,S=1表示是系统段描述符。

5-6位表示:DPL 该段的特权级别也就是Ring 0-3;7位表示:P: 存在(Present)位。

; P=1 表示描述符对地址转换是有效的,即描述的段在内存当中.; P=0 表示描述符对地址转换无效,即该段不存在。

使用该描述符进行内存访问时会引起异常【第7个字节】的内容:【7(G) 6(D) 5(0 ) 4(AVL) 3(段界限) 2(段界限) 1(段界限) 0(段界限)】0-3位表示:[段界限②]4位表示:软件可利用位。

80386对该位的使用未做规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。

5位表示:0 ;Intel资料也没表示6位表示:是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同,通常置17位表示:段界限粒度(Granularity)位。

G=0 表示界限粒度为字节;G=1 表示界限粒度为4K 字节。

注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位。

那么这段宏dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)表示:取[段界限]参数除去低16位取高4位,得到【段界限②】取[段属性]参数的低8位12-15位(AVL属性等)属性1 + 段界限2 + 属性2【第8个字节】的内容:[段基址②] 、db (%1 >> 24) & 0FFh 取基地址参数的最高8位那么一个Descriptor 结构体就这样成形了.2.2 【编写程序跳转到保护模式】%include "386.inc" ;是Descriptor结构体宏;%define _DEBUG_BOOT_%ifdef _DEBUG_BOOT_org 0100h%elseorg 07c00h%endifjmp LABEL_BEGIN[SECTION .gdt] ;全局描述符数据段; 段基址, 段界限, 属性LABEL_GDT: Descriptor 0, 0, 0 ;空描述符LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_CR | DA_32 ;代码段描述符LABEL_DESC_DATA: Descriptor 0,SegDataLen - 1,DA_DRW ;数据段LABEL_DESC_VIDEO: Descriptor 0B8000h,0FFFFh,DA_DRW ;显示器内存段由于DOS中断不能随意使用了,,只能输出到显示缓冲区; GDT 结束GdtLen equ $ - 1GdtPtr dw GdtLen - 1 ;GDT 的段界限,dd 0 ;GDT基地址; GDT 选择子SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT ;代码相对全局描述符起始地址的EA值SelectorData equ LABEL_DESC_DATA - LABEL_GDT ;数据段SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ;显示数据段[SECTION .s16] ;16位代码段[BITS 16] ;BITS指出处理器的模式是16位LABEL_BEGIN:mov ax, csmov ds, axmov es, axmov ss, ax ;初始化段寄存器;初始化数据mov eax,strHellomov word[LABEL_DESC_DATA + 2],axmov byte[LABEL_DESC_DATA + 4],alshr eax,16mov byte[LABEL_DESC_DATA + 7],ah; 初始化并把32位段代码的基地址分配给段描述符mov eax, LABEL_CODE32 ;mov word [LABEL_DESC_CODE32 + 2], ax ;axshr eax, 16mov byte [LABEL_DESC_CODE32 + 4], almov byte [LABEL_DESC_CODE32 + 7], ah; 为加载GDTR 作准备mov eax, LABEL_GDTmov dword [GdtPtr + 2], eax ;得到GDT基地址; 加载全局描述符的信息结构体到GDTRlgdt [GdtPtr]CA20 ;利用键盘端口打开A20地址线; 将CRO的PE位也就是0位置1 那么就进入386模式了mov eax, cr0or eax, 1mov cr0, eaxjmp dword SelectorCode32:0 ;;执行这一句会把SelectorCode32 装入cs, 并跳转到Code32Selector:0 处;这个描述符集合是以一个空描述符开始得,现在LABEL_DESC_CODE32描述符的索引值因该是8,;所以SelectorCode32的值应该就是LABEL_DESC_CODE32的索引值,Code32Selector:0当中的0是指LABEL_DESC_CODE32 的段基址+ 0;那么在打开cr0的PE位后,这个JMP指令不再是直接跳到段地址去了;;而是去GDTR全局描述符寄存器当中去找这个当前CS的索引,当前段基址+偏移的内存地址了。

相关文档
最新文档