进入保护模式
最近开始学习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