OSLab:开启保护模式
日期:2019/5/22
关键词:操作系统;OS;保护模式;A20地址线激活;分页开启;二级页表的设置
PS:OSLAB实验课的整理。
本文主要内容是分析操作系统中一个简易的MBR。
建议先阅读:https://www.cnblogs.com/sinkinben/p/10888599.html
宏定义和数据定义
%define CR0_PE (1 << 0) %define CR0_MP (1 << 1) %define CR0_EM (1 << 2) %define CR0_TS (1 << 3) %define CR0_WP (1 << 16) %define CR0_PG (1 << 31) %define PTE_PRESENT (1 << 0) %define PTE_WRITE (1 << 1) %define OUTTER_PGTBL 0x1000 %define INNER_PGTBL 0x2000 gdt:dw 0,0,0,0 ; dummy dw 0xFFFF ; limit=4GB dw 0x0000 ; base address=0 dw 0x9A00 ; code read/exec dw 0x00CF ; granularity=4096,386 dw 0xFFFF ; limit=4GB dw 0x0000 ; base address=0 dw 0x9200 ; data read/write dw 0x00CF ; granularity=4096,386 gdt_desc: dw 23 ; gdt limit=sizeof(gdt) - 1 dw gdt dw 0xAA55 |
实模式:初始化
设置段寄存器。
org 0x7c00 [bits 16] ; First, BIOS loads the bootsector into 0000:7C00. cli xor ax, ax mov ds, ax mov ss, ax |
实模式:A20地址线激活
参考:https://wenku.baidu.com/view/d6efe68fcc22bcd126ff0c00.html
在8086/8088中,地址线20条(A0-A19),可寻址空间220bytes=1MB(可使用内存最大值)。但是寄存器是16位的(CPU可以"看到"216=64KB的内存),所以才引入了段寄存器,引入之后,寻址格式变为[ES:DI],计算方法是ES<<4+DI(这个值是20bit的)。
在这种情况下,CPU可以"看到"的内存的最大地址是:[0xFFFF: 0xFFFF] = 0x10FFEF = 1087 KB > 1024KB
本来是为了让CPU能看到完整的1MB内存,但是现在却多出了[1024, 1087]这个区间的地址,如果程序访问了这个区间的地址,CPU该如何处理?
答案是:当程序员给出超过1M(100000H-10FFEFH)的地址时,系统并不认为其访问越界而产生异常,而是自动从重新0开始计算。
即:存在映射:1024=>0, 1025=>1以此类推。
但是后来的80286,系统的地址总线发展为24根(A0-A23),这样能够访问的内存可以达到224=16M。
这样使得80286芯片却存在一个问题:如果程序员访问100000H-10FFEFH之间的内存,系统将实际访问这块内存,而不是重新从0开始。
这就导致一个问题:不能在80286上面运行8086/8088的程序。(不能向前兼容,当时80286性能再好也不会有人买)
为了解决这个问题,IBM使用键盘控制器上剩余的一些输出线来管理第21根地址线,即A20 Gate。
- 如果A20 Gate被打开,则当程序员给出100000H-10FFEFH之间的地址的时候,系统将真正访问这块内存区域;
- 如果A20 Gate被禁止,则当程序员给出100000H-10FFEFH之间的地址的时候,系统仍然使用8086/8088的方式。
从80286开始出现保护模式,那么A20 Gate就一定需要激活。
如果A20 Gate被禁止(不论给出的地址中A20是什么,CPU将A20看作0处理):
- 对于80286来说,其地址为24bit,其地址表示为EFFFFF;
- 对于80386极其随后的32-bit芯片来说,其地址表示为FFEFFFFF。
如果A20禁止,那么访问到的地址不是连续的。
A20地址线的激活是通过一个叫8042的芯片完成的,其编程方法和8259中断控制器类似,但是比8259简单得多。
主要步骤是:
- 禁止中断(cli)
- 等待输入缓冲(端口0x64)为空
- 把0xd1写入端口0x64(0xd1表示下面要准备写数据到输出端口P2,IBM-PC使用P2的位2即P21来控制A20地址线)
- 等待输入缓冲(端口0x64)为空
- 把0xdf写入端口0x60。0xdf = 11011111, P21所在bit为1。(0bit是P25)
汇编程序
; Enable A20 wait_8042_1: in al, 0x64 test al, 0x2 jnz wait_8042_1 mov al, 0xd1 out 0x64, al wait_8042_2: in al, 0x64 test al, 0x2 jnz wait_8042_2 mov al, 0xdf out 0x60, al |
实模式:保护模式开启
开启保护模式的主要工作有:
- 段寄存器初始化
- GDT的初始化
- CR0寄存器PE位的设置
参考https://www.cnblogs.com/sinkinben/p/10888599.html
开启保护模式代码
; Switch to protect mode lgdt [gdt_desc] mov eax, cr0 or eax, CR0_PE mov cr0, eax jmp 0x08:start32 [bits 32] start32: ; In protect mode cli mov ax, 0x10 mov ds, ax mov es, ax mov ss, ax mov esp, 0x10000 |
保护模式:开启分页
开启分页的主要工作:
- 二级页表初始化(包括PDE和PTE)
- 保存页表基地址(CR3)
- 设置CR0的PG位
PTE表项的格式
其中,31-12bit是该PTE项对应的物理页框号。
其实PDE表项的格式与之类似,32-12bit是PDE项对应的PTE表的基地址。
代码
; Initialize inner page table(页表) mov eax, PTE_WRITE|PTE_PRESENT ;PTE项的实际内容 mov edi, INNER_PGTBL ;PTE表在内存中的起始地址 cld init_pte: stosd ;eax => [edi] add eax, 4096 ;每个页面4KB大小,4096=1 0000 0000 0000 个PTE项 ; Initialize outter page table ,即PDE[i] = 0 xor eax, eax mov edi, OUTTER_PGTBL cld rep stosd 个PDE mov dword [OUTTER_PGTBL+0*4], INNER_PGTBL|PTE_WRITE|PTE_PRESENT ;PDE[0] -> PTE[0] mov dword [OUTTER_PGTBL+1*4], INNER_PGTBL|PTE_WRITE|PTE_PRESENT ;PDE[1] -> PTE[0] ; Load CR3 mov eax, OUTTER_PGTBL ;页目录基地址 mov cr3, eax ; Enable paging and write-protect mov eax, cr0 and eax, ~(CR0_EM|CR0_TS) ;把EM和TS位清零 mov cr0, eax |
保护模式:输出字符串
完整代码
%define CR0_PE (1 << 0) %define CR0_MP (1 << 1) %define CR0_EM (1 << 2) %define CR0_TS (1 << 3) %define CR0_WP (1 << 16) %define CR0_PG (1 << 31) %define PTE_PRESENT (1 << 0) %define PTE_WRITE (1 << 1) %define OUTTER_PGTBL 0x1000 %define INNER_PGTBL 0x2000 org 0x7c00 [bits 16] ; First, BIOS loads the bootsector into 0000:7C00. cli xor ax, ax mov ds, ax mov ss, ax ; Enable A20 wait_8042_1: in al, 0x64 test al, 0x2 jnz wait_8042_1 mov al, 0xd1 out 0x64, al wait_8042_2: in al, 0x64 test al, 0x2 jnz wait_8042_2 mov al, 0xdf out 0x60, al ; Switch to protect mode lgdt [gdt_desc] mov eax, cr0 or eax, CR0_PE mov cr0, eax jmp 0x08:start32 [bits 32] start32: ; In protect mode cli mov ax, 0x10 mov ds, ax mov es, ax mov ss, ax mov esp, 0x10000 ; Initialize inner page table mov eax, PTE_WRITE|PTE_PRESENT mov edi, INNER_PGTBL cld init_pte: stosd loop init_pte ; Initialize outter page table xor eax, eax mov edi, OUTTER_PGTBL cld rep stosd mov dword [OUTTER_PGTBL+0*4], INNER_PGTBL|PTE_WRITE|PTE_PRESENT mov dword [OUTTER_PGTBL+1*4], INNER_PGTBL|PTE_WRITE|PTE_PRESENT ; Load CR3 mov eax, OUTTER_PGTBL mov cr3, eax ; Enable paging and write-protect mov eax, cr0 and eax, ~(CR0_EM|CR0_TS) or eax, CR0_PG|CR0_WP|CR0_MP mov cr0, eax mov esi, msg mov edi, 0xB8000 label: mov al, [esi] mov ah, 0x0c mov [edi], ax add edi, 2 inc esi cmp al, 0 jne label jmp $ align 8 msg:db "Hello world from sinkinben", 0 gdt:dw 0,0,0,0 ; dummy dw 0xFFFF ; limit=4GB dw 0x0000 ; base address=0 dw 0x9A00 ; code read/exec dw 0x00CF ; granularity=4096,386 dw 0xFFFF ; limit=4GB dw 0x0000 ; base address=0 dw 0x9200 ; data read/write dw 0x00CF ; granularity=4096,386 gdt_desc: dw 23 ; gdt limit=sizeof(gdt) - 1 dw gdt dw 0xAA55 |
如何运行?
QEMU硬盘启动:
nasm -f bin -o paging-string.bin paging-string.asm
dd if=paging-string.bin of=paging-string.img count=1 bs=512 conv=notrunc
qemu-system-i386 paging-string.img
OSLab:开启保护模式的更多相关文章
- ASM:《X86汇编语言-从实模式到保护模式》第12章:存储器的保护
12章其实是11章的拓展,代码基本不变,就是在保护模式下展开讨论. ★PART1:存储器的保护机制 1. 修改段寄存器的保护 当执行把段选择子传到段寄存器的选择器部分的时候,处理器固件在完成传送之前, ...
- ASM:《X86汇编语言-从实模式到保护模式》第11章:进入保护模式
★PART1:进入保护模式 1. 全局描述符表(Global Descriptor Table,GDT) 32位保护模式下,如果要使用一个段,必须先登记,登记的信息包括段的起始地址,段的 ...
- Redis 保护模式
默认 redis 启用了保护模式,即如果是远程链接不能进行 CRUD 等操作,如果进行该操作报错如下 (error) DENIED Redis is running in protected mode ...
- 关于80286——《x86汇编语言:从实模式到保护模式》读书笔记15
一.80286的工作模式 80286首次提出了实模式和保护模式的概念. 实模式:和8086的工作方式相同: 保护模式:提供了存储器管理机制和保护机制,支持多任务. 二.80286的寄存器 (一)通用寄 ...
- 32位x86处理器编程导入——《x86汇编语言:从实模式到保护模式》读书笔记08
在说正题之前,我们先看2个概念. 1.指令集架构(ISA) ISA 的全称是 instruction set architecture,中文就是指令集架构,是指对程序员实际"可见" ...
- x86CPU 实模式 保护模式 傻傻分不清楚? 基于Xv6-OS 分析CR0 寄存器
基于Xv6-OS 分析CR0 寄存器 之前一直认为晕乎乎的...啥?什么时候切换real model,怎么切换,为什么要切换? ------------------------------------ ...
- Lab_1:练习3——分析bootloader进入保护模式的过程
文章链接:https://www.cnblogs.com/cyx-b/p/11809742.html 作者:chuyaoxin 一.实验内容 BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中 ...
- x86架构:从实模式进入保护模式
详细的过程说明参考:(1) https://www.cnblogs.com/Philip-Tell-Truth/p/5211248.html (2)x86汇编:从实模式到保护模式 这里简化一下 ...
- 【理解OS】1.保护模式概述
这个系列文章主要目的是为了记录我个人学习保护模式后的总结与一点点的思考.我也是一个学习者,其中由错误在所难免,若各位朋友指出将不胜感激. 1. Intel CPU的运行模式概述 这里我将粗略介绍Int ...
随机推荐
- 算发帖——俄罗斯方块覆盖问题一共有多少个解
问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形. 那么一共可以有多少个解呢?(若通过旋转.翻转一个解而得到的新解,则两个解视为同一个解) 首先,求解的问题,已经在上一篇帖子里完成 算 ...
- Python——10模块
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 6——PHP顺序结构&&字符串连接符
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- Cenots 7 安装mysql cluster 通过rpm 包
环境:Cenots 7 MG:192.168.0.105 NDB:192.168.0.108 NDB:192.168.0.109 SQL:192.168.0.111 SQL:192.168.0.107 ...
- 这几个IDEA高级调试技巧,用完就是香
一个项目启动两次 测试分布式项目时,经常要一个项目启动2次,不用将一个项目打开多次启动,配置一下即可 1.点击Edit Configurations 2.勾选Allow parallel run 3. ...
- 小白学 Python 数据分析(10):Pandas (九)数据运算
人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...
- mysql插入数据报错一二
上周selenium+phantomjs+python3简单爬取一个网站,往数据库写数据遇到以下两个问题,记录一下: 报错一:Data truncated for column 'update_tim ...
- APScheduler使用总结
安装 pip install apscheduler APScheduler组件 1.triggers(触发器) 触发器中包含调度逻辑,每个作业都由自己的触发器来决定下次运行时间.除了他们自己初始配置 ...
- Spring的工作原理
一.什么是Spring (1).Spring真正的精华是它的Ioc模式实现的BeanFactory和AOP,它自己在这个基础上延伸的功能有些画蛇添足. (2). Spring它是一个开源的项目,而且目 ...
- 关于图数据库HugeGraph的百万,千万,亿量级测试
1.Hugegraph测试硬件 1.1.本机硬件 本机测试hugeGraph版本:0.10.4 后置存储数据库:rocksdb,1TB的普通硬盘 1.2.测试服务器硬件 测试服务器hugegraph版 ...