一个操作系统的实现:关于保护模式和实模式的跳转和段描述符高速缓冲寄存器

     依旧是第三章,看的好慢哦,其实从实模式跳转到保护模式还是很好懂得,主要注意就是跳转指令

jmp dword SelectorCode32:0  
//而不能是
jmp SelectorCode32:0



     因为这时编译出来的是16位代码。如果目标地址的偏移不是0,而是一个较大的值,比如

jmp SelectorCode32:0x12345678  



则编译后偏移会被截断,只剩下0x5678。

     所以,这个特殊的跳转需要特殊的处理。在Linux内核中(Linux使用的是AT&T汇编,不是一般常见的IBMPC汇编),这个跳转是用DB指令直接写二进制代码的方法实现的,而NASM显然提供了更好的解决方法,就是加一个dword,本来dword应该加在偏移之前,但NASM允许加在整个地址之前,就像我们之前做的那样,这也是NASM的优点吧。总之 一个程序中可以包含多个不同位的段,32位或者16位,他们之间也可以互相跳转,只是32位段用的是32位寄存器,16位代码段用的是16位寄存器,如果要在16位段下使用32位寄存器,必须象高级语言中强制类型转换一样,显示的定义 dword。

     而从保护模式跳转回实模式则不是那么好理解了,至少我是这样认为的,因为在准备结束保护模式回到实模式之前,需要加载一个合适的描述符选择子到有关的段寄存器,以使对应段描述符高速缓冲寄存器 (见后面的解释)中含有合适的段界限和属性(这里正确的段界限显然是64K,即0ffffh,属性应该是DA_DRW,即90h可读写数据段),而且,不能从32位代码段返回实模式,只能从16位代码段中返回。这是因为无法实现从32位代码段返回时cs高速缓冲寄存器中的属性符合实模式的要求(实模式不能改变段属性)。

     在实模式下,段寄存器含有段值,为访问存储器形成物理地址时,处理器引用相应的某个段寄存器并将其值乘以16,形成20位的段基地址。在保护模式下,段寄 存器含有段选择子,如上所述,为了访问存储器形成线性地址时,处理器要使用选择子所指定的描述符中的基地址等信息。为了避免在每次存储器访问时,都要访问 描述符表而获得对应的段描述符,从80286开始每个段寄存器都配有一个高速缓冲寄存器,称之为段描述符高速缓冲寄存器 或描述符投影寄存器,对程序员而言 它是不可见的。每当把一个选择子装入到某个段寄存器时,处理器自动从描述符表中取出相应的描述符,把描述符中的信息保存到对应的高速缓冲寄存器中。此后对 该段访问时,处理器都使用对应高速缓冲寄存器中的描述符信息,而不用再从描述符表中取描述符。

     新增的Normal描述符,段界限64K,属性DA_DRW,在返回实模式之前把对应选择子SelectorNormal加载到ds、es和ss正好合适。

------------------------------------------------------------------------------------------------------

 

转载我博客文章郑重声明:技术性网站著名原创作者即可转载,商业性网站必须经过我的同意才能转载,否则追究责任——

pang123hui的博客:

博客园http://www.cnblogs.com/pang123hui/

CSDNhttp://blog.csdn.net/pang123hui/

原文地址:https://www.cnblogs.com/pang123hui/p/2309926.html