写操作系统(八)执着 进入保护模式

在前两次学习的基础上,这次试着解释一个简单的由实模式进入保护模式的代码,当然进入保护模式的方法不止这一种

看注释就可以了。

 

 

;; 文件:pmode.asm
;; 工具:UltraEdit14.12编辑,Nasm2.02汇编
;; 创建日期:2009/02/4 HouRj
;; 作用:由实模式进入保护模式的一种方法
;; 备注:没有文件系统,1.44M 512bits/80sec 软盘启动,
;; hourj_er@yahoo.cn
;;================================================
[bits 16]                 ;告诉编译器,编译成16位指令,前面代码缺省默认
[org 0x7c00]    
   cli                        ;关闭中断,保证引导程序在执行时不被打扰
   xor ax,ax             ;GDTR的地址是 DS:offset,这里对DS进行初始化,下面lgdt指令是对offset初始化
   mov ds,ax            ;GDT将被加载的地址,00h
  
   lgdt[gdt_desc]    ;加载GDT,将GDT的地址及其大小属性载入到GDT描述符中,即GDTR(48) = limit(16) + base(32)
   mov eax,cr0
   or eax,1             ;设置eax的第0位,
   mov cr0,eax        ;置pe位
   jmp 08h:clear_pipe   ;08h的算法:由于GDT第一个段是Intel保留的空段,而一个段64b的8B个区域,
                                   ;所以跳过空段(00h-07h),即08h
  
[BITS 32] 
clear_pipe:           ;这里由于要进入保护模式,所以要对DS,CS,ES,SS,FS,GS进行重新写
   mov ax,10h       ;10h的算法:第一段是空段(00h-07h)
   mov ds,ax         ;第二段是代码段(08-0fh),第三段是数据段(10h-17h)
   mov ss,ax         ;堆栈段与数据相同
   mov esp,090000h   ;
  
   ;由于在保护模式下不能直接使用BIOS中断,显示的方法是向显存的缓冲里直接写入
   ;显存位于:0xA0000---0xbffff,帧缓冲位于0xb8000处,我们将要向这里输入
   ;每个字符需要2个字节,第一个代表ASCII,第二个属性字节的不同位,代表不同属性
   ;0-3前景色,4-6背景色,7闪烁,
  mov byte [ds:0B8000h], 'M'      ; Move the ASCII-code of 'H' into first video memory
  mov byte [ds:0B8001h], 1ah      ; Assign a color code
  mov byte [ds:0B8002h], 'u' 
  mov byte [ds:0B8003h], 9bh
  mov byte [ds:0B8004h], 'm' 
  mov byte [ds:0B8005h], 1ch
  mov byte [ds:0B8006h], 'O' 
  mov byte [ds:0B8007h], 9dh
  mov byte [ds:0B8008h], 's' 
   mov byte [ds:0B8009h], 1eh
  
hang:
  jmp hang
 
gdt:                 ;填写GDT
gdt_null:         ;空段,Intel保留的区域,用零填充
  dd 0              ;共64位的0
  dd 0
 
gdt_code:         ;填写代码段的GDT,参照GDT的结构
  dw 0ffffh         ;填充limit(15-0),共16位1,偏移即寻址为
  dw 0               ;基地址为0
  db 0                ;十六位,低八位仍是基址,填0
  db 10011010b      ;高八位需要分别开一下,低到高:A,R/W,ED/C,E,S,DPL,P 它们分别为:
               ;A是访问标志,由CPU在第一次访问时设置,置0;
               ;R/W置为1使段可读;
               ;ED/C表示顺从性,如果设置位1,则表示低优先级的代码段可以跳转到或调用该段。此处置0,不需要此功能;
               ;E置为1,表示描述符描述的是代码段;E置为0,表示描述符描述的是数据段
               ;S表示该段是代码段或数据段,置为1;系统置0
               ;DPL表示优先级,由于是引导程序,所以要把优先级设为00;
               ;最后,P设置为1,段有有效的基址和界限。没有定义描述置0
  db 11001111b      ;这里的十六位,低八位分别:四位偏移,AV,0,D,G
              ;首先4位偏移量,设置为0Fh;
              ;AV为表示Available,AV=1表示segment is available,此处忽略该位,设为0;
              ;Intel保留了一位必须设为0;
              ;D表示大小位,置为1,它告诉CPU使用32位代码而不是16位代码;
              ;G表示粒度,如果G=0,则Limit所表示的段偏移是00000H-FFFFFH,
              ;如果G=1,则Limit表示的段偏移是00000XXXH-FFFFFXXXH,
              ;即Limit所表示的段偏移实际上是它的值再乘以4K。此处设置G=1。于是得到前8位:11001111
  db 0          ;高八位基址,全置0
 
gdt_data:         ;填写数据段GDT,同样参照GDT结构
  dw 0ffffh         ;这里只看跟代码段不通的位
  dw 0               ;相同
  db 0                ;相同
  db 10010010b      ;看低位第4位,这里是0,表示描述符描述的是数据段,上面代码段置的是1
  db 11001111b      ;相同
  db 0                      ;相同
gdt_end:                 ;由于在lgdt的时候需要把GDT的地址和大小加载到GDTR中,
                               ;本条指令GDT的结束,是为了计算GDT的大小

gdt_desc:               ;GDT的描述符,被lgdt加载到GDTR=基址+大小
  dw gdt_end-gdt-1    ;计算大小
  dd gdt                       ;基址
 
  times 510-($-$$) db 0
  dw 0aa55h
  
;;================================================

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值