学习笔记:一个操作系统的实现--保护模式进阶

         上节初步认识了保护模式,这节继续顺着这本书的思路,完成保护模式到实模式的转换。

         与上节相比,在跳入保护模式之前,以下两行代码比较诡异:

            73  mov     [LABEL_GO_BACK_TO_REAL+3],ax

            74  mov     [SPValueInRealMode],sp

 

        然后增加了以下保护模式跳入实模式的代码(这里只贴出部分):

 

            144 LABEL_REAL_ENTRY:       ; 从保护模式跳回到实模就到了这里

                            mov ax, cs

                            mov ds, ax

                            mov es, ax

                            mov ss, ax

 

                            mov sp, [SPValueInRealMode]

 

                            in  al, 92h     ;`.

                            and al, 11111101b   ;关闭A20 地址线

                            out 92h, al     ;

 

                            sti         ; 开中断

 

                           mov ax, 4c00h   ;`.

                           int 21h     ;  回到DOS

                  ; END of [SECTION .s16]

 

 

                  ; 16 位代码段. 由32 位代码段跳入, 跳出后到实模式

           308 [SECTION.s16code]

                  ALIGN   32

                  [BITS   16]

                  LABEL_SEG_CODE16:

                         ; 跳回实模式:

                         mov ax, SelectorNormal

                         mov ds, ax

                         mov es, ax

                         mov fs, ax

                         mov gs, ax

                         mov ss, ax

 

                         mov eax, cr0

                         and al, 11111110b

                         mov cr0, eax

 

                LABEL_GO_BACK_TO_REAL:

                         jmp 0:LABEL_REAL_ENTRY  ; 段地址会在程序开始处被设置成正确的值

 

                Code16Len   equ $ - LABEL_SEG_CODE16

 

                ; END of [SECTION .s16code]

 

         由于在实模式下和保护模式下,都有自己的堆栈,因此在实模式->保护模式时,需要先保存SP(即代码74         mov     [SPValueInRealMode], sp),与之对应,在保护模式->实模式时,需要恢复SP的值(即代码150 mov sp, [SPValueInRealMode])。

         在保护模式->实模式前,需要加载一个合适的描述符选择子到有关段寄存器中,以使对应的段描述符高速缓冲寄存器(隐藏在段寄存器之后的寄存器)中含有合适的段界限和属性,因此,有了代码313  mov     ax, SelectorNormal)。需要注意的是,不能从32位代码段返回实模式,只能从16位代码段中返回。

        好了,只剩下代码73行 (mov       [LABEL_GO_BACK_TO_REAL+3], ax)和代码325行(jmp  0:LABEL_REAL_ENTRY)的问题了。看到这两行代码很莫名,认真看了作者的描述,我的理解如下:

        在运行程序前,代码已经编译为比特串。运行时,在CPU看来,它仅仅是存在内存中的比特。LABEL_GO_BACK_TO_REAL+3地址中存储的是jmp操作数的段地址,即取代了jmp  0:LABEL_REAL_ENTRY中的“0”。因此,执行代码73行   (mov       [LABEL_GO_BACK_TO_REAL+3], ax)后,其实是替代了jmp指令操作数的段地址。

    总结如下:

    实模式->保护模式:

(1)   暂存SP

(2)   初始化段描述符

(3)   加载GDTR,关中断

(4)   打开A20

(5)   置cr0位1,跳转入保护模式

 

    保护模式->实模式:

(1)   跳入16位代码段

(2)   设置段寄存器值,使其符合实模式规范

(3)   置cr0为0,跳转入实模式

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值