﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-xingkongyun-文章分类-操作系统</title><link>http://www.cppblog.com/xingkongyun/category/8310.html</link><description>星空陨的程序小站</description><language>zh-cn</language><lastBuildDate>Wed, 29 Oct 2008 13:54:31 GMT</lastBuildDate><pubDate>Wed, 29 Oct 2008 13:54:31 GMT</pubDate><ttl>60</ttl><item><title>Bochs调试指令</title><link>http://www.cppblog.com/xingkongyun/articles/65033.html</link><dc:creator>杨彬彬</dc:creator><author>杨彬彬</author><pubDate>Sat, 25 Oct 2008 13:59:00 GMT</pubDate><guid>http://www.cppblog.com/xingkongyun/articles/65033.html</guid><wfw:comment>http://www.cppblog.com/xingkongyun/comments/65033.html</wfw:comment><comments>http://www.cppblog.com/xingkongyun/articles/65033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingkongyun/comments/commentRss/65033.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingkongyun/services/trackbacks/65033.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><strong><span>Bochs</span></strong><strong><span>调试指令</span></strong><strong></strong></p>
<p>&nbsp;</p>
<p><span>（</span><span>1</span><span>）</span><span>b addr </span><span>在物理地址处设置断点</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>2</span><span>）</span><span>lb&nbsp;</span><span>在线性地址处设置断点</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>3</span><span>）</span><span>info break </span><span>显示当前所有的断点的信</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>4</span><span>）</span><span>c </span><span>继续执行知道遇到断点</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>5</span><span>）</span><span>n </span><span>单步执行，跳过子程序</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>6</span><span>）</span><span>s </span><span>单步执行</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>7</span><span>）</span><span>s num ( s</span><span>指令后加一数字</span><span>)&nbsp;</span><span>执行</span><span>n</span><span>步</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>8</span><span>）</span><span>dump_cpu </span><span>查看寄存器信息</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>9</span><span>）</span><span>xp /nuf addr </span><span>显示物理内存的数据</span></p>
<p><span>(</span><span>例</span><span>:xp /32bx 0x7c00 ----</span><span>显示</span><span>0x7c00 </span><span>开始处的内存内容</span></p>
<p><span>32bx --b </span><span>代表显示字节</span> <span>x </span><span>表示以</span><span>16</span><span>进制显示</span><span>)</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>10</span><span>）</span><span>x /nuf addr </span><span>显示线性内存地址的数据</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>11</span><span>）</span><span>disassemble [/count] start end&nbsp;</span><span>反汇编一段线性内存</span></p>
<p><span>u [/count] start end&nbsp;</span><span>反汇编一段线性内存</span><span>(</span><span>作用与上面的一样</span><span>)</span></p>
<p><span>(count </span><span>参数指明要反汇编的指令条数</span><span>&nbsp;,</span><span>例子：</span><span>u /5 --</span><span>反汇编从当前地址开始的</span><span>5</span><span>条指令</span><span>)</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>（</span><span>12</span><span>）</span><span>vbreak segment:offset </span><span>在指定的虚拟地址处设置断点（段地址：偏移）</span></p>
<p>&nbsp;</p>
<p><span>（</span><span>13</span><span>）</span><span>info</span><span>指令组</span></p>
<p><span>info break </span><span>展示当前的断点状态信息</span></p>
<p><span>info dirty </span><span>展示自从上次显示以来物理内存中的脏页（被写的页）</span></p>
<p><span>info program </span><span>展示程序的执行状态</span></p>
<p><span>info r|reg|rigisters </span><span>展示寄存器内容</span></p>
<p><span>info cpu </span><span>展示</span><span>CPU</span><span>寄存器内容</span></p>
<p><span>info fpu </span><span>展示</span><span>FPU</span><span>寄存器的状态</span></p>
<p><span>info idt </span><span>展示中断描述表</span></p>
<p><span>info ivt </span><span>展示中断向量表</span><span>(</span><span>保护模式下无效</span><span>)</span></p>
<p><span>info gdt </span><span>展示全局描述表</span></p>
<p><span>info tss </span><span>展示当前的任务状态段</span></p>
<p><span>info cr&nbsp;</span><span>展示</span><span>CR0-CR4</span><span>寄存器状态</span></p>
<p><span>info flags </span><span>展示标志寄存器</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/xingkongyun/aggbug/65033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingkongyun/" target="_blank">杨彬彬</a> 2008-10-25 21:59 <a href="http://www.cppblog.com/xingkongyun/articles/65033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>保护模式下DPL,RPL,CPL的区别</title><link>http://www.cppblog.com/xingkongyun/articles/63495.html</link><dc:creator>杨彬彬</dc:creator><author>杨彬彬</author><pubDate>Wed, 08 Oct 2008 12:28:00 GMT</pubDate><guid>http://www.cppblog.com/xingkongyun/articles/63495.html</guid><wfw:comment>http://www.cppblog.com/xingkongyun/comments/63495.html</wfw:comment><comments>http://www.cppblog.com/xingkongyun/articles/63495.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingkongyun/comments/commentRss/63495.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingkongyun/services/trackbacks/63495.html</trackback:ping><description><![CDATA[&nbsp;
<p><strong>&nbsp;</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong><span>1.</span></strong><strong><span>当前特权</span><span>CPL(</span></strong><strong><span>Current</span><span> Privilege Level)</span></strong></p>
<p><span>&nbsp;CPL</span><span>是当前进程的权限级别</span><span>(Current Privilege Level)</span><span>，是当前正在执行的代码所在的段的特权级，存在于</span><span>cs</span><span>寄存器的低两位。</span></p>
<p>&nbsp;</p>
<p><strong><span>2.</span></strong><strong><span>描述符特权级</span><span>DPL(</span></strong><strong><span>Descriptor</span><span> Privilege Level)</span></strong><span><br>&nbsp;&nbsp;DPL</span><span>存储在段描述符中，规定访问该段的权限级别</span><span>(Descriptor Privilege Level)</span><span>，每个段的</span><span>DPL</span><span>固定。</span><span><br><br></span><strong></strong></p>
<p><strong><span>3.</span></strong><strong><span>请求特权级</span><span>RPL(Request Privilege Level)</span></strong></p>
<p><span>RPL</span><span>保存在选择子的最低两位。</span><span>RPL</span><span>说明的是进程对段访问的请求权限，意思是当前进程想要的请求权限。</span><span>RPL</span><span>的值由程序员自己来自由的设置，并不一定</span><span>RPL&gt;=CPL</span><span>，但是当</span><span>RPL&lt;CPL</span><span>时，实际起作用的就是</span><span>CPL</span><span>了，因为访问时的特权检查是判断：</span><span>EPL=max(RPL,CPL)&lt;=DPL</span><span>是否成立，所以</span><span>RPL</span><span>可以看成是每次访问时的附加限制，</span><span>RPL=0</span><span>时附加限制最小，</span><span>RPL=3</span><span>时附加限制最大。所以你不要想通过来随便设置一个</span><span>RPL</span><span>来访问一个比</span><span>CPL</span><span>更内层的段。</span></p>
<p><strong><span>对于为甚麽在</span><span>CPL</span></strong><strong><span>之外在增加一个</span><span>RPL</span></strong><strong><span>的原因：</span></strong></p>
<p><span>Intel</span><span>手册上的解释为：</span><span>The RPL can be used to insure that privileged code does not access a segment on behalf of an application program unless the program itself has access privileges for that segment.</span></p>
<p><span>（</span><span>RPL</span><span>能够用来确保具有特权级的代码不会代表另一个应用程序去访问一个段，除非那个应用程序具有访问那个段的权限</span><span>.</span><span>）</span></p>
<p><span>比方说：</span><span>A</span><span>进程的</span><span>DPL</span><span>为</span><span>0</span><span>，</span><span>C</span><span>进程的</span><span>DPL</span><span>为</span><span>1</span><span>，现在有一个</span><span>B</span><span>进程他的</span><span>DPL</span><span>为</span><span>2</span><span>，这</span><span>B</span><span>进程想委托</span><span>A</span><span>进程去访问</span><span>C</span><span>的数据，如果没有</span><span>RPL</span><span>的话这样的委托访问是可以成功的，但这样是非常不安全的。有了</span><span>RPL</span><span>以后</span><span>A</span><span>进程在访问</span><span>C</span><span>的时候还要受到</span><span>RPL</span><span>的约束，此时可以将访问</span><span>C</span><span>的选择子的</span><span>RPL</span><span>设为</span><span>B</span><span>的</span><span>DPL</span><span>，这样</span><span>A</span><span>的访问权限就相当为</span><span>EPL=max</span><span>（</span><span>RPL</span><span>，</span><span>DPL</span><span>）</span><span>=2</span><span>，这样他就无法代表</span><span>B</span><span>去越权访问</span><span>C</span><span>了。</span></p>
<p>&nbsp;</p>
<p><span>在网上还有一个形象的例子，一起贴出来：</span></p>
<p align=left><span>一个农民</span><span>(</span><span>低特权级</span><span>)</span><span>请县长</span><span>(</span><span>高特权级</span><span>)</span><span>打听一种超级种子，如果找到的话帮忙拿一点回来，听闻这种超级种子可让收成倍增。县长说：好！我认识很多当官的，我可以帮你打听一下哪里有，但是有些地方如果需要表示身分的话我只能说我是农民的代理人。县长利用自己的身份很容易找到了种子在哪里</span><span>---</span><span>找的时候没有人问起他代表谁。县长问种子管理员可不可以给他一点，管理员说种子不能给农民因为种子还在试验阶段，我们可以给县长让他们带回当地的专家来帮忙一起做试验，但是一定要县长来申请。那你是谁？县长说我是农民的代理人，因为县长保证他会这样回答的</span><span>(</span><span>他也不知道那农民是不是专家</span><span>)</span><span>，管理员当然不给。县长没办法只能告诉农民拿不到种子。这件事里面县长是以县长的身份帮农民找到种子，但需要表示身分的时候他说只是农民的代理人。这样做县长可以帮人但也不会给别人利用。</span><span>(</span><span>农民可能把种子拿回来卖钱也说不定，没人知道</span><span>)<br></span><span>在这里</span><span>RPL</span><span>就是县长的另一个身份</span><span>---</span><span>农民的代理人也就是农民</span><span>---</span><span>他会带在身上，人家没有问他的时候他不会告诉别人，所以别人也就以县长的身分来看待他。当查身份的时候他才告诉你</span><span>---</span><span>我是农民的代理人。</span><span><br><br></span></p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/xingkongyun/aggbug/63495.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingkongyun/" target="_blank">杨彬彬</a> 2008-10-08 20:28 <a href="http://www.cppblog.com/xingkongyun/articles/63495.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>地址环绕和A20地址线问题</title><link>http://www.cppblog.com/xingkongyun/articles/63417.html</link><dc:creator>杨彬彬</dc:creator><author>杨彬彬</author><pubDate>Tue, 07 Oct 2008 09:51:00 GMT</pubDate><guid>http://www.cppblog.com/xingkongyun/articles/63417.html</guid><wfw:comment>http://www.cppblog.com/xingkongyun/comments/63417.html</wfw:comment><comments>http://www.cppblog.com/xingkongyun/articles/63417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingkongyun/comments/commentRss/63417.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingkongyun/services/trackbacks/63417.html</trackback:ping><description><![CDATA[转自：<a href="http://www.eetop.cn/blog/html/64/64964-2377.html">http://www.eetop.cn/blog/html/64/64964-2377.html</a><br><br>
<p>早期的8086只有20根地址线，只能访问1M的地址空间。CPU寻址则按段+偏移的方式进行。16位段+16位偏移的可能的范围是0~0x10FFEF（即0xFFFF0+0xFFFF），即1M+65520字节的范围。由于只有20根地址线，所以在对1M~1M+65520范围进行访问时，会发生&#8220;地址回绕&#8221;的现象，就是说实际会访问到0~65520的地方。据说某个著名的/臭名昭著的软件利用了这个特点。在80286，386等CPU上，它会失败，因为这些CPU有多于20根的地址线，并不产生&#8220;地址回绕&#8221;现象。为了保持完全的兼容性，IBM决定在PC AT系统上加个逻辑，来模仿以上的回绕特征。他们的方法就是把A20和键盘控制器的一个输出进行AND，这样来控制A20的打开和关闭。一开始时A20是被屏蔽的（总为0），直到系统软件去打开它。</p>
<p>&nbsp;</p>
<p><strong>A20地址线问题</strong> <br>&nbsp;1981年8月，IBM公司最初推出的个人计算机IBM PC使用的CPU是Intel 8088。在该微机中地址线<br>只有20根(A0 &#8211; A19)。在当时内存RAM只有几百KB或不到1MB时，20根地址线已足够用来寻址这些<br>内存。其所能寻址的最高地址是0xffff:0xffff，也即0x10ffef。对于超出0x100000(1MB)的寻址地址将默认<br>地环绕到0x0ffef。当IBM公司于1985年引入AT机时，使用的是Intel 80286 CPU，具有24根地址线，最<br>高可寻址16MB，并且有一个与8088完全兼容的实模式运行方式。然而，在寻址值超过1MB时它却不能<br>象8088那样实现地址寻址的环绕。但是当时已经有一些程序是利用这种地址环绕机制进行工作的。为了<br>实现完全的兼容性，IBM公司发明了使用一个开关来开启或禁止0x100000地址比特位。由于在当时的8042<br>键盘控制器上恰好有空闲的端口引脚（输出端口P2，引脚P21），于是便使用了该引脚来作为与门控制这<br>个地址比特位。该信号即被称为A20。如果它为零，<strong>则比特20及以上地址都被清除</strong>。从而实现了兼容性。 <br>&nbsp;由于在机器启动时，默认条件下，A20地址线是禁止的，所以操作系统必须使用适当的方法来开启它。<br>但是由于各种兼容机所使用的芯片集不同，要做到这一点却是非常的麻烦。因此通常要在几种控制方法中<br>选择。</p>
<p>&nbsp;<br>&nbsp;对A20信号线进行控制的常用方法是通过设置键盘控制器的端口值。&nbsp;有些操作系统将A20的开启和禁止作</p>
<p>为实模式与保护运行模式之间进行转换的标准过程中的一部分。<br>由于键盘的控制器速度很慢，因此就不能使用键盘控制器对A20线来进行操作。为此引进了一个A20快<br>速门选项(Fast Gate A20)，它使用I/O端口0x92来处理A20信号线，避免了使用慢速的键盘控制器操作方<br>式。对于不含键盘控制器的系统就只能使用0x92端口来控制，但是该端口也有可能被其它兼容微机上的<br>设备（如显示芯片）所使用，从而造成系统错误的操作。 <br>&nbsp;还有一种方式是通过读0xee端口来开启A20信号线，写该端口则会禁止A20信号线。</p>
<img src ="http://www.cppblog.com/xingkongyun/aggbug/63417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingkongyun/" target="_blank">杨彬彬</a> 2008-10-07 17:51 <a href="http://www.cppblog.com/xingkongyun/articles/63417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于80x86处理器保护模式下存储段描述符属性中类型小结</title><link>http://www.cppblog.com/xingkongyun/articles/62743.html</link><dc:creator>杨彬彬</dc:creator><author>杨彬彬</author><pubDate>Thu, 25 Sep 2008 02:09:00 GMT</pubDate><guid>http://www.cppblog.com/xingkongyun/articles/62743.html</guid><wfw:comment>http://www.cppblog.com/xingkongyun/comments/62743.html</wfw:comment><comments>http://www.cppblog.com/xingkongyun/articles/62743.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xingkongyun/comments/commentRss/62743.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xingkongyun/services/trackbacks/62743.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><strong><span>关于</span></strong><strong><span>80x86</span></strong><strong><span>处理器保护模式下存储段描述符属性中类型小结</span></strong><strong></strong></p>
<p align=center><strong>&nbsp;</strong></p>
<p><strong><span>*1.</span></strong><strong><span>存储段描述符</span></strong></p>
<p><strong>&nbsp;</strong></p>
<p><span>80x86</span><span>存储段描述符</span><span>(</span><span>共</span><span>8</span><span>字节</span><span>)</span></p>
<p><img height=177 alt="" src="http://www.cppblog.com/images/cppblog_com/xingkongyun/t1.JPG" width=718 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(</span><span>图</span><span>1)</span></p>
<p><span>属性字段（第</span><span>5</span><span>，</span><span>6</span><span>字节）</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>我们先来看看这</span><span>8</span><span>个字节中我感觉最复杂的</span><span>TYPE</span><span>这四位标志吧，然后在看看其他的位</span></p>
<p><span>第五字节低四位为描述符的类型描述，下面主要将这四位单独抽出进行说明</span><span>:</span></p>
<p><span>__________________________________</span></p>
<p><span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|</span></p>
<p><span>|&nbsp;3<span>&nbsp;&nbsp; </span>|&nbsp;2<span>&nbsp;&nbsp;&nbsp; </span>|&nbsp;1&nbsp;|&nbsp;0&nbsp;|</span></p>
<p><span>|&nbsp;E<span>&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|&nbsp;A&nbsp;|</span></p>
<p><span>_________________________________</span></p>
<p>&nbsp;</p>
<p><span>(1)</span><span>位</span><span>0</span><span>指示描述符是否被访问过</span><span>(Accessed)</span><span>，用符号</span><span>A</span><span>标记。</span><span>A=0</span><span>表示尚未被访问，</span><span>A=1 </span><span>表示段已被访问。当把描述符的相应选择子装入到段寄存器时，</span><span>80386</span><span>把该位置为</span><span>1</span><span>，表明描述符已被访问。操作系统可测试访问位，已确定描述符是否被访问过</span></p>
<p><span>(2)</span><span>位</span><span>3</span><span>指示所描述的段是代码段还是数据段，用符号</span><span>E</span><span>标记。</span><span>E=0</span><span>表示段为数据段，相应的描述符也就是数据段</span><span>(</span><span>包括堆栈段</span><span>)</span><span>描述符。数据段是不可执行的，但总是可读的。</span><span> E=1</span><span>表示段是可执行段，即代码段，相应的描述符就是代码段描述符。代码段总是不可写的，若需要对代码段进行写入操作，则必须使用别名技术，即用一个可写的数据段描述符来描述该代码段，然后对此数据段进行写入。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>___________________________________</span></p>
<p><span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|</span></p>
<p><span>|&nbsp;3<span>&nbsp;&nbsp; </span>|&nbsp;2<span>&nbsp;&nbsp;&nbsp; </span>|&nbsp;1&nbsp;|&nbsp;0&nbsp;|</span></p>
<p><span>|&nbsp;E=0 |&nbsp;ED<span>&nbsp;&nbsp; </span>|&nbsp;W&nbsp;| &nbsp;A&nbsp;|</span></p>
<p><span>_________________________________</span></p>
<p><span>(3)</span><span>在数据段描述符中</span><span>(E=0</span><span>的情况</span><span>, </span><span>，如上图所示</span><span>)</span><span>，</span><span>TYPE</span><span>中的位</span><span>1</span><span>指示所描述的数据段是否可写，用</span><span>W</span><span>标记。</span><span> W=0</span><span>表示对应的数据段不可写。反之，</span><span>W=1</span><span>表示数据段是可写的。注意，数据段总是可读的。</span></p>
<p><span>TYPE</span><span>中的位</span><span>2</span><span>是</span><span>ED</span><span>位，指示所描述的数据段的扩展方向。</span><span>ED=0</span><span>表示数据段向高端扩展，也即段内偏移必须小于等于段界限。</span><span>ED=1</span><span>表示数据段向低扩展，段内偏移必须大于段界限。</span><span> </span></p>
<p><span>___________________________________</span></p>
<p><span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|<span>&nbsp;&nbsp;&nbsp;&nbsp; </span>|</span></p>
<p><span>|&nbsp;3<span>&nbsp;&nbsp; </span>|&nbsp;2<span>&nbsp;&nbsp;&nbsp; </span>|&nbsp;1&nbsp;|&nbsp;0&nbsp;|</span></p>
<p><span>|&nbsp;E=1 |&nbsp;C<span>&nbsp;&nbsp;&nbsp; </span>|&nbsp;R&nbsp;|&nbsp;A&nbsp;|</span></p>
<p><span>_________________________________</span></p>
<p><span>(4)</span><span>在代码段描述符中</span><span>(E=1</span><span>的情况，如上图所示</span><span>)</span><span>，</span><span>TYPE</span><span>中的位</span><span>1</span><span>指示所描述的代码段是否可读，用符号</span><span>R</span><span>标记。</span><span>R=0</span><span>表示对应的代码段不可读，只能执行。</span><span>R=1</span><span>表示对应的代码段可读可执行。注意代码段总是不可写的，若需要对代码段进行写入操作，则必须使用别名技术。</span></p>
<p><span>在代码段中，</span><span>TYPE</span><span>中的位</span><span>2</span><span>指示所描述的代码段是否是一致代码段，用</span><span>C</span><span>标记。</span><span>C=0</span><span>表示对应的代码段是非一致代码段</span><span>(</span><span>普通代码段</span><span>)</span><span>，</span><span>C=1</span><span>表示对应的代码段是一致代码段。</span></p>
<p>&nbsp;</p>
<p><span>小结：（如下图）</span></p>
<p><img height=256 alt="" src="http://www.cppblog.com/images/cppblog_com/xingkongyun/t2.JPG" width=703 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(</span><span>图</span><span>2)</span></p>
<p>&nbsp;</p>
<p><span>上面这些我在初学保护模式的时候感觉很迷惑，所以先拿出来说说，下面再看看其他的标志位</span><span>.</span></p>
<p>&nbsp;</p>
<p><span>一．段基址与段界限</span></p>
<p><span>从图一我们可以看出基地址长</span><span>32</span><span>位，被安排在</span><span>2</span><span>，</span><span>3</span><span>，</span><span>4</span><span>，</span><span>7</span><span>字节中，段界限长</span><span>20</span><span>位，被安排在</span><span>0</span><span>，</span><span>1</span><span>字节与第</span><span>6</span><span>字节的低</span><span>4</span><span>位中。</span></p>
<p><span>使用两个域存放段基地址和段界限的原因与</span><span>80286</span><span>有关。在</span><span>80286</span><span>保护方式下，段基地址只有</span><span>24</span><span>位长，而段界限只有</span><span>16</span><span>位长。</span><span>80286</span><span>存储段描述符尽管也是</span><span>8</span><span>字节长，但实际只使用低</span><span> 6</span><span>字节，高</span><span>2</span><span>字节必须置为</span><span>0</span><span>。</span><span>80386</span><span>存储段描述符这样的安排，可使得</span><span>80286</span><span>的存储段描述符的格式在</span><span>80386</span><span>下继续有效。</span></p>
<p>&nbsp;</p>
<p><span>二</span><span>.</span></p>
<p><span>(1)P</span><span>位称为存在</span><span>(Present)</span><span>位。</span><span>P=1</span><span>表示描述符对地址转换是有效的，或者说该描述符所描述的段存在，即在内存中；</span><span>P=0</span><span>表示描述符对地址转换无效，即该段不存在。使用该描述符进行内存访问时会引起异常。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>(2)DPL</span><span>表示描述符特权级</span><span>(Descriptor Privilege level)</span><span>，共</span><span>2</span><span>位。它规定了所描述段的特权级，用于特权检查，以决定对该段能否访问</span></p>
<p><span>&nbsp;</span></p>
<p><span>(3)DT</span><span>位说明描述符的类型。对于存储段描述符而言，</span><span>DT=1</span><span>，以区别与系统段描述符和门描述符</span><span>(DT=0)</span><span>。</span></p>
<p>&nbsp;</p>
<p><span>(4)TYPE</span><span>标志，即开篇讲得那堆。</span></p>
<p>&nbsp;</p>
<p><span>(5)G</span><span>为就是段界限粒度</span><span>(Granularity)</span><span>位。</span><span>G=0</span><span>表示界限粒度为字节；</span><span>G=1</span><span>表示界限粒度为</span><span>4K </span><span>字节。注意，界限粒度只对段界限有效，对段基地址无效，段基地址总是以字节为单位。</span></p>
<p>&nbsp;</p>
<p><strong><em><span>补充</span></em></strong><span>：</span><span>段界限规定段的大小。在<span>80386</span>保护模式下，段界限用<span>20</span>位表示，而且段界限可以是以字节为单位或以<span>4K</span>字节为单位。段属性中有一位对此进行定义，把该位成为粒度位，用符号<span>G</span>标记。<span>G=0</span>表示段界限以字节位位单位，于是<span>20</span>位的界限可表示的范围是<span>1</span>字节至<span>1M</span>字节，增量为<span>1</span>字节；<span>G=1</span>表示段界限以<span>4K</span>字节为单位，于是<span>20</span>位的界限可表示的范围是<span>4K</span>字节至<span>4G</span>字节，增量为<span>4K</span>字节。当段界限以<span>4K</span>字节为单位时，实际的段界限<span>LIMIT</span>可通过下面的公式从<span>20 </span>位段界限<span>Limit</span>计算出来：<span> </span></span></p>
<p align=left><span>LIMIT=limit*4K+0FFFH=(Limit SHL 12)+0FFFH</span></p>
<p align=left><span>所以当粒度为<span>1</span>时，段的界限实际上就扩展成<span>32</span>位。由此可见，在<span>80386</span>保护模式下，段的长度可大大超过<span>64K</span>字节。 </span></p>
<p align=left>&nbsp;</p>
<p align=left>&nbsp;</p>
<p><span>&nbsp;(6)D</span><span>位是一个很特殊的位，在描述可执行段、向下扩展数据段或由</span><span>SS</span><span>寄存器寻址的段</span><span>(</span><span>通常是堆栈段</span><span>)</span><span>的三种描述符中的意义各不相同。</span><span> </span></p>
<p><span>在描述可执行段的描述符中，</span><span>D</span><span>位决定了指令使用的地址及操作数所默认的大小。</span><span>D=1</span><span>表示默认情况下指令使用</span><span>32</span><span>位地址及</span><span>32</span><span>位或</span><span>8</span><span>位操作数，这样的代码段也称为</span><span>32</span><span>位代码段；</span><span>D=0 </span><span>表示默认情况下，使用</span><span>16</span><span>位地址及</span><span>16</span><span>位或</span><span>8</span><span>位操作数，这样的代码段也称为</span><span>16</span><span>位代码段，它与</span><span>80286</span><span>兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。</span><span> </span></p>
<p><span>在向下扩展数据段的描述符中，</span><span>D</span><span>位决定段的上部边界。</span><span>D=1</span><span>表示段的上部界限为</span><span>4G</span><span>；</span><span>D=0</span><span>表示段的上部界限为</span><span>64K</span><span>，这是为了与</span><span>80286</span><span>兼容。</span><span> </span></p>
<p><span>在描述由</span><span>SS</span><span>寄存器寻址的段描述符中，</span><span>D</span><span>位决定隐式的堆栈访问指令</span><span>(</span><span>如</span><span>PUSH</span><span>和</span><span>POP</span><span>指令</span><span>)</span><span>使用何种堆栈指针寄存器。</span><span>D=1</span><span>表示使用</span><span>32</span><span>位堆栈指针寄存器</span><span>ESP</span><span>；</span><span>D=0</span><span>表示使用</span><span>16</span><span>位堆栈指针寄存器</span><span>SP</span><span>，这与</span><span>80286</span><span>兼容。</span></p>
<p>&nbsp;</p>
<p><span>(7)AVL</span><span>位是软件可利用位。</span><span>80386</span><span>对该位的使用未左规定，</span><span>Intel</span><span>公司也保证今后开发生产的处理器只要与</span><span>80386</span><span>兼容，就不会对该位的使用做任何定义或规定。</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>三：</span><span>.</span><span>存储段描述符的结构类型表示</span></p>
<p>&nbsp;</p>
<p><span>; </span><span>宏</span><span> (</span><span>注：采用</span><span>nasm</span><span>语法）</span></p>
<p><span>; </span><span>描述符</span></p>
<p><span>; usage: Descriptor Base, Limit, Attr</span></p>
<p><span>;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Base:&nbsp;dd</span></p>
<p><span>;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Limit: dd (low 20 bits available)</span></p>
<p><span>;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Attr:&nbsp;dw (lower 4 bits of higher byte are always 0)</span></p>
<p><span>%macro Descriptor 3</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dw<span>&nbsp;&nbsp; </span>%2 &amp; 0FFFFh<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; </span><span>段界限</span><span> 1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(2 </span><span>字节</span><span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dw<span>&nbsp;&nbsp; </span>%1 &amp; 0FFFFh<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; </span><span>段基址</span><span> 1<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(2 </span><span>字节</span><span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>db<span>&nbsp;&nbsp;&nbsp; </span>(%1 &gt;&gt; 16) &amp; 0FFh<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; </span><span>段基址</span><span> 2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(1 </span><span>字节</span><span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>dw<span>&nbsp;&nbsp; </span>((%2 &gt;&gt; 8) &amp; 0F00h) | (%3 &amp; 0F0FFh)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; </span><span>属性</span><span> 1 + </span><span>段界限</span><span> 2 + </span><span>属性</span><span> 2<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(2 </span><span>字节</span><span>)</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>db<span>&nbsp;&nbsp;&nbsp; </span>(%1 &gt;&gt; 24) &amp; 0FFh<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>; </span><span>段基址</span><span> 3<span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>(1 </span><span>字节</span><span>)</span></p>
<p><span>%endmacro ; </span><span>共</span><span> 8 </span><span>字节</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong><span>*2.</span></strong><strong><span>系统段描述符</span></strong><strong></strong></p>
<p><span>在上面我们讲过对于存储段描述符其</span><span>DT</span><span>位为</span><span>1</span><span>，当描述符的</span><span>DT</span><span>位为</span><span>0</span><span>时，那么这个描述符所描述的就是一个系统段描述符了。</span></p>
<p>&nbsp;</p>
<p><span>系统段是为了实现存储管理机制所使用的一种特别的段。在</span><span>80386</span><span>中，有两种系统段：任务状态段</span><span>TSS</span><span>和局部描述符表</span><span>LDT</span><span>段。用于描述系统段的描述符称为系统段描述符。</span></p>
<p>&nbsp;</p>
<p><span>系统段描述符与存储段描述符几乎一模一样，但也有一定的差别：</span></p>
<p><span><span>(1)<span>&nbsp;&nbsp; </span></span></span><span>DT</span><span>位，</span><span>DT=1</span><span>表示存储段，</span><span>DT=0</span><span>表示系统段。</span></p>
<p><span><span>(2)<span>&nbsp;&nbsp; </span></span></span><span>D</span><span>位，</span><span>D</span><span>位在系统段中不使用。</span></p>
<p><span><span>(3)<span>&nbsp;&nbsp; </span></span></span><span>与存储段最不相同的是</span><span>TYPE</span><span>段。</span><span>系统段描述符的类型字段<span>TYPE</span>仍是<span>4</span>位，其其含义与存储段描述符的类型却完全不同。只有类型编码为<span>2</span>、<span>1</span>、<span>3</span>、<span>9</span>和<span>B</span>的描述符才是真正的系统段描述符，它们用于描述系统段<span>LDT</span>和任务状态段<span>TSS</span>，其它类型的描述符是门描述符。具体见下表：</span></p>
<p><img height=172 alt="" src="http://www.cppblog.com/images/cppblog_com/xingkongyun/t3.JPG" width=708 border=0></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>图3</span></p>
<p>&nbsp;</p>
<p><strong><span>**</span><span>LDT</span></strong><strong><span>段描述符</span></strong></p>
<p><span>LDT</span><span>段描述符描述任务的局部描述符表段。</span><span>LDT</span><span>段描述符必须安排在全局描述符表中才有效。在装载</span><span>LDTR</span><span>寄存器时，描述符中的</span><span>LDT</span><span>段基地址和段界限等信息被装入</span><span>LDT</span><span>段描述符高速缓冲寄存器中。</span></p>
<p>&nbsp;</p>
<p><strong><span>**.</span></strong><strong><span>任务状态段描述符</span></strong></p>
<p><span>任务状态段</span><span>TSS</span><span>用于保存任务的各种状态信息。任务状态段描述符描述某个任务状态段</span><span>TSS</span><span>描述符分为</span><span>286TSS</span><span>和</span><span>386TSS</span><span>两类。</span><span>TSS</span><span>描述符规定了任务状态段的基地址和任务状态段的大小等信息。在装载任务状态段寄存器</span><span>TR</span><span>时，描述符中的段基地址和段界限等信息被装入到</span><span>TR</span><span>的高速缓冲寄存器中。在任务切换或执行</span><span>LTR</span><span>指令时，要装载</span><span>TR</span><span>寄存器。</span></p>
<p>&nbsp;</p>
<p><span>参考：</span></p>
<p><span>《<span>80X86</span>汇编语言程序设计教程》清华大学出版社<span>&nbsp;</span>扬季文主编</span></p>
<p><span>《自己动手编写操作系统》</span><span> </span><span>于渊著</span><span><br clear=all></span></p>
<table cellSpacing=0 cellPadding=0 width="100%" align=left border=0>
    <tbody>
        <tr>
            <td>
            <p align=center>&nbsp;</p>
            </td>
            <td>
            <p align=center>&nbsp;</p>
            </td>
            <td>
            <p align=center>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/xingkongyun/aggbug/62743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xingkongyun/" target="_blank">杨彬彬</a> 2008-09-25 10:09 <a href="http://www.cppblog.com/xingkongyun/articles/62743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>