《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.跳转,进入保护模式

你可能感兴趣的:(操作系统)