386实模式转保护模式那点事(1)

来源:互联网 发布:263视频会议登录软件 编辑:程序博客网 时间:2024/05/22 11:41
最近突然心血来潮,恶补了一点x86保护模式编程的知识,遇到一个颇为令人费解的问题。别的暂不说,我们先看大屏幕:

   MOV EAX, CR0
    OR   EAX, 1
   MOV CR0, AX   ;设置保护启用位
    JMP    Flush      ;清指令预取队列
Flush:
    JMP   far ptr Start32  ;通过GDT跳转到32位OS代码

早在386时代,使用 MOV CR0, EAX 将PE置位后,后面必须跟一个近跳转指令(通常是JMP$+2),这个是白纸黑字的写在Intel的80386手册上的 --也就是说,不做跳转,后续指令是不能保证被正确执行的。为毛?很多代码或资料上都写:我们需要清除预取队列,因为实模式和保护模式的指令译码不同,如果不这么做,CPU很生气,后果很严重;葛优在这么用,几百万人都在这么用,反社会的人木有好下场。。。

可是,可但是,这个地方实在太令人迷惑了。很多童鞋不禁要问:尼玛这个 JMP难道不也是实模式预取的吗,为毛丫可以正确执行啊。。。是不是有后门内定的。。。

外事问过股沟内事问过度娘,几番翻箱倒柜之后,发现事情的内幕是这样滴:原来只是有些实模式预取*并译码*的指令在*386*保护模式下无法正确的执行,这些指令包括特权指令如 LTR和段加载指令 LDS 等等。大多数P民级别的指令如 JMP近跳转,怎么改朝换代也改变不了自己屌丝的命运,该当牛当牛,该当马当马,两种模式下执行效果是一样一样的。所以,理论上只要让这些体型娇贵无法快速适应环境改变的指令离PE置位指令足够远,整个代码还是和谐滴,流程还是可以正常执行滴,直到有朝一日你想跳槽到32位代码段了,才需要用长跳转更新CS。另外就是,Intel自己也知道这个规定太过诡异太反人类,586以后的U就把这个限制去掉鸟。。。

原创粉丝点击