《Orange’s 一个操作系统的实现》3.保护模式2----认识保护模式A

1.前言

还是先来分析下保护模式的代码pmtest1.asm,要硬这头皮看这段代码,而且的搞明白了,后面的代码都是在此基础上扩展的,此代码是大致轮廓

2.代码分析

; ==========================================
; pmtest1.asm
; 编译方法:nasm pmtest1.asm -o pmtest1.bin
; ==========================================

%include	"pm.inc"	; 常量, 宏, 以及一些说明

org	07c00h                  ; 加载07c00h处cs=0000h,ip=07c00h(别人规定的)
	jmp	LABEL_BEGIN     ; 跳转到LABEL_BEGIN处

[SECTION .gdt]
; GDT
;                              段基址,       段界限     , 属性
LABEL_GDT:	   Descriptor       0,                0, 0           ; 空描述符     
LABEL_DESC_CODE32: Descriptor       0, SegCode32Len - 1, DA_C + DA_32; 非一致代码段 
LABEL_DESC_VIDEO:  Descriptor 0B8000h,           0ffffh, DA_DRW	     ; 显存首地址
; GDT 结束

GdtLen		equ	$ - LABEL_GDT	; GDT长度 
GdtPtr		dw	GdtLen - 1	; GDT界限
		dd	0		; GDT基地址

; GDT 选择子
SelectorCode32		equ	LABEL_DESC_CODE32	- LABEL_GDT  ;32位代码段选择子
SelectorVideo		equ	LABEL_DESC_VIDEO	- LABEL_GDT  ;显存选择子
; END of [SECTION .gdt]

[SECTION .s16] 
[BITS	16]
LABEL_BEGIN:
	mov	ax, cs 
	mov	ds, ax
	mov	es, ax
	mov	ss, ax     ;以上代码将当前的ds,es,ss全部指向cs代码段
	mov	sp, 0100h  ;sp设置为0100h

	; 初始化 32 位代码段描述符
	xor	eax, eax ;eax清0
	mov	ax, cs   ;存入cs   
	shl	eax, 4   ;左移4位,扩展为20位地址
	add	eax, LABEL_SEG_CODE32 ;在cs的基础上加上LABEL_SEG_CODE32的地址偏移(相对于0)
       
	mov	word [LABEL_DESC_CODE32 + 2], ax ;将ax中的16位段地址移入描述符LABEL_DESC_CODE32对应的2~3字节
	shr	eax, 16                          ;将eax的高16位移入低16位中
	mov	byte [LABEL_DESC_CODE32 + 4], al ;将al中的8位段地址移入描述符LABEL_DESC_CODE32对应的4字节中
	mov	byte [LABEL_DESC_CODE32 + 7], ah ;将ah中的8位段地址移入描述符LABEL_DESC_CODE32对应的7字节中

	; 为加载 GDTR 作准备
	xor	eax, eax ;eax清0
	mov	ax, ds   ;ds移入ax
	shl	eax, 4   ;扩展为20位
	add	eax, LABEL_GDT		; eax <- gdt 基地址 ds+gdt基地址
	mov	dword [GdtPtr + 2], eax	; [GdtPtr + 2] <- gdt 基地址    将gdt基地址移入GdtPtr中

	; 加载 GDTR
	lgdt	[GdtPtr];将GdtPtr中的GDT界限和GDT基地址加载到寄存器gdtr中

	; 关中断
	cli 

	; 打开地址线A20-----前面的段地址已经扩展位20位
	in	al, 92h 
	or	al, 00000010b
	out	92h, al

	; 准备切换到保护模式
	mov	eax, cr0 ;加载cr0到eax
	or	eax, 1   ;将cr0的PE置位1,打开保护模式
	mov	cr0, eax ;更改cr0

	; 真正进入保护模式
	jmp	dword SelectorCode32:0	; 执行这一句会把 SelectorCode32 装入 cs,
					; 并跳转到 Code32Selector:0  处  SelectorCode32中段基址指向LABEL_SEG_CODE32偏移为0
; END of [SECTION .s16]


[SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS	32]

LABEL_SEG_CODE32:
	mov	ax, SelectorVideo       
	mov	gs, ax			; 视频段选择子(目的)

	mov	edi, (80 * 11 + 79) * 2	; 屏幕第 11 行, 第 79 列。
	mov	ah, 0Ch			; 0000: 黑底    1100: 红字
	mov	al, 'P'
	mov	[gs:edi], ax

	; 到此停止
	jmp	$

SegCode32Len	equ	$ - LABEL_SEG_CODE32
; END of [SECTION .s32]
 

3.编译

   nasm pmtest1.asm –o pmtest1.bin

4.写入软盘

   dd if=pmtest1.bin of=a.img bs=512 count=1 conv=notrunc  

5. jmp dword SelectorCode32:0

    保护模式下SelectorCode选择子对应的描述符为LABEL_DESC_CODE32,而我们之前已经将描述符的段基址初始化为指向LABEL_SEG_CODE32,

    偏移为0,所以会跳转到LABEL_SEG_CODE32处执行.

6.进入保护模式的主要步骤

  a.准备GDT

  b.用lgdt加载gdtr

  c.打开A20

  d.置cr0的PE位

  e.跳转,进入保护模式

posted @ 2011-01-05 21:13  Aoysme  阅读(979)  评论(3编辑  收藏  举报