非常好!!!【从头开始写操作系统系列】实现一个-GDT(1)【转】
转自:http://blog.csdn.net/luoyhang003/article/details/47338019
权声明:本文为博主原创文章,未经博主允许不得转载。(文章来源:http://blog.luoyuanhang.com)
在这篇文章中我们完成了以下内容:
- 介绍 GDT
- 介绍段描述符
- 实现一个段描述符
介绍 GDT
GDT 是什么?
GDT(Global Descriptor Table)是一种数据结构,用来提供段式存储机制,这种机制是通过段寄存器和 GDT 中的描述符共同提供的。
在保护模式下,虽然现在的寄存器已经有32位的,但是我们依旧采用『段:偏移』的形式来寻址,只不过『段』的概念就相当于 GDT,段值仍然由16位的 cs、ds 等寄存器表示,但是这时段值仅仅是相当于一个索引,指向一个数据结构,这个数据结构就是 GDT一个表项,这个表项定义有段的起始地址、界限、属性等内容,这个表项也叫做描述符(descriptor)
描述符结构
代码段和数据段描述符
段描述符是一个8个字节的结构体,其中包含了段基址、段界限、段属性等信息
- 段基址(32位):表示物理地址
- 段界限(20位):表示段的长度(并不是地址,而是字节长度)
- 段属性(12位):系统、门、数据等属性
下面我们来实现这个结构体:
;描述符
;3个参数:
; 1.段基址:32位(4字节)
; 2.段界限:低20位
; 3.属性:12位(高字节中的低4位总是0)
%macro Descriptor 3 ;定义宏Descriptor,有3个参数
dw %2 & 0FFFFh ;用参数2的低16位填充一个WORD
dw %1 & 0FFFFh ;用参数1的低16位填充一个WORD
db (%1 >> 16) & 0FFh ;用参数1的17-25位填充一个BYTE
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ;用参数2的17-21位以及参数3的1-8位和13-16位填充一个WORD
dw (%1 >> 24) & 0FFh ;用参数1的25-32位填充一个WORD
%endmacro
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
从代码中我们可以分析出各个参数的有效位:(F为有效)
- 段基址:0xFFFFFFFF
- 段界限:0x000FFFFF
属性:0x0000F0FF
我们得到了如下图所示的结构:

下面我们来介绍每一位的作用:
- 第0、1字节:表示段界限
- 第2、3、4字节:表示段基址
第5、6字节比较复杂
- 第5字节(从低到高):
- 0-3:TYPE,说明存储段描述符所描述的存储段的具体属性
S 段类型 类型值 说明 0 数据段 0000 只读 0 数据段 0001 只读、已访问 0 数据段 0010 读/写 0 数据段 0011 读/写、已访问 0 数据段 0100 只读、向下扩展 0 数据段 0101 只读、向下扩展、已访问 0 数据段 0110 写、向下扩展 0 数据段 0111 写、向下扩展、已访问 0 代码段 1000 只执行 0 代码段 1001 只执行、已访问 0 代码段 1010 执行/读 0 代码段 1011 执行/读、已访问 0 代码段 1100 只执行、一致码段 0 代码段 1101 只执行、一致码段、已访问 0 代码段 1110 执行/读、一致码段 0 代码段 1111 执行/读、一致码段、已访问 1 系统段 0000 (未定义) 1 系统段 0001 可用286TSS 1 系统段 0010 LDT 1 系统段 0011 忙的286TSS 1 系统段 0100 286调用门 1 系统段 0101 任务门 1 系统段 0110 286中断门 1 系统段 0111 286陷阱门 1 系统段 1000 (未定义) 1 系统段 1001 可用386TSS 1 系统段 1010 (未定义) 1 系统段 1011 忙的386TSS 1 系统段 1100 386调用门 1 系统段 1101 (未定义) 1 系统段 1110 386中断门 1 系统段 1111 386陷阱门 - 4:S,说明描述符的类型。对于存储段描述符而言,S=1,以区别与系统段描述符和门描述符(S=0)。
- 5-6:DPL,表示描述符特权级(Descriptor Privilege level),共2位。它规定了所描述段的特权级,用于特权检查,以决定对该段能否访问。
- 7:P,存在(Present)位。
- P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中
- P=0 表示描述符对地址转换无效,即该段不存在。使用该描述符进行内存访问时会引起异常。
- 第6字节
- 0-3:段界限
- 4:AVL,软件可利用位。80386对该位的使用未做规定,Intel公司也保证今后开发生产的处理器只要与80386兼容,就不会对该位的使用做任何定义或规定。
- 5:0(未定义)
- 6:D/B,D位是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同。
- 在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小
- D=1表示默认情况下指令使用32位地址及32位或8位操作数,这样的代码段也称为32位代码段;
- D=0 表示默认情况下,使用16位地址及16位或8位操作数,这样的代码段也称为16位代码段,它与80286兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。
- 在向下扩展数据段的描述符中,D位决定段的上部边界
- D=1表示段的上部界限为4G
- D=0表示段的上部界限为64K,这是为了与80286兼容
- 在描述由SS寄存器寻址的段描述符中,D位决定隐式的堆栈访问指令(如PUSH和POP指令)使用何种堆栈指针寄存器
- D=1表示使用32位堆栈指针寄存器ESP;
- D=0表示使用16位堆栈指针寄存器SP,这与80286兼容
- 在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小
7:G,段界限粒度(Granularity)位
- G=0 表示界限粒度为字节
- G=1 表示界限粒度为4K 字节
注意,界限粒度只对段界限有效,对段基地址无效,段基地址总是以字节为单位
- 第5字节(从低到高):
版权声明:本文为博主原创文章,未经博主允许不得转载。
非常好!!!【从头开始写操作系统系列】实现一个-GDT(1)【转】的更多相关文章
- 从头开始写框架(一):浅谈JS模块化发展
博客申请下来已经过去一个月了,一直不知道写点什么,毕竟我的文笔不是很好orz. 不过既然申请下来了,不写点什么总是觉得很可惜.正好最近在自己写框架,就把自己的进程和一些心得体会分享出来吧. 写在前面: ...
- 用Qt写软件系列三:一个简单的系统工具(上)
导言 继上篇<用Qt写软件系列二:QIECookieViewer>之后,有一段时间没有更新博客了.这次要写的是一个简单的系统工具,需求来自一个内部项目.功能其实很简单,就是查看当前当前系统 ...
- 给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器
今天的主角是HashSet,Set是什么东东,当然也是一种java容器了. 现在再看到Hash心底里有没有会心一笑呢,这里不再赘述hash的概念原理等一大堆东西了(不懂得需要先回去看下Has ...
- 【百度地图-安卓SDK】从头开始写android程序
[百度地图-安卓SDK]从头开始写android程序首先确保有这四个文件 安装jdk先安装android开发SDK(并不只是为eclipse服务的),即运行installer_r15-windo ...
- 给jdk写注释系列之jdk1.6容器(13)-总结篇之Java集合与数据结构
是的,这篇blogs是一个总结篇,最开始的时候我提到过,对于java容器或集合的学习也可以看做是对数据结构的学习与应用.在前面我们分析了很多的java容器,也接触了好多种常用的数据结构,今天 ...
- 给jdk写注释系列之jdk1.6容器(12)-PriorityQueue源码解析
PriorityQueue是一种什么样的容器呢?看过前面的几个jdk容器分析的话,看到Queue这个单词你一定会,哦~这是一种队列.是的,PriorityQueue是一种队列,但是它又是一种什么样的队 ...
- 给jdk写注释系列之jdk1.6容器(11)-Queue之ArrayDeque源码解析
前面讲了Stack是一种先进后出的数据结构:栈,那么对应的Queue是一种先进先出(First In First Out)的数据结构:队列. 对比一下Stack,Queue是一种先进先出的容 ...
- 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析
前面我们已经接触过几种数据结构了,有数组.链表.Hash表.红黑树(二叉查询树),今天再来看另外一种数据结构:栈. 什么是栈呢,我就不找它具体的定义了,直接举个例子,栈就相当于一个很窄的木桶 ...
- 给jdk写注释系列之jdk1.6容器(9)-Strategy设计模式之Comparable&Comparator接口
前面我们说TreeMap和TreeSet都是有顺序的集合,而顺序的维持是要靠一个比较器Comparator或者map的key实现Comparable接口. 既然说到排序,首先我们不用去关心什 ...
随机推荐
- linux php
ubuntu php -v 查看php版本号 查看目录 cd / ls apache: 如果采用RPM包安装,安装路径应在/etc/httpd目录下 apache配置文件:/etc/httpd/con ...
- 线性四叉树十进制Morton码计算示例
线性四叉树十进制Morton码计算,具体算法描述龚健雅<地理信息系统基础>P108
- css页面布局
写在前面: 页面布局整体上可以分为两类:固定宽度(一般固定960px):流式布局:将流式布局转换为固定布局很容易,只需要外围再包括一个div,为其设置宽度即可. html默认的布局方式是将每个块状标签 ...
- Xcode 6.x 添加Empty Application模板
Xcode 6.x 添加Empty Application模板 在Apple最新的XCode6.x中没有了Empty Application模板,这对一个老人来说是不能别接受的,同时也可以看出Appl ...
- 线程池——JAVA并发编程指南
TPS00-J. 用线程池实现应用在流量暴涨时优雅降级 很多程序都要解决这样一个问题——处理一系列外来的请求.Thread- Per-Message这种设计模式是最简单的并发策略了,它为每一个请求创建 ...
- arping 通知网关刷新IP
arping -c 2 -I em1 -s 192.168.110.12 192.168.110.1
- oracle调整表中列顺序
有一个哥们提出一个问题: 有个表,创建时候的列顺序是a,b,c 如何使用select * 的时候,让列的显示顺序是a,c,b 而且任性地必须使用select *来查询,且不能重建表. 假设有个表tes ...
- java程序员从笨鸟到菜鸟之(七)一—java数据库操作
本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 数据库访问几乎每一个稍微成型的程序都要用到的知识,怎么高效的访问数据库也是我们学习的一个 ...
- PostgreSQL 系统的基本体系结构
PostgreSQL 使用客户机/服务器(C/S)的模式提供服务,一个PostgreSQL会话由下列相关的进程(程序)组成: (1)一个服务器端进程.该进程管理数据库文件,接受客户端与数据库的连接,且 ...
- 如何不切换windows登陆用户,更换用户名访问共享文件夹
@echo offnet use * /del /ynet use \\192.168.2.1 /user:wr@echo off 先进行删除所有,然后在进行映射,按照部门来,不同的部门可能需要映射的 ...