日期: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:开启保护模式的更多相关文章

  1. ASM:《X86汇编语言-从实模式到保护模式》第12章:存储器的保护

    12章其实是11章的拓展,代码基本不变,就是在保护模式下展开讨论. ★PART1:存储器的保护机制 1. 修改段寄存器的保护 当执行把段选择子传到段寄存器的选择器部分的时候,处理器固件在完成传送之前, ...

  2. ASM:《X86汇编语言-从实模式到保护模式》第11章:进入保护模式

    ★PART1:进入保护模式 1. 全局描述符表(Global Descriptor Table,GDT)        32位保护模式下,如果要使用一个段,必须先登记,登记的信息包括段的起始地址,段的 ...

  3. Redis 保护模式

    默认 redis 启用了保护模式,即如果是远程链接不能进行 CRUD 等操作,如果进行该操作报错如下 (error) DENIED Redis is running in protected mode ...

  4. 关于80286——《x86汇编语言:从实模式到保护模式》读书笔记15

    一.80286的工作模式 80286首次提出了实模式和保护模式的概念. 实模式:和8086的工作方式相同: 保护模式:提供了存储器管理机制和保护机制,支持多任务. 二.80286的寄存器 (一)通用寄 ...

  5. 32位x86处理器编程导入——《x86汇编语言:从实模式到保护模式》读书笔记08

    在说正题之前,我们先看2个概念. 1.指令集架构(ISA) ISA 的全称是 instruction set architecture,中文就是指令集架构,是指对程序员实际"可见" ...

  6. x86CPU 实模式 保护模式 傻傻分不清楚? 基于Xv6-OS 分析CR0 寄存器

    基于Xv6-OS 分析CR0 寄存器 之前一直认为晕乎乎的...啥?什么时候切换real model,怎么切换,为什么要切换? ------------------------------------ ...

  7. Lab_1:练习3——分析bootloader进入保护模式的过程

    文章链接:https://www.cnblogs.com/cyx-b/p/11809742.html 作者:chuyaoxin 一.实验内容 BIOS将通过读取硬盘主引导扇区到内存,并转跳到对应内存中 ...

  8. x86架构:从实模式进入保护模式

    详细的过程说明参考:(1)  https://www.cnblogs.com/Philip-Tell-Truth/p/5211248.html    (2)x86汇编:从实模式到保护模式 这里简化一下 ...

  9. 【理解OS】1.保护模式概述

    这个系列文章主要目的是为了记录我个人学习保护模式后的总结与一点点的思考.我也是一个学习者,其中由错误在所难免,若各位朋友指出将不胜感激. 1. Intel CPU的运行模式概述 这里我将粗略介绍Int ...

随机推荐

  1. Web 项目刚要打包,却找不到项目资源?

    编程无小事,不管是语言层面还是工具层面,都要熟悉,方能在编程中过程中众享丝滑,不然就随处卡顿,耗费时间不说,还没有任何成就感.撸码过程中用 Idea 也很多年了,工具或环境遇到问题,问下度娘就完事了, ...

  2. C++走向远洋——28(项目三,时间类,2)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:time.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  3. Day06 - Fetch、filter、正则表达式实现快速古诗匹配

    Day06 - Fetch.filter.正则表达式实现快速古诗匹配 作者:©liyuechun 简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战.项目免费提供了 30 个 ...

  4. 大多数项目中会用到的webpack小技巧

    原文地址 本文是作者对自己所学的webpack技巧的总结,在没有指定特殊情况下适用于webpack 3.0版本. 进度汇报 使用webpack --progress --colors这样可以让编译的输 ...

  5. http相关知识点回顾

    一.概述 1.什么是HTTP HTTP是一种可以获取HTML这样的网络资源的一种通讯协议protocol.是在WEB上进行数据交换的基础,是一种客户端--服务器协议.HTTP是一种可扩展的应用层协议, ...

  6. Node的require和module.exports

    node编程中最重要的思想之一就是模块,在 Node.js 模块系统中,每个文件都被视为独立的模块.这是这个思想,让javascript的大规模工程成为可能.模块化编程在前端大肆盛行,在node中导出 ...

  7. 教你用纯Java实现一个网页版的Xshell(附源码)

    前言 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用,当时看到了很多这方面的项目,例如:Gat ...

  8. 【ERROR 1064 (42000)】MySQL中使用mysqladmin或set修改root密码时提示语法错误

    报错信息: mysql> mysqladmin -uroot -p123456 password 654321; ERROR 1064 (42000): You have an error in ...

  9. 有了这套微信小程序x5调试,调试一些简单的开发者工具调试不了的功能不成问题!!!!

    1.首先我们需要打开微信 TBS 调试 地址是:http://debugx5.qq.com 2.然后打开手机 打开开发者模式,打开 USB 调试 3.然后 在谷歌浏览器地址栏输入 chrome://i ...

  10. SSL/TLS 协议运行机制概述(二)

    SSL/TLS 协议运行机制概述(二) 在SSL/TLS 协议运行机制概述(一)中介绍了TLS 1.2 的运行机制,现在我们来看年 TLS 1.3 的运行机制.会涉及到SSL/TLS 协议运行机制概述 ...