关于X86混合16位32位汇编编码的问题.

发布于 2022-09-10 07:03:08 字数 658 浏览 13 评论 9

本帖最后由 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

等风来 2022-09-19 16:54:31

回复 3# feqin

    指令是有流水线的.
第五条指令的取操作数阶段是紧接着第四条指令的取操作数阶段的,第四条指令此时还在译码阶段,也就是说还没有被执行,cpu还在实模式.而当第五条指令执行时,即cpu到保护模式下了,这时第五条指令已经进入译码阶段了,要跳转的地址当然已经取回来了.正好一条跳转,把在l1 cache中的可能预取到的仍然在实模式下寻址到的指令数据等全部清掉.这样的设计,不需要硬件多的电路,只需要软件做一点点工作就行了.很完美的设计啊.

心碎无痕… 2022-09-19 16:54:05

回复  PCliangtao

    你这这种验证方法不队 你的SS还是实模式下的值
lgj1107 发表于 2010-10-24 23:16

      你有没有看在讨论什么问题啊?

旧情别恋 2022-09-19 16:51:02

回复 7# PCliangtao

    你这这种验证方法不队 你的SS还是实模式下的值

慵挽 2022-09-19 16:39:13

LS这位为何把教课书搬出来... 教科书里的东西不足以作为佐证...
    上次按照自己的理解回了这个帖子... 并没有实验一下...
    LS说是因为预取指令. 那我可以在进入保护模式之后...随便执行无用的指令...然后跳转继续执行这个序列指令。 如果正常指令... 可以说是与预取指令无关了吧...

  1. #say goodbye to the real mode...
  2.                 movw                $0x0001, %ax
  3.                 lmsw                %ax
  4.                 jmp                flush_instr    /* 这样能够刷新预取指令队列吧? */
  5. flush_instr:
  6.                 pushl                %eax
  7.                 pushl                %ebx
  8.                 pushl                %ecx
  9.                 pushl                %edx
  10.                 popl                %edx
  11.                 popl                %ecx
  12.                 popl                %ebx
  13.                 popl                %eax
  14.                 jmp                flush_instr

复制代码在bochs下执行... 死循环... 我在回贴中已经提到intel涉及所谓的影子寄存器是干什么的.
即使在实模式下.这个影子寄存器肯定也是会用到的.不然每次通过总线访问内存,都要把段寄存器的值左移四位么?

浮云落日 2022-09-19 15:56:20

哦~~这好像就是书里说的,这条段间转移指令在实模式下被预取,保护模式下呗执行

挽你眉间 2022-09-19 14:29:35

回复 3# feqin

     楼主的这个问题很有意思... 我以前写这个代码也只是按照说明来做... 只是觉得很奇怪而已...
     既然楼主翻阅Intel的文档都没有找到资料... 我也只能根据自己的理解以及逻辑推理来试着解释一下.
     首先需要提到的就是段寄存器中的非可能编程的所谓的影子寄存器。在实模式下这个影子寄存器应该也是可用的.只是不能对它编程。
    因为实模式的寻址方式是segff。这个当然与影子寄存器的值是无关的。假设这个影子寄存器中的基址应该是seg << 4,至于段长无法推测.
     如果需要起作用的话,至少是64KB。有了这个假设,从实模式到保护模式切换的那一刻一切都有很好的解释了.
     切换到保护模式.将机器状态字的最低比特位置1即可。这个指令执行之后,CPU就处于保护模式了。寻址方式也变为保护模式。
    这个时候要寻址下一条指令以及数据。寻址时就需要参考影子寄存器中的基地址。而这时候的基地址就是此时的seg << 4。外加偏移。
    当然就可以寻址下一条指令以及数据了。在重新装载CS的时候才会根据CS指定的GDT项的内容来重新装载影子寄存器。
    楼主可以试验一下...在进入保护模式之后.不改变CS的值... 看能否继续执行后续的保护模式下的指令.后续能够执行的指令长度应该是有限的...

人生百味 2022-09-19 03:04:17

{:3_183:}

睫毛溺水了 2022-09-15 21:57:48

回复 2# dibug

    你好像没有看明白我的意思,不过还是很感谢你回答我的问题..
    我写出的只是涉及16位和32位切换的交接处的4行代码,加载GDTR和关中断在第1行以前已经完成了..
既然第4行已经置位了PE位,那么从第5行开始(包括第5行)不就是进入保护模式了吗?保护模式的寻址不是要用段选择子吗??
我查了很多文档和代码,基本上置位PE之后接着的就是一条跳转指令,但是这条跳转指令的寻址方式是实模式的寻址方式..
所以我很困惑...
    intel文档里给出的16位和32位切换就是这个样子(置PE位,然后跳转)但是跳转指令的寻址是实模式,官方文档给出置位PE就进入了保护模式..
    我想intel的设计师不会用这么牵强的解决办法吧,可能是我在某一点上想错了..
    请各位知道的帮我解答一下,谢谢了..
    憋这么一个问题还真是寝食难安..

对不⑦ 2022-09-15 11:49:22

在完成实模式到保护模式转换之前,需要加载GDTR和关中断。
在第五条指令之前的CS的内容还是实模式下代码段的段值,而不是保护模式下的选择子,所以要用段间转移指令jmp。可以先定义一个宏,然后再运行这个宏指令

  1. _jmp macro sel,off
  2. db 0eah  ;jmp操作码
  3. dw off     ;16位偏移
  4. dw sel    ;选择子
  5. endm
  6. ...
  7. _jmp <sel>,<off>

复制代码

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文