自己动手写操作系统学习笔记

来源:互联网 发布:深入浅出数据分析 编辑:程序博客网 时间:2024/05/18 18:15

;
;保护模式的学习
;
;
;


%include "pm.inc"
org 0100h
 jmp LABEL_BEGIN

[SECTION .gdt]

LABEL_GDT:      Descriptor 0,0,0;空描述符,GDT中,必须有一个空描述符
LABEL_DESC_CODE32:   Descriptor 0,SegCode32Len-1,DA_C+DA_32
LABEL_DESC_VIDEO:    Descriptor 0B8000h,0ffffh,DA_DRW

GdtLen equ $ - LABEL_GDT
GdtPtr dw GdtLen
       dd 0

SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT ;这个地方真的很精彩,描述符的长度是八个字节。
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT  ;而参看“选择子Selector”的格式,低三位是TI,RPL,高13位才是INDEX
       ;2^3刚好是8,这样,LABEL_DESC_CODE32 - LABEL_GDT得到的高十三位好就是
       ;LABEL_DESC_CODE32在GDT中的序号
       ;
       ;个人认为,选择子Selector的使用,就是为了让保护模式下的寻址和实模式下
       ;的寻址兼容。因为选择子的长度是16,我们还是能像在实模式下操作地址一样,
       ;只是在得到的地址实际上是保护模式下的地址。
       ;
       ;我想这也就是所谓的"对程序员编程来说,没有增加复杂性"的意义所在吧。


[SECTION .s16]
[BITS 16]
LABEL_BEGIN:
 mov ax,cs
 mov ds,ax
 mov es,ax
 mov ss,ax
 mov sp,0100h

 xor eax,eax    ;这个地方CS中的是段地址,再加上LABEL_SEG_CODE32这个偏移地址
 mov ax,cs    ;即实模式地址计算方法:CS*16+LABEL_SEG_CODE32
 shl eax,4    ;从而得到了LABEL_DESC_CODE32的物理地址
 add eax,LABEL_SEG_CODE32  ;并将其保存到LABEL_DESC_CODE32的描述符当中
 mov word [LABEL_DESC_CODE32+2],ax 
 shr eax,16    ;根据描述符的格式
 mov byte [LABEL_DESC_CODE32+4],al ;分别保存在第三,第四,第五和第八字节中
 mov byte [LABEL_DESC_CODE32+7],ah ;完成了对LABEL_DESC_CODE32描述符的初始化

 xor eax,eax    ;
 mov ax,ds    ;
 shl eax,4    ;将GDT的物理地址保存到GdtPtr的第三到第六字节中
 add eax,LABEL_GDT   ;为加载GDT到gdt寄存器中做准备
 mov dword [GdtPtr+2],eax  ;

 lgdt [GdtPtr]

 cli     ;关实模式的中断,因为保护模式下的中断方式和实模式下不同。

 in al,92h    ;只有打开A20的地址线,才能访问大于1MB的地址空间
 or al,00000010b    ;也有其它办法打开A20地址线,对端口92h操作是常用的方法
 out 92h,al    ;

 mov eax,cr0    ;cr0是80386CPU中的控制寄存器
 or eax,1    ;第0位,即PE位,用来控制是否进入保护模式(是/否:1/0)
 mov cr0,eax    ;

 jmp dword SelectorCode32:0  ;选择子是16位的,当然要用dword把它的属性定为32位的双字咯~

[SECTION .s32]
[BITS 32]

LABEL_SEG_CODE32:
 mov ax,SelectorVideo   ;将显示器的段地址传到GS寄存器
 mov gs,ax    ;

 mov edi,(80*10+0)*2   ;显存的偏移地址edi,决定了在显示器上显示的位置
 mov ah,0Ch    ;
 mov al,'P'    ;
 mov [gs:edi],ax    ;而物理地址[gs:edi]中的内容,则决定了显示的内容,AH为显示属性,AL为显示内容

 jmp $

SegCode32Len equ $ - LABEL_SEG_CODE32