问题描述
关于实模式与保护模式的基础可以参考《深入理解linux内核》,或相关博文。
1 | 1.实模式下的寻址方式 |
问题:
当打开cr0的PE位的瞬间,处理器进入保护模式,寻址方式改变。此时cs的值并没有改变,并且打开cr0瞬间处理器对cs的解释方式完全不一样,那么问题来了,如何确保在进入保护模式后下一条指令被顺利执行?
解决过程
你可能会想
- 1.是不是cs段寄存器的内容足够特别,使得无论此时采用实模式的寻址方式还是保护模式的寻址方式所解释出来的地址相等?然后你会发现其实这个cs目前值没有任何规律,完全不对头。
- 2.翻一翻x86指令集,发现x86规定,在cpu执行长跳转指令的时候才会自动改变cs寄存器的值。然后你会去找,是不是前后有哪些地方执行过长跳转指令?然后没找到。
- 3.然后没招的时候你还可能想是不是并不一定就是接着下一条指令执行呢?然后就真的按照当前cs段的值以实模式的方式计算一下下条指令会在那个地方,最后发现根本行不通。
** 图书馆、百度、Google齐上阵后发现**
问题答案
段寄存器后面都有隐藏的高速缓冲寄存器,当cs寄存器值被更新时,这个高速缓冲寄存器的值会根据当时的寻址方式更新,比如实模式下就是cs<<4后放入高速缓冲寄存器,等需要取指令的时候就直接取高速缓冲寄存器的值与eip相加即可,并不会真的再去cs段寄存器找这个值然后做像保护模式下的寻址方式那样推导。这样就解释了上面的情况,虽然寻址方式改变了,但是cs段寄存器的值没变,高速缓冲寄存器的值就不会变,基址仍然是实模式时的值,从而实际上计算出来的还是实模式的地址,保证了指令流的持续执行。内核在等到切换准备就绪的时候就会执行一个长跳转指令来刷新cs段寄存器的值,从而真的跳转导保护模式下了。
可以参考《x86汇编语言:从实模式到保护模式》,里面也做了相关描述。