|
本帖最后由 不点 于 2017-5-28 02:20 编辑
报告一个好消息,我似乎猜到了。
从“加载过程不稳定”这一现象,我努力地想,感觉这可能是“中断响应”之类的问题。比如说,数据传输过程中破坏了中断向量表,或者破坏了内存的代码或堆栈。
终于,突然意识到,mem64 没有执行 cli 指令。
在早期,32 位保护模式的代码只运行在 cli 的情况下,只有切换到实模式之后才执行 sti,一旦准备进入保护模式,就又要先执行一条 cli 了。
mem64 就是早期写成的,所以,无需执行 cli 指令(根据刚才的解释,保护模式代码的运行,就意味着 cli 早执行过了)。
然而后来,我们给保护模式开放了中断响应。进入保护模式之后,执行了 sti。就是说,保护模式的代码运行在 sti(允许响应硬件中断)的状态。
这下子,mem64 就“躺枪”了。
假如说 mem64 依旧只是使用 32 位保护模式,那就不用管 cli 和 sti 的问题,因为 32 位代码可以响应硬件中断,我们已经有了 32 位的硬件中断响应处理程序。
然而 mem64 要切换 cpu 模式,就是切换到 64 位模式,这就不能响应硬件中断了,因为我们没有编写 64 位的硬件中断处理程序。只要在 64 位代码执行期间发生硬件中断(比如时钟中断),程序必然要崩溃。因此,在进入 64 位模式之前,必须执行一条 cli 指令(禁止响应硬件中断)。
yaya 可以在 mem64 的开头放置一条 cli,然后在尾部的 ret 之前再放置一条 sti。
更好一点的做法是,在开头放置一条 pushfl(保存原有的中断标志),然后执行 cli(目的是让 64 位指令能够不受干扰地顺利执行),再在结尾的 ret 之前放置一条 popfl 指令,恢复原有的中断标志。
这样的话,程序的适应性就要好一些了:既能适用于早期的情况(32 位保护模式不具有中断响应的功能),也能适用于现在的情况(32 位保护模式能够响应硬件中断,比如键盘中断、时钟中断)。
|
|