您的位置:首页 > 其它

80x86保护模式(1)

2015-10-20 13:55 393 查看
在IA32模式下,CPU有两种工作模式:实模式和保护模式。实际上,当CPU加电时是工作在实模式下的,通过某种机制后才进入保护模式。在保护模式下,通过分段机制实现逻辑地址到线性地址的转换,通过分页机制实现线性地址到物理地址的转换。



具体是怎么转换的呢?

1、在了解怎么转换之前,实模式下是怎么寻址的呢?

8086CPU是16位的CPU,拥有16位的寄存器,16位的数据总线,20位的地址总线,寻址空间仅仅为1M(2^20)。一个地址由段和偏移两部分构成,指令操作的直接为物理地址。

物理地址 = 16*段地址 + 偏移地址

80386时代,Intel进入32位的时代,CPU的寻址能力达到了4G,为了与以前兼容,实模式下访问方式类似于8086CPU,而在保护模式下则采用段业机制访问物理内存。

2、保护模式的分段机制

先了解几个概念Descriptor(描述符)、GDT(全局描述符表)、GDTR(全局描述符寄存器)、Selector(选择子)、LDT(局部描述符表)、LDTR(局部描述符寄存器),可以参考此文帮助理解《GDT,LDT,GDTR,LDTR
详解,包你理解透彻》。

以下,为具体的调用模式。



当selector的TI位为0时,表示段描述符在GDT中,过程为1-> 2 -> 3。

当selector的TI位为0时,表示段描述符的LDT中,过程为1' --> 2' --> 3' --> 4' --> 5'

实际上,分段机制采用的思想类似于C语言中的指针和数组访问的思想。TI=0时,GDTR给出GDT的地址,selector选择GDT中某个描述符的具体位置,描述符中记录的才是某个段的32位段地址。例如:jmp cs:offset,实际上是selector <== cs,具体访问的

物理地址 = selector对应描述符中的32位段地址 + offset

3、分页机制

分页机制的开启控制位为,cr0寄存器的PG位,以后详述分页机制。

4、编程实现实模式转入保护模式

;/*
;nasm boot.asm -o boot.com
;*/
;
; 描述符
; usage: Descriptor Base, Limit, Attr
;        Base:  dd
;        Limit: dd (low 20 bits available)
;        Attr:  dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3
dw	%2 & 0FFFFh				; 段界限1
dw	%1 & 0FFFFh				; 段基址1
db	(%1 >> 16) & 0FFh			; 段基址2
dw	((%2 >> 8) & 0F00h) | (%3 & 0F0FFh)	; 属性1 + 段界限2 + 属性2
db	(%1 >> 24) & 0FFh			; 段基址3
%endmacro ; 共 8 字节
DA_DRW		EQU	92h	; 存在的可读写数据段属性值
DA_32		EQU	4000h	; 32 位段
DA_C		EQU	98h	; 存在的只执行代码段属性值

org 0x0100
jmp 	LABEL_BEGIN
[section .gdt]
;GDT									段基址,      段界限,     段属性
LABEL_GDT_NULL:				Descriptor 		  0,		    0,		0	;空描述符
LABEL_CODE_DESC:			Descriptor		  0,	Code32Len,		DA_C + DA_32	;非一致代码段
LABEL_VEDIO_DESC:			Descriptor	0B8000H,       0FFFFH,	     DA_DRW;显存
;GDT end
Gdtlen						equ 			$ - LABEL_GDT_NULL
Gdtptr						dw				Gdtlen; GDTR段界限
dd				0		;GDTR段基址
;GDT选择子
SelectorCode32				equ				LABEL_CODE_DESC - LABEL_GDT_NULL
SelectorVedio				equ				LABEL_VEDIO_DESC - LABEL_GDT_NULL

;end section .gdt

[section .code16]
[BITS 16]
LABEL_BEGIN:
mov ax,	cs
mov es, ax
mov ds, ax
mov ss, ax
mov sp, 0100h

;初始化32位代码段描述符
xor	eax, eax
mov ax, cs
shl eax, 4
add eax, LABEL_CODE32
mov word [LABEL_CODE_DESC + 2], ax
shr	eax, 16
mov	byte [LABEL_CODE_DESC + 4], al
mov byte [LABEL_CODE_DESC + 7], ah
;为加载GDTR做准备
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT_NULL
mov dword[Gdtptr + 2], eax
;加载gdtr
lgdt [Gdtptr]
;关中断
cli
;a20地址线打开
in al, 92h
or al, 00000010b
out 92h, al
;切换保护模式 准备
mov eax, cr0
or	eax, 1
mov	cr0, eax

;跳转到保护模式
jmp	dword SelectorCode32:0

; end of section .code16

[section .code32]
[BITS 32]
LABEL_CODE32:
mov	ax, SelectorVedio
mov	gs, ax

xor ecx, ecx
mov cx, 20
print:
mov edi, (80*11 +10) ; 11行,10~30列,每个位置两个字节,打印20个‘P’
add edi, ecx
add edi, edi
mov ah, 0ch
mov	al, 'P'
mov [gs:edi], ax
dec ecx
jnz print

jmp	$

Code32Len		equ 		$ - LABEL_CODE32
;end of .code32


命令nasm boot.asm -o boot.com,可以生成可在dos环境下运行的com文件。从bochs官网下载freedos映像文件,用WinImage工具将boot.com文件加入freedos.img 映像文件中,在bochs中运行freedos,执行boot.com命令。结果如下:



参考 《自己动手写操作系统》 于渊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: