免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1113 | 回复: 0
打印 上一主题 下一主题

我的boot(2)---- 切换到保护模式 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-16 00:57 |只看该作者 |倒序浏览
本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net 
 
1.1  进入保护模式的主要步骤:
1.1.1  GDT表

GDT表是存储GDT描述符的数组,每一个描述符对应着一个段。GDT表中的第一项必须为全0。表项类型为结构体Descriptor,结构如下:

; usage: Descriptor Base, Limit, Attr

;    %1    Base:  dd

;    %2    Limit: dd (low 20 bits available)

;    %3    Attr:  dw (lower 4 bits of higher byte are always 0)

%macro Descriptor 3

   dw  %2 & 0FFFFh        ; 段界限 1    (2 字节)

   dw  %1 & 0FFFFh        ; 段基址 1    (2 字节)

   db  (%1 >> 16) & 0FFh  ; 段基址 2    (1 字节)

   dw  ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性 1 + 段界限 2 + 属性 2  (2 字节)

   db  (%1 >> 24) & 0FFh  ; 段基址 3    (1 字节)

%endmacro ; 共 8 字节

根据nasm编译器的规则,结构体定义以%macro开始,以%endmacro结束。结构体名为Descriptor,宏名后的3表示该结构体有三个成员变量。

GDT表的定义方式如下:

[SECTION .gdt]

; GDT                           Base Addr   Limit          Attrib

LABEL_DES_GDT:    Descriptor   0,          0,             0

LABEL_DES_CODE32: Descriptor   0,          Code32Len - 1,  DA_C + DA_32

LABEL_DES_VIDEO:  Descriptor   0B8000h,    0ffffh,         DA_DRW

; GDT end

这里可以看到给结构体赋值的方式,每一项对应结构体中的一个成员变量。以表项LABEL_DES_VIDEO为例,0B8000h对应%1,0ffffh对应%2,DA_DRW对应%3。

注意:表项LABEL_DES_CODE32保存的是我们要跳入的32位代码段的GDT表项,其中Base Addr是0,因为此时还不知道32为代码段的地址,在后面的16为代码段中才会设置它。


1.1.2  Gdtr

GdtLen  equ $ - LABEL_DES_GDT   ; Gdt Len

GdtPtr   dw  GdtLen - 1      ; Gdt Limit

         dd  0               ; Gdt Base Addr

GDT表的地址保存在寄存器Gdtr中,该地址首先通过上面的语句计算而得后存在变量GdtPtr中,之后才加载。GdtPtr低2字节保存GDT表长度,通过“$ - LABEL_DES_GDT”计算而得。GdtPtr高4字节保存GDT表基址,这里先置0,后面会存入地址。

 


1.1.3  Selector选择子

; Gdt Selector

SelectorCode32  equ LABEL_DES_CODE32 - LABEL_DES_GDT

SelectorVideo   equ LABEL_DES_VIDEO - LABEL_DES_GDT

 

选择子Selector中保存的是各段对应GDT表项相对地址,通过上面的语句计算而得。

 


1.1.4  16位段与32位段

[SECTION .s16]

[BITS 16]

……

[SECTION .s32]

[BITS 32]

……

由于本程序实现了有实模式到保护模式的跳转,所以需要在程序中定义两个代码段,一个是16位段;一个是32位段。


1.1.5  初始化32位代码段描述符

       ; Init 32 bits code segment descriptor

    xor eax, eax

    mov ax, cs

    shl eax, 4

    add eax, LABEL_CODE32

    mov word [LABEL_DES_CODE32 + 2], ax

    shr eax, 16

    mov byte [LABEL_DES_CODE32 + 4], al

    mov byte [LABEL_DES_CODE32 + 7], ah

 

首先要设置32为代码段对应GDT表项的基址。基址对应着表项中的第2、3、4、7,四个字节。


1.1.6  准备加载gdtr

    ; Prepare for loading gdtr

    xor eax, eax

    mov ax, cs

    shl eax, 4

    add eax, LABEL_DES_GDT

    mov dword [GdtPtr + 2], eax

这段代码用于设置变量GdtPtr,长度为2字节。


1.1.7  加载gdtr

    ; Load gdtr

    lgdt [GdtPtr]

此处加载gdtr寄存器,x86使用专门的指令lgdt实现gdtr寄存器的设置。


1.1.8  关闭中断

    ; close int

    Cli

由于实模式与保护模式下的中断模式不同,所以在实模式/保护模式转换时必须关闭中断。


1.1.9  打开A20

    ; open A20

    in al, 92h

    or al, 00000010b

    out 92h, al

80286及之前的cpu最大寻址空间为1M,超过1M的地址(也就是使用了A20之后的地址线),会开始从0重新计算,即使跳入保护空间,也无法使用超过1M的地址。

80386开始,增加了保护模式,寻址空间变为4G。为了与80286之前的cpu兼容,超过1M的地址平时是关闭的,只有打开A20后才能访问超过1M的地址。

上面只是打开A20的一种方式,但不是唯一的方式。


1.1.10           设置cr0的PE位

    ; open protected mode

    mov eax, cr0

    or  eax, 1

    mov cr0, eax

此处打开cr0的PE位,实际上就使能了保护模式,也就是说,“mov cr0, eax”这一句后,系统就运行于保护模式下了。但是,此时ics的值仍然是实模式下的值,我们需要把代码段的Selector选择子装入cs。


1.1.11           跳入保护模式

    ; jump into protected mode

    jmp dword SelectorCode32:0   

 

这个跳转是为了设置cs寄存器,其目的是选择子SelectorCode32对应的GDT描述符LABEL_DESC_CODE32对应的段首地址,即标号LABEL_    CODE32C处。

该句指令还在16位段中执行,而目标地址却是32位的,从这一点上看,他是混合16位于32位的代码。所以,jmp后的dword就必不可少了。如果没有dword,编译出来的只是16位代码。假设目标地址偏移量为0x12345678,执行jmp SelectorCode32:0x12345678,则等价于jmp SelectorCode32:0x5678。

Nasm编译器的好处之一就是可以通过jmp后添加dword,指定编译后为32位指令。

至此,我们真正跳入了保护模式。

 


1.1.12           显示字符

LABEL_CODE32:

    mov eax, SelectorVideo

    mov gs, eax

    mov edi, (80 * 6 + 6) * 2      ; Line: 6, Column: 6

    mov ah, 0Ch                         ; 0000: background(black)    1100: foreground(red)

    mov al, 'P'

    mov [gs:edi], ax

这是进入保护模式后执行的代码。SelectorVideo选择子对应着显存的基址,我们通过把‘P’放入显存,实现了字符‘P’的显示。

本文乃fireaxe原创,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,并注明原作者及原链接,严禁用于任何商业用途。
作者:fireaxe_hq@hotmail.com
博客:fireaxe.blog.chinaunix.net 
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP