操作系统真相还原第四章-------进入保护模式

进入保护模式主要有三个步骤:
1.打开a20地址使能:
in al,0x92
or al,0000_0010B
out 0x92,al
2.构建GDT表,初始化出代码段、数据段、栈段的段描述符,确定各个段的起始地址,段的大小,以及访问权限等信息。
GDT表的第一项初始化为全0.
3.使能creg0的第0位
mov eax,cr0
or eax,0x00000001
mov cr0,eax

整个代码如下所示:
boot.inc

LOADER_BASE_ADDR equ 0x900
LOADER_START_SECTOR equ 0x2
;一一一一一一- gdt 描述符属性 一一一一一一-

G_4k equ 1_00000000000000000000000b
D_32 equ 1_0000000000000000000000b
L equ 0000000000000000000000b
AVL equ 000000000000000000000b
LIMIT_DATA equ 1111_0000000000000000b
LIMIT_CODE equ LIMIT_DATA
LIMIT_VIDIO equ 0000_0000000000000000b
P equ 1_000000000000000b ;当时这个位置成了0,导致发生错误,不能打开32位地址
DPL_USR equ 11_0000000000000b
DRL_OS equ 00_0000000000000b
S equ 1_000000000000b
TYPE_CODE equ 1000_00000000b
TYPE_DATA equ 0010_00000000b

;代码段高32位段描述符
CODE_HIGH4 equ (0x00<<24)+G_4k+D_32+L+AVL+LIMIT_CODE+P+DRL_OS+S+TYPE_CODE+0x00
;数据段高32位段描述符
DATA_HIGH4 equ (0x00<<24)+G_4k+D_32+L+AVL+LIMIT_DATA+P+DRL_OS+S+TYPE_DATA+0x00
;显存段高32位段描述符
VIDIO_HIGH4 equ (0x00<<24)+G_4k+D_32+L+AVL+LIMIT_VIDIO+P+DRL_OS+S+TYPE_DATA+0x0B

;一-一一一一一- 选择子属性一一一一一一一-
RPL0 equ 00b
RPL1 equ 01b
RPL2 equ 10b
RPL3 equ 11b
TI_GDT equ 000b
TI_LDT equ 100b

load.S内容:
%include “boot.inc”
section loader vstart=LOADER_BASE_ADDR
LOADER_STACK_TOP equ LOADER_BASE_ADDR
jmp start

GDT_START: dd 0x00000000
dd 0x00000000

CODE_DESC: dd 0x0000FFFF
dd CODE_HIGH4
STACK_DATA_DESC: dd 0x0000FFFF
dd DATA_HIGH4
VIDIO_DESC: dd 0x80000007
dd VIDIO_HIGH4

GDT_SIZE equ $-GDT_START
GDT_LIMIT equ GDT_SIZE-1
times 60 dq 0

;段选择子创建
SELECT_CODE equ (0x0001<<3)+TI_GDT+RPL0
SELECT_DATA equ (0x0002<<3)+TI_GDT+RPL0
SELECT_VIDIO equ (0x0003<<3)+TI_GDT+RPL0

gdt_ptr dw GDT_LIMIT
dd GDT_START

start:

in al,0x92
or al,0000_0010B
out 0x92,al

lgdt [gdt_ptr]

mov eax,cr0
or eax,0x00000001
mov cr0,eax

jmp dword SELECT_CODE:mode_start ;注意此处dword
[bits 32] ;此处提示编译按照32位程序编译
mode_start:
mov ax,SELECT_DATA
mov ds,ax
mov es,ax
mov ss,ax
mov esp,LOADER_STACK_TOP
mov ax,SELECT_VIDIO
mov gs,ax

mov byte [gs:160],‘P’
jmp $

将上面程序的P位更改过后发现屏幕没有显示P字符
在这里插入图片描述
说明显存的程序有问题,没有写到显存中。
在这里插入图片描述
发现显存段的起始地址是0x00008000,而不是0x000b8000,所以查出是显存段的段描述符出了问题,更改
;显存段高32位段描述符
VIDIO_HIGH4 equ (0x00<<24)+G_4k+D_32+L+AVL+LIMIT_VIDIO+P+DRL_OS+S+TYPE_DATA+0x00

;显存段高32位段描述符
VIDIO_HIGH4 equ (0x00<<24)+G_4k+D_32+L+AVL+LIMIT_VIDIO+P+DRL_OS+S+TYPE_DATA+0x0B
之后就可以显示
当上面的P为0时,运行时会出错,如图
在这里插入图片描述
因为P位是指示内存是否在内存中,当置成0时,会产生缺页中断,导致程序出错,因为此时还没有处理缺页问题。更改后可以解决。

此外,更改mbr.S中读入扇区为4,
mov cx,4 ;cx保存加载几个扇区(从eax开始)

此时要注意,在将load.bin写入硬盘中的时候注意:
指令为:dd if=/boch/load.bin of=/boch/hd60M.img bs=512 count=4 seek=2 conv=notrunc
在这里插入图片描述
在这里插入图片描述

在运行boch时,输入c后,程序一直运行,此时输入ctrl+c,就会停下来,可以继续输入指令。进行上图的调试。

发布了24 篇原创文章 · 获赞 3 · 访问量 930

猜你喜欢

转载自blog.csdn.net/HIT_zhanmusi/article/details/102992017
今日推荐