关于X86混合16位32位汇编编码的问题.
本帖最后由 feqin 于 2010-10-21 00:35 编辑
程序如下所示. NASM汇编..
1 ;准备切换到保护模式
2 mov eax,cr0
3 or eax,1
4 mov cr0,eax ;真正进入保护模式
5 jmp dword SelectofCode32:0
程序本身是没有问题的..
基本所有资料的解释都是:"程序执行完第4行,然后一个长跳转进入32位保护模式.."
我的疑问是:当执行完第4行的时候程序应该已经是进入保护模式了,就是说接下来的取指令CS寄存器里边的内容就应该是以段选择子的形式来解释了..那么现在的问题是第5条指令是这样寻址的吗??
但是以我的分析,第5条指令寻址还是实模式时候的CS:IP..
我很疑惑,请知道的各位帮我解答.
万分感激..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
回复 3# feqin
指令是有流水线的.
第五条指令的取操作数阶段是紧接着第四条指令的取操作数阶段的,第四条指令此时还在译码阶段,也就是说还没有被执行,cpu还在实模式.而当第五条指令执行时,即cpu到保护模式下了,这时第五条指令已经进入译码阶段了,要跳转的地址当然已经取回来了.正好一条跳转,把在l1 cache中的可能预取到的仍然在实模式下寻址到的指令数据等全部清掉.这样的设计,不需要硬件多的电路,只需要软件做一点点工作就行了.很完美的设计啊.
你有没有看在讨论什么问题啊?
回复 7# PCliangtao
你这这种验证方法不队 你的SS还是实模式下的值
LS这位为何把教课书搬出来... 教科书里的东西不足以作为佐证...
上次按照自己的理解回了这个帖子... 并没有实验一下...
LS说是因为预取指令. 那我可以在进入保护模式之后...随便执行无用的指令...然后跳转继续执行这个序列指令。 如果正常指令... 可以说是与预取指令无关了吧...
复制代码在bochs下执行... 死循环... 我在回贴中已经提到intel涉及所谓的影子寄存器是干什么的.
即使在实模式下.这个影子寄存器肯定也是会用到的.不然每次通过总线访问内存,都要把段寄存器的值左移四位么?
哦~~这好像就是书里说的,这条段间转移指令在实模式下被预取,保护模式下呗执行
回复 3# feqin
楼主的这个问题很有意思... 我以前写这个代码也只是按照说明来做... 只是觉得很奇怪而已...
既然楼主翻阅Intel的文档都没有找到资料... 我也只能根据自己的理解以及逻辑推理来试着解释一下.
首先需要提到的就是段寄存器中的非可能编程的所谓的影子寄存器。在实模式下这个影子寄存器应该也是可用的.只是不能对它编程。
因为实模式的寻址方式是segff。这个当然与影子寄存器的值是无关的。假设这个影子寄存器中的基址应该是seg << 4,至于段长无法推测.
如果需要起作用的话,至少是64KB。有了这个假设,从实模式到保护模式切换的那一刻一切都有很好的解释了.
切换到保护模式.将机器状态字的最低比特位置1即可。这个指令执行之后,CPU就处于保护模式了。寻址方式也变为保护模式。
这个时候要寻址下一条指令以及数据。寻址时就需要参考影子寄存器中的基地址。而这时候的基地址就是此时的seg << 4。外加偏移。
当然就可以寻址下一条指令以及数据了。在重新装载CS的时候才会根据CS指定的GDT项的内容来重新装载影子寄存器。
楼主可以试验一下...在进入保护模式之后.不改变CS的值... 看能否继续执行后续的保护模式下的指令.后续能够执行的指令长度应该是有限的...
{:3_183:}
回复 2# dibug
你好像没有看明白我的意思,不过还是很感谢你回答我的问题..
我写出的只是涉及16位和32位切换的交接处的4行代码,加载GDTR和关中断在第1行以前已经完成了..
既然第4行已经置位了PE位,那么从第5行开始(包括第5行)不就是进入保护模式了吗?保护模式的寻址不是要用段选择子吗??
我查了很多文档和代码,基本上置位PE之后接着的就是一条跳转指令,但是这条跳转指令的寻址方式是实模式的寻址方式..
所以我很困惑...
intel文档里给出的16位和32位切换就是这个样子(置PE位,然后跳转)但是跳转指令的寻址是实模式,官方文档给出置位PE就进入了保护模式..
我想intel的设计师不会用这么牵强的解决办法吧,可能是我在某一点上想错了..
请各位知道的帮我解答一下,谢谢了..
憋这么一个问题还真是寝食难安..
在完成实模式到保护模式转换之前,需要加载GDTR和关中断。
在第五条指令之前的CS的内容还是实模式下代码段的段值,而不是保护模式下的选择子,所以要用段间转移指令jmp。可以先定义一个宏,然后再运行这个宏指令
复制代码