X86CPU在段式管理下的地址形成机制_第1页
X86CPU在段式管理下的地址形成机制_第2页
X86CPU在段式管理下的地址形成机制_第3页
X86CPU在段式管理下的地址形成机制_第4页
X86CPU在段式管理下的地址形成机制_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、X86 CPU在段式管理下的地址形成机制以及BIOS初始化过程对这种机制的利用陈英豪中科院计算所2005-7-28我们对x86 cpu的多少年來的某些刻骨铭心的理解可能是不正确 的。这里之所以用了 “可能”一词,是因为下面的一些结论是建立在 我自己的实验和推测的基础Z上的,没有绝对的把握,但我基本上都 是以官方的手册或资料(出然还包括从网上收罗到的大堆高手们写 作的很有价值的但却很难找到出处的非官方资料)作为实验和推测的 根据,所以这些结论也绝不是臆想出来的,并且在很人程度丄具有说 服力。另外为了帮助理解,我对某些问题的相关基础知识都作了适出 的补充。下面切入正题。一、x86的地址翻译机制(知

2、识准备)由于历史原因,在存储管理上,80x86系列的所有cpu都支持段式 管理方式(分段方式),并且分段是地址翻译的必经阶段(后面提到 的分页是可选的)。我们把段式地址翻译Z前所使用的“段基址:偏 移量”的地址形式,也就是程序员使用的地址形式称为虚拟地址,很 显然虚拟地址是二维的。而虚拟地址经过段翻译后得到的地址称为线 性地址,这时的线性地址已经变成平坦的维的形式了。如果不分页, 这个线性地址就是实际的物理内存地址(简称物理地址)了。如果启 用分页机制,再由分页地址翻译机制将线性地址译成物理内存地址。最后形成的物理地址显然也是维的。整个地址翻译过程可以用下图来农示:段地址翻译机制页地址翻译机制

3、物理地址4段地I址 稠线性地址 賀地址劇译或bypass图1地址翻译过程 二、关于神秘的A20 (知识准备)上面只提供了 个地址形成机制的理论框架。接下來我们來看看 单就实模式而言,由个虚拟地址得到相应的物理地址的具体过程是 怎样的。我们知道,8086 cpu比较单纯,cpu内部的段寄存器和其它 的寄存器宽度都是16位的,只有20根地址线(AbAQ ,并且没有什 么保护模式和分页一说。它的段翻译机制使用如卜方法将虚拟地址翻 译成线性地址:将16位的段寄存器的值左移4个二进制位(也就是 乘以16),再加上16位的偏移地址,形成一个20位的线性地址,由 于没有分页机制,所以形成的线性地址也就是实际

4、的物理内存地址 To但有个细节,我们不能忽略,那就是8086的20根地址线只能 访问IM (220)的地址空间,也就是0OOOOhFFFFFh。但8086的这 种地址翻译机制却很明显允许我们使用一个段地址是FFFFh偏移地 址也是FFFFh的虚拟地址:FFFFh : FFFFh。这个虚拟地址形成的物 理地址为FFFFOh + FFFFh = lOFFEFh,但这个地址已经超出了 1M(它 比1M多64K-16字节),由于地址宽度有限,截掉高位的进位,最后 形成的物理地址实际上是:OFFEFh,这种地址循环的地址翻译方式 我们称Z为wrap-aroundo也就是说,程序员访问100000hlOF

5、FEFh Z间的内存时,会被处理器H动wrap-around去访问00000hOFFEFh 的内存空间。这也是后来出现一根特殊的A20地址线的历史根源。80286出现以后,地址线增加到24根,可以访问到最大16MC224) 的物理内存空间,并且有了保护模式,情况变得复杂起Intel在设 计80286时提出的目标是,在实模式下,系统所农现的行为应该和 8086/8088所农现的完全一样,也就是说,在实模式下,80286以及 后续系列,应该和8086/8088完全兼容。但最终,80286芯片却存在 个BUG:如果程序员访问100000H-1 OFFEFH Z间的内存,系统将 实际访问这块内存,而不

