进入保护模式

Published: by Creative Commons Licence

最近开始学习kernel,所以从最基础开始,由实模式进入保护模式。

进入保护模式之前要打开A20Gate,还要设置cr0寄存器,可以用下面代码设置:

in	al,0x92
or	al,00000010b
out	0x92,al
mov	eax,cr0
or	eax,1
mov	cr0,eax

当然在进入保护模式之前要cli,关掉中断,因为保护模式下还没有设置我们自己的中断处理

以下是进入中断时遇到的问题:

在远跳转进入32位代码时失败,发现是下面两个原因

1.代码段的段选择符忘记设置P位(present,表示段是否在内存中)
2.vstart表示的是一个section的开始虚拟地址,我是在section code设置vstart,而section gdt并没有设置vstart,所以使用的是相对文件开头的位置,后面换成org就可以了。(org全局生效,只能用一次,vstart只在单独的section内生效)

代码:

%include "boot.inc"
org	LOADER_BASE_ADDR
[section code]
[bits 16]
	mov	ax,cs
	mov	ds,ax
	mov	es,ax
	mov	ss,ax
	mov	sp,LOADER_BASE_ADDR

	lgdt [GDT_PTR]
	cli
	in	al,0x92
	or	al,00000010b
	out	0x92,al
	mov	eax,cr0
	or	eax,1
	mov	cr0,eax
	jmp dword SelectorCode:Code32

[bits 32]
Code32:
	mov	ax,SelectorData
	mov	ds,ax
	mov	ax,SelectorVideo
	mov	gs,ax
	mov	edi,0xa0
	mov	ah,0xc
	mov	esi,msg
print_text:
	mov	al,[esi]
	inc	esi
	mov	[gs:edi],ax
	add	edi,2
	test	al,al
	jnz	print_text
	jmp $

[section gdt]
;gdt						base,	limit,		attribut
GDT		:Seg_Desc		0,		0,			0
CODE_DESC	:Seg_Desc		0,		0xfffff,	DA_C+DA_32+LIMITE_32+PRESENT
DATA_DESC	:Seg_Desc		0,		0xfffff,	DA_DRW+LIMITE_32+PRESENT
VIDEO_DESC	:Seg_Desc		0xb8000,	0xffff,		DA_DRW+PRESENT
;gdt end
GDT_LEN		equ $-GDT
GDT_PTR		dw	GDT_LEN-1
			dd	GDT
SelectorCode	equ CODE_DESC-GDT
SelectorData	equ DATA_DESC-GDT
SelectorVideo	equ VIDEO_DESC-GDT
msg db "Now we are in protected mode",0

   run_time