80x86保护模式(1)
2015-10-20 13:55
393 查看
在IA32模式下,CPU有两种工作模式:实模式和保护模式。实际上,当CPU加电时是工作在实模式下的,通过某种机制后才进入保护模式。在保护模式下,通过分段机制实现逻辑地址到线性地址的转换,通过分页机制实现线性地址到物理地址的转换。
![](http://img.blog.csdn.net/20151020141022829?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
具体是怎么转换的呢?
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
详解,包你理解透彻》。
以下,为具体的调用模式。
![](http://img.blog.csdn.net/20151020145515633)
当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,可以生成可在dos环境下运行的com文件。从bochs官网下载freedos映像文件,用WinImage工具将boot.com文件加入freedos.img 映像文件中,在bochs中运行freedos,执行boot.com命令。结果如下:
![](http://img.blog.csdn.net/20151020171731361)
参考 《自己动手写操作系统》 于渊
具体是怎么转换的呢?
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命令。结果如下:
参考 《自己动手写操作系统》 于渊
相关文章推荐
- Android Drawable 那些不为人知的高效用法
- Leetcode Unique Paths II
- BZOJ 1006 [HNOI2008]神奇的国度 弦图的最小染色
- java动态代理(JDK和cglib)
- decorView和window之间的层级及关系
- ls --color的使用
- 结构型模式之四——外观模式
- php解决key没有双引号的问题
- 观察变量值修改的位置
- 硬币问题(贪心)
- GRUB- "No suitable mode found"
- handsontable-chosen-editor
- JS日期时间类型(Y-m-d H:i:s)与时间戳互转
- Request的getParameter和getAttribute方法的区别
- 如何修改MFC的图标
- MDK Executing a function or an interrupt handler in RAM
- Window窗口布局 --- DecorView浅析
- 你应该知道的 RPC 原理
- 网址
- 接口类与抽象类的区别