6、是象过去一样重新从0开始。为了解决上述问题,IBM使用键盘控制器上剩余的些输出线来 管理第21根地址线(从0开始数是第20根,被称为A20 Gate)0如 果A20Gate被打开,则当程序员给出100000H-10FFEFH Z间的地址 的时候,系统将真正访问这块内存区域:$11M A20 Gate被禁止,则 当程序员给出100000H-10FFEFH Z间的地址的时候,系统仍然使用 8086/8088的方式。绝大多数IBM PC兼容机默认的A20 Gate是被禁 止的。由于在当时没有更好的方法來解决这个问题,所以IBM使用 了键盘控制器来操作A20 Gate,但这只是一种黑客行为,毕竞A20

7、 Gate和键盘操作没有任何关系。在许多新型PC上存在着一种通过芯 片來直接控制A20 Gate的BIOS功能。从性能上,这种方法比通过键 盘控制器来控制A20 Gate要稍微高一点。我们也不难发现,在实模式下即使打开了 A20,也只能访问到最 大1024K + 64K- 16Byte的地址空间。这是由其地址翻译机制的先犬 因索所决定的。这正好又给我们展示出个值得关注的地方。那就是: 在实模式F,由它的物理地址形成机制(段地址左移4位加偏移)最 多只需要21根地址线(原来的20根地址线再加上A20)就能解决寻 址问题,但保护模式下可以访问的空间要比这大得多,肯足还需要使 用A20以上的地址线,

8、但如果此时A20却关闭了,那会带來什么样 的后果呢?也就是说在进入保护模式时,不打开A20,会出现什么样 的情况呢?首先我们必须明白关闭A20和打开A20是什么样一个意思。所 谓关闭就是将A20恒置0,也就是通过地址翻译机制得到的物理地址 对该位不会有影响;所谓打开就是允许按实际的地址翻译机制得到的 物理地址去设置该位。对于关闭A20的情况,我们只要仔细分析 下地址字,将其第21位恒置0,于是可以得到地址线宽度所决定的 地址空间范围内任意的奇数兆段的地址,如IM (OOOOOhFFFFFh), 3M (200000h2FFFFFh), 5M (400000h4FFFFFh),但却得不到偶 数兆

9、段的地址。所以我们进保护模式Z前都要习惯性的开启A20, A20的相关电路虽然不是在CPU内部,但与CPU关系密切,所以就 多说了儿句。三. x86处理器在保护模式下的地址翻译(这里主要阐述分段部分的 翻译过程,并且主要是为了引入shadow register,为下面的文章作铺 垫)(知识准备)由于80286只是个过渡产品,生存时间也很短,不具有很强的 代农性,不作为重点讲述,我将兎点放在386及其以后的32位处理 器(统称为80x86或X86)的寻址上。32位的x86处理机有了实模式, 保护模式和V86模式等三种工作模式,由于启动部分不涉及V86模 式,所以对该部分也不作重点讲述。另外在这里

10、我不详细阐述X86的 整个存储系统支持,相关的内容可以在手册上和其它的些书籍上找 到。我们來看32位保护模式的寻址机制。为了以最小的篇幅介绍相 关的知识点并尽早切入觅点问题,我先给出一幅X86保护模式下的地 址翻译图:Paging部分(分页部分),其中Paging部分是可选的。Segmentation 部分是必须的,该部分的翻译过程如下:首先从指定的段寄存器中取 出选择了 (selector),然后根据selector屮的T1位确定是要检索GDT (全局描述符衣)还是LDT (局部描述符农)中的描述符,不妨假 设是要检索GDT屮的描述符,然后再根据GDTR寄存器所指示的GDT的基址以及sele

11、ctor中的index字段所指示的描述符的索引号在 GDT中找到相应的描述符,将描述符屮的特权级字段DPL与selector 的RPL字段进行比较,看是否有越权访问发生,另外还要检查虚拟 地址中的偏移量是否超过了描述符中的limit字段所定义的段长限, 这些检査都通过后,再将描述符中的段基址Base与虚拟地址中的偏 移量offset相加形成线性地址。为了便于理解,下面提供了 selector 和段描述符的格式:(5打2,1 °index| RPLTable Indicator10 = GDT1 =LDTRequested Privilege Level (RPL)图3 selecto

12、r格式第 7 byte 第 6 byte 第 5 byte 第 4 byte 第 3 byte 第 2 byte 第 1 byte 第 0 byteBase31.24AttributesSegment Base23.0Segment Limit15.011 r GD0A vLimitpDPLSTYPEAttributes中的数字1I1VL16 191213表示所占bil数图4段描述符格式上而只是理论上的情况,在实际的实现中对于每个段寄存器都增加了个相应的shadow register (称着段描述符高速缓冲寄存器或者彫了 寄存器),每个shadow register都用来存一个完整的描述符,这

13、个描 述符是与Z相关的那个段寄存器所装的selector所指示的描述符, shadow register的格式如卜:Base 32 bitLimit 32 bitAttr 12 bit图 5 shadow register 格式有了 shadow register,就只需要在将选择了载入段寄存器时到描述符 衣中读一次段描述符,并将其存入shadow register中,以后只要段寄 存器屮的选择了不改变,就再也不需要到描述符农中去索引描述符 了,而直接使用shadow register中的描述符形成线性地址,效率大大 提高。但还有个地方不是很明确,那就是intel似乎从來没有在手 册上说过sh

14、adow register的limit字段是32bit的。实际上,在描述符 屮的limit字段只有20bit,而是通过一个粒度字段G来说明每个单位 是lByte还是4K,从而达到指示IM limi(或4G limit的目的。那么 这个shadow register中的limit是不是也是20bit,然后由Attribute字 段中的粒度位來指示它的单位呢?也就是说shadow register中的字段 和描述符中的字段是不是完全一样呢?这还存在一些争议。不过我个 人认为,把shadow register的limit字段设讣成32bit更合理点,因 为在指令执行时需要用到limit的时候非常多,

15、如果每次都从shadow register中収出20位,然后再取出粒度位计算出一个32bit的limit, 这艶然在做高频率的匝复劳动,还不如直接把shadow register的limit 域设计成32bit,这样只需要在将描述符装入时计算一次,得到一个 32bit的limit,以后直接使用就行了。不过这可能会带來些兼容性 问题,例如在&4位处理器的情况卜,乂会怎么样呢?需要进一步的 分析和研究。四、x86 32位处理器对实模式地址形成机制的模拟(关键)这些shadow register对我们很觅要。这种重要性不单单來自效率 方面。如果情况真像我卜面所说的那样,那么我们不得不改变原来

16、所 固化在脑了里的很多对实模式地址翻译机制的理解。我们都知道在8086的实模式卜是将16位段地址左移4个二进制 位再加上16位偏移地址形成20位的物理地址。而80286及其后续产 品在保护模式下是这样形成物理地址的:理论上是通过虚拟地址中的 选择子索引到描述符农屮的描述符,再将描述符中的基地址加上虚拟 地址中的偏移量形成32位的线性地址(暂不考虑64位的情况),如 果不分页,这个线性地址就是物理地址了;实际情况是,直接使用 cpu内部的shadow register中的描述符而得到线性地址,而不是每次 都去访问内存中的描述符衣。那么现在的问题是,这种具有了保护模 式的cpu在实模式下是不是也按

17、照8086的方式來形成物理地址呢? 或是自己采用另外一套方案,只是模拟出8086的效果来呢?很多迹 象表明,它选择的是后者。其中一个最有力的证据就是可以在具有保护模式的x86 cpu (286 一般先不考虑)的实模式上,不使用任何内存扩展程序的前提卜可以 访问到4GE的物理内存空间,并且我已经亲手做成了这个实验。这 是怎么回事呢?难免让人糊涂。按理说如果保持向前完全兼容的话实 模式下是只能访问1M物理内存空间的,就算打开A20,也就再多加 64K-16Byte而已,所以说x86 cpu对8086在实模式卜的行为只是一 种模拟,而不是完全相同的。卜面我來谈谈这些具有保护模式的X86 cpu是怎样

18、模拟8086的实模式的。首先从我的实验说起。我事先构建了一个具有三个描述符的描述 符表GDT,其中第个是NULL描述符,这对x86 cpu來说是必须 的(至于原因我就不再这里多说了)。第二个是一个数据段描述符, 它的Base被设成0, limit被设成4GB。第三个是个代码段描述符, Base被设成准备在保护模式下执行的代码的入口点limit被设置成 64Ko因为我准备切换到保护模式,所以先打开A20,否则不能访问 到所有内存地址,这在前而有详细的阐述。当CR0中的保护模式允 许位被打开后,我用一个长跳转(该长跳转后面带的虚拟地址的选择 了指向上面所说的代码段描述符,虚拟地址中的偏移设置成0,

19、也就 是jmp far 16:0这样的形式,由于该描述符的Base被设置成准备在保 护模式下执行的代码的入口点,它再加上个虚拟地址中的偏移0, 其线性地址还是准备在保护模式卜执行的代码的入口点)正好跳到准 备在保护模式下执行的代码的入口点,最主要的是该长跳转将指定的 选择了更新到CS寄存器中,并将选择了指定的描述符更新到CS寄 存器的shadow register屮。这个隐藏在背后的更新shadow register的 动作我们吋刻都不能忘记,后面很多的内容都涉及到这点。然后在保护模式的代码中,我将上面的数据段描述符对应的选择 了载入了 DS, ES, FS, GS等寄存器,同样这个数据段描述

20、符就被 载入了上面那些段寄存器的shadow register中,也就是说这些段寄存 器都指向个4G段了。然后马上切换回实模式。另外,我们再留意 一个细节,其实如果在保护模式卜只干这么一点点事的话,我们完全 没有必要为CS再准备个描述符,也没有必要用长跳转去更新CS 寄存器以及其相关shadow register的内容,因为即使让CS保持着在 实模式下的值去执行保护模式的这一点点无关痛痒的代码也是不会 有问题的。因为如果更新了 CS的值,那么下次切换回实模式吋述得 先找回一个返回到实模式执行代码的返回点,这个返回点显然在切换 进保护模式Z前就应该保存起来。所以说,其实在保护模式下不改变 CS的

21、值会得到更精炼的代码,只不过别人看起來会有些晕。好,现在又回到了实模式。这时,让人吃惊的事情发生了,我居 然可以使用DS, ES, FS, GS这些段寄存器再加上一个32位的偏移 访问到4GB以内的任何物理内存。怪哉!怎么來解释这种现彖呢?用段地址左移4位加偏移肯定是不能 说明问题了,因为理论上在实模式下是根本不能使用32位偏移的, 并且如果不是我这通从实模式到保护模式,然后又从保护模式回实 模式的折腾,在平常一般的实模式的实际坏境卜也是的确访问不了超 过1M的内存的(当然开启A20可以多访问64K-16Byte,但仅此而 已)。问题还不明朗,等我再把实验往下进行一步。那就是在回实模式 后,觅

22、新把段寄存器加载次,如像下面这样更新DS寄存器:PUSH CSPOP DSZ后再使用DS加32位偏移去访问超过1M的内存就不能获得成功 To究竟是哪个东西有这么人的威力,显然仅仅通过改变DS寄存器 的值不至于会造成这么大的差別,只有一个东西具有这么大的神通, 那就是shadow registero每次更新段寄存器都会更新它,并口我们知 道,在保护模式下,自从更新完个段寄存器后,该段寄存器里的选 择子除了有一个RPL域用于特权检查外,其它情况下,该段寄存器 都只是个摆设,因为真正使用的是它的shadow register,因为里面 装着宝贵的描述符。难道实模式卞也是这样的情况吗?或许真是这 样,

23、因为只有这样我们才能够解释很多现象和问题,虽然我们从没有 听说过在实模式下还有什么段描述符。我用整套看起來还算合理的理论來解释这串现象。事实上我 们可以认为X86在保护模式和实模式下使用近乎相同的方式来形成 地址(当然抛开分页机制不谈,因为在实模式卜是不能分页的)。也 就是说,在实模式下也会使用shadow registero只不过它使用的方式 与保护模式不同:在保护模式卜更新一个段寄存器时,会有相应的段 描述符去更新相应的shadow register;而在实模式下更新个段寄存 器时,不会有相应的段描述符去更新相应的shadwo register,而是由 cpu按照固定的程序去更新相应的sh

24、adow registero这个I古I定的程序 是什么样的呢?至少下面的方式应该是合理的:比如说我们在实模式 卜给DS赋值FOOOh,那么cpu会将FOOOh送入DS寄存器,并将FOOOh 左移4个二进制位形成个32位的Base (高12位置0,低20位为 FOOOOh )放入DS的shadow register中的Base域,而limit域直接放 入FFFFh,以形成64k的段长限,属性域再填入相关内容(属性域应 该怎么填,还有待进一步研究)。当我们使用如下的方式去访问DS 段时:mov ax, word ptr ds:si ;假设 si 中的值是 FFFOh 那么cpu会-百接将DS对应的

25、shadow register中的Base域取出來再加 上si中指示的偏移FFFOh而形成物理地址FFFFOh,很显然由于在实 模式下没有各种特权检查,所以段寄存器本身更加像一个摆设了。又 有个需要考虑的细节,虽然在实模式下装载段时会口动给register shadow 一个64K的limit,但如果人为的使用一个超过64K的offset 会有什么后果呢?我的测试结果是直接导致死机。正是因为x86 cpu在实模式下有这样一种形成地址的机制(这显 然不同于8086在实模式下形成地址的机制,而只是一种对它的模 拟),所以就可以解释,为什么我们进入保护模式将段bre“k成4GB 后,冋到实模式卜还会

26、生效,因为那事实上是register shadow的内容 还保持着在保护模式下设置的值而在实模式下这些值继续被利用上 了而已。至于为什么段寄存器在实模式卜被重新加载了以后,又回到 T 64K的limit,那是因为register shadow又按照实模式的规则更新 了的缘故。另外,利用register shadow的这种地址形成功能,我们还 可以解释个令人困惑的地方。那就是我们切换进保护模式(将CRO 的PE位置1)之后,更新保护模式下的CS之前,可能还会有儿条指 令,但至少有条指令(那就是跳转到保护模式的代码段和偏移的那 条远跳转指令)按理说这条指令或几条指令应该按照保护模式的地 址形成机制

27、來运作了,也就是说此时的CS被当作一个选择子来索引 描述符了,但是此时的CS还是实模式下的CS,它显然不是个选 择子,假设它的值是FOOOh,如果把它的值当作一个选择子去描述符 农中找描述符,那结果显然是不堪设想的,而正是由于实模式和保护 模式在不更新段寄存器的值时都按register shadow形成地址这么个 游戏规则,才保证了这时仍按当前register shadow中的内容来寻址并 找到适出的指令执行这样个美好的结果。使实模式和保护模式顺利 交接。保护模式切换回实模式时,存在着类似的问题,也存在着同样 美妙的解决方案。五、X86 CPU在BIOS初始化过程中所处的状态以及BIOS对这种

28、状 态的利用(关键)有了前面这些分析作为基础,我们就可以来看看BIOS To这里 是CPU执行第条指令的地方。此时的处理器处在个什么样的状 态卞呢? BIOS又怎么样来利用和处理这些状态呢?下面我将一步一 步解开这些疑团。以下有些内容來口我在oldlinux论坛里的发帖, 我在那里的用户名是herochen,不过我在那些帖子中的阐述有一些不 正确Z处,在这里全都更正过来。众所周知,机器开始执行的第一条指令不是在内存nun里,而一 般是做在固件rom里,因为我们知道ram在断电后是会丢欠数据的。 关键是这块固件rom在统地址空间中如何编址。以前的8086年代, 由于使用实模式,地址不能超过1M,

29、所以将这块固件rom编址在1M 的最后64k,即它的段地址是OxFOOO,这样就不至于把RAM分成两 段。而一般有一个习惯,就是将机器执行的第一条指令放在FOOOh : FFFOh处,般彖下而这样安排BIOS启动代码:FOOO : 0000:FOOO : XXXX:FOOO : FFFO: jmp F000 : XXXX这样安排的好处是,让启动周件的地址尽可能靠后,事实上F000 : FFF0离实模式的极限地址F000 : FFFF只有16个字节了,也就安排 得开一个跳转指令和其他-些额外信息。而实际究竟需要使用多长的 启动代码苗jmp F000 : XXXX屮的偏移XXXX來把握,如果使用得

30、 多,XXXX就小,使用得少,XXXX就大,这样使启动代码尽量靠 后,而不浪费多余的地址空间,由于地址空间安排在最后,也不会把 整个地址空间隔离成两段。但出现80386 (更准确的说应该是80286)后,麻烦就来了,由 于80386的保护模式可以使用超过1M的地址空间,如果把冷启动固 件编址在FOOOh段内,就会把整个地址空间隔离成不连续的两段,一 段是FOOOh以前的地址,段是1M以后的地址,这很不方便。inlel 采用的办法是,还是默认将执行启动代码的BIOS ROM编址在系统 可寻址空间的最后(如32位X86机的话,这段地址就位于4GB的最 后-个64K内),在系统复位吋,CPU进入实模

31、式,并将CS寄存器 设置成FOOOh,而将它的shadow register的Base设置成FFFFOOOOh (理论上正常情况下CS为FOOOh的话,其shadow register的Base 应该设置成OOOFOOOOh,但intel有意识的将高12位触发成1 了,除 了这样他也没有什么好办法让机器启动就跑道4GB那么高的地址 上去执行),而偏移量EIP置成0OOOFFFOh,所以机器执行的第条 指令的周件安排的物理地址显然就变成了 FFFFFFFOho BIOS代码和 以前述是要兼容的,也就是说此吋从FFFFFFFOh处取岀的还是条 远跳转指令jmp F000 : XXXX (我跟踪调试

32、过好儿款BIOS,这里的 XXXX似乎都是E05B),问题随之而来。这个远跳转指令是要更新 CS寄存器和它的shadow register的,也就是说执行这条jmp F000 : E05B 也就是CPU执行第条指令Z后),CS将被更新成F000, 其实CS原来就是这个值,这里说不上是更新,但CS的shadow register 就不-样了,它被真正的更新了,它的Base域被更新成0OOFOOOOh 了(高12不再貝有触发成1的功能,那个功能只在机器启动到第- 次更新CS的内容期间有效)。这个Base再加上虚拟地址中的偏移量 E05B,得到物理地址000FE05Bh,这就是CPU执行的第二条指令

33、的 地址,但是这条指令的地址已经是1M以内了。但我们不要忘记,这 时的FOOOh段内可不再是BIOS ROM T ,这段此时安排的事实上 是我们的RAM空间,这一段RAM需不需要初始化才能使用那还另 说,关键是此时此刻这个地方不应该有可以执行的代码才对啊? CPU 第二条指令就跳到这里不是自寻死路吗?似乎走进了死胡同,但我翻阅了很多资料,找到了一点线索。在 很久以前岀现过个叫着Chips & Technologies的公司,他设计出 组被称着neat的芯片组,可以将内存高端的BIOS ROM映射到1M 以内的RAM空间里,并且可以使这段被映射的RAM空间具有与 ROM类似的只读属性。这

34、个公司后来被intel收购。但后来这种映射 似乎就成为了种标准。由于这种映射关系我们有理由相信,机器启 动的时候,4G的最后个64K里与1M的最后个64K里应该貝有 相同的东西,所以即使从FFFFFFFOh用一条jmp跳到OOOFEO5Bh, 也仍然能够找到正确的代码去执行。那么BIOS接下来要干一些什么事呢?它有很多事情要做,我只 举几件有代农性的,其中有两件事是DRAM的初始化和memory sizingo按理说这个时候CPU还处在实模式下,BIOS还没有办法去 确定超过1M的内存量。另外还有件事就是代码和数据拷贝,因为 映射到1M以内来的BIOS ROM容量有限,事实上还有很大一部分 没

35、有映射过来,以压缩的形式存放在高端的ROM屮了,BIOS在1M 以内执行初始化吋难免需更将高端的那些内容拷过來使用,这也是不 容易做到的。但不要忘了,我们可以使用前面说的将段break成4G的方法來做成这儿件事。当然,似乎还存在着这样种可能性,那就 是切换到保护模式,这些事悄就都町以做了,并且好像没有必要再切 换回实模式。情况没有想彖中那么简单,从我前面的那个实验看,我 切换到保护模式Z后只执行了儿行非常必要的将段break成4G的代 码,其他的事情律不做,因为保护模式下有非常严格的特权检杳, 并且需要设置GDT, IDT, LDT等一系列的农格,般的代码是不 容易在保护模式下跑起来的,所以想

36、在保护模式卜完成整个BIOS的 初始化,工程过于浩大,几乎等于写套小型的保护模式操作系统了 (FreeBios nJ'能就是这么干的)。当然我也有足够多的证据证明我们常用的BIOS都使用了这种 break limit的技术,并且它们完成break后都是迅速切换回实模式。 以下是几款BIOS的一些代码资料,我们可以窥见一斑。先来看AMI BIOSo网上可以找到关于AMI BIOS的部分源代码(但似乎不是很完整):j mp_si go_to_flat_modecheck_point_ini Od3h jmp u_cp_init u_cp_init_end: check_point_ini

37、0d4h;DS=ES=O (4GB limit),;GateA20 enabled=D3;init all chipset register=D4512 KB MEMORY TESTxorax,axmoves,axmovbx,es:word ptr |472h; save 40:72这段代码很简单,其中jmp_si是个宏,是将jmp的下条指 令的地址放入si,以备返回用(因为这时内存还没有初始化,还不能 使用堆栈,所以不便于用c“ll指令),再看看该语句后而的注释,基 木上U以认为go_to_flat_mode这段代码就是作break limit用的(遗 憾的是该段代码没有提供,所以只能猜测,

38、不过从上下文看,也是八 九不离十)。随后的check_point_ini是输出阶段码供调试用,(fl jmp u_cp_init是去做内存初始化和memory sizing女f,关键是看看最下 面三行,我们假设此时还是在保护模式卜没有回到实模式,那么最后 的三条指令就是将个NULL选择了载入ES寄存器,并且最后-条 语句是使用ES去访问内存单元,这毫无疑问是会出杲常的,因为 NULL selector是作占位用的,不能真正去使用它。所以我们据此一 点就可以断定,此时已经回到了实模式。再看AWORD BIOSo我没有得到AWORD BIOS的源代码,我 是用工具将其反汇编出来的。AWORD BI

39、OS里切换进保护模式的次 数很多,这正好从一个侧面反映了它每次切换进保护模式后乂回到了 实模式,我只举一处。代码中有这样一个子过程sub. 178:sub_178proc nearax,csmovmovds,axmovsi,4()B8hlgdlfword ptr si; Load global des tblmoveax.crO; Mov reg-control regor al JmovcrOeax; Mov reg-control regjmpshort loc_458db8Bh,0C0hloc_458:movax,10hmovds,axre tnsub._178endpsub.178过程

40、显然执行了从实模式切换进保护模式的动作,但似乎并没有从保护模式返回实模式,千万不要以为我们已经找到了疑点。止 我们看看程序对sub_178的调用:sub 180proc nearcallsub_178callsub_179sub_180 endp有call sub_178出现的地方,后面总会跟个call sub_179, sub_179又是何物呢?sub_179 proc nearmov eax, crO; Mov reg-control regand al, OFEhmov crO, eax; Mov reg-control regjmp far ptr loc_ret_459loc_ret

41、_459: sub_179 endp很显然sub. 179不干别的,就是切换回实模式。代码胜于雄辩。J再來看BOCHS的虚拟BIOSo BOCHS的BIOS的所有反汇编代 码中,用到CR0的地方仅仅4处,正好是前面两处用于切换到保护 模式,而后面两处用于切换回实模式:lgdt fword ptr es:si+8J ; Load global des tbllidt fword ptr cs:data_316 ; Load int des tablemov eax,crO; Mov reg-control regoral JmovcrO,eax;Mov reg-control reg;* Thi

42、s jump)is a protected mode jump to flush the pre-fetch queue -;* - the segment selector was ignored.jmpfar ptr loc_374Ioc_374:movax,28hmovss,axmovax,10hmovds,axmovax, 18hmoves,ax;*xor si,si;Zero registerdb31h,OF6h; Fixup byte match;*xordi,di;Zero registerdb31h,OFFh; Fixup - byte matchcld;Clear direc

43、tionrep movsw;Rep when ex >0 Mov si to es:dimovax,28hmovds.axmoves,axmoveax.crO;Mov reg-control regandal,OFEhmovcrO,eax;Mov reg-control regjmpfar ptr loc_375loc 375:licit fword ptr cs:data_317 ; Load int des table ;* xor ax,ax; Zero registerdb 31 h,OCOh; Fixup - byte matchmovds,ax非常的明了!还有Vmware的虚

44、拟BIOS,情况也都类似,我就不再觅复举例To到这里,我希望已经将一些基本的问题都讲清楚了,当然只是希 望而已。J文中可能还有很多的纽;漏,请大家多多批评指正!首先感谢herochen的宝贵资料正好我故近也在看这方面的东西,在台湾一个汇编语言论坛(他们称 为组合语言)上找到好多相关的资料,发帖者都是些BIOS和PC 硬件工程师,他们的说法应该很可靠。文章中所说的跟我查到的资料都很吻合,只是对其中这么段有点 点的看法:“似乎走进了死胡同,但我翻阅了很多资料,找到了一点线索。在很 久以前出现过一个叫着Chips & Technologies的公司,他设计出一组 被称着neat的芯片组,可以将内存高端的BIOS ROM映射到1M以 内的RAM空间里,并J1可以使这段被映射的RAM空间具有与 ROM类似的只读属性。这个公司后来被intel收购。但后来这种映射 似乎就成为了 种标准。由于这种映射关系我们有理由相信,机器 启动的时候,4G的最后一个64K里与1M的最J5个64K里应该具 有相同的东西,所以即使从FFFFFFFOh用条jmp跳到000FE05Bh, 也仍然能够找到正确的代码去执行。"“4G的最后个64K里与1M的最后-个64K里应该具有相同的东 西''这个思想肯定是没有问题的,否则无法继续执行BIOS里的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论