文章目录

  • 实模式的缺陷
  • 保护模式的扩展
    • 段寄存器的变化
    • 寄存器扩展
    • 寻址扩展
  • 全局描述符表GDT
    • 描述符格式
    • 字段含义
  • 进入保护模式
    • 步骤
    • 解释
    • 示例
      • 说明
      • 程序编写
        • boot.inc
        • mbr.s
        • loader.s
      • 编译并写入硬盘
      • 启动bochs执行

实模式的缺陷

1、实模式下用户程序所引用的地址都是指向真实的物理地址,用户程序可以自由修改段基址进而轻而易举地访问所有内存,这就意味着用户程序乃至操作系统的数据都可以被随意的修改,没有安全性可言

2、实模式下访问超过64KB的内存区域需要切换段基址,一次只能运行一个程序,无法充分利用计算机的资源,总共20条地址线,最大可用内存为1MB

保护模式的扩展

段寄存器的变化


描述符索引值:GDT/LDT的index
TI:0表示在GDT中索引,1表示在LDT中索引
RPL:表示请求特权级

寄存器扩展

寻址扩展

全局描述符表GDT

描述符格式

字段含义

段基址:32位,表示段的起始地址

段界限:20位,表示段的最大偏移量

G位:
0:粒度为1B
1:粒度为4KB

D/B字段:
对于代码段(D)来说
0:按照16位模式译码(表示指令中的有效地址与操作数是16位)
1:按照32位模式译码(表示指令中的有效地址与操作数是32位)
对于栈段(B)来说
0:表示使用的是sp寄存器
1:表示使用的是esp寄存器

L字段:
0:32位代码段
1:64位代码段

AVL字段:4位,保留,用户可用

P字段:
0:表示此段不在内存中
1:表示此段在内存中

DPL字段:2位,表示段的特权级,等级分别为0、1、2、3级特权,内核处于0特权级

S位:0:表示系统段
1:表示非系统段

type字段:4位,表示段的类型,分为系统段或非系统段,由S位决定
系统段:

非系统段:

进入保护模式

步骤

1、构造段描述符
2、打开A20地址线
3、加载gdt寄存器
4、将CR0的pe位置1
5、刷新流水线

解释

构造段描述符:
保护模式的运行依赖于GDT,所以进入保护模式之前需要构造GDT

打开A20地址线:
实模式下仅有0~19号地址线可用,保护模式下地址线扩展到了32位,所以需要打开高位的地址线

加载gdt寄存器:
在CPU中有一个寄存器专用于记录GDT的地址,所以使用GDT时需要将其地址加载到gdt寄存器

将CR0的pe位置1:
CR0控制寄存器中有许多控制信息,其中pe位用于开启保护模式

刷新流水线:
由于CPU存在指令预取的操作,使得在开启保护模式之前CPU已经取得了保护模式下的指令,此时段寄存器cs中的信息仍为16实模式下的信息,所以在指令译码阶段是按照16位译码,保护模式下的指令按照实模式运行方式移码在执行阶段可能就会出错,所以需要一个远跳转来刷新cs寄存器中的信息以及清空流水线,使得32位代码以32位方式译码

示例

说明

boot.inc包含一些loader加载和gdt设置的宏定义
mbr.s用于加载loader.s,同时会在屏幕上输出"enter mbr"
loader.s用于开启保护模式,开启保护模式之前会在屏幕上输出“enter loader”,开启保护模式之后会在屏幕上输出"enter protect mode"

程序编写

boot.inc

;--------- mbr & loader ---------
LBA_START_SECTOR equ 0x1
SECTOR_COUNT equ 0x4
LOADER_BASE_ADDR equ 0x100
LOADER_OFF_ADDR equ 0x0
LOADER_ADDR equ 0x1000
;--------- gdt ---------
DESC_G_4K   equ   1_00000000000000000000000b
DESC_D_32   equ    1_0000000000000000000000b
DESC_L      equ     0_000000000000000000000b
DESC_AVL    equ      0_00000000000000000000b
DESC_LIMIT_CODE2  equ 1111_0000000000000000b
DESC_LIMIT_DATA2  equ DESC_LIMIT_CODE2
DESC_LIMIT_VIDEO2  equ 0000_000000000000000b
DESC_P      equ       1_000000000000000b
DESC_DPL_0  equ        00_0000000000000b
DESC_DPL_1  equ        01_0000000000000b
DESC_DPL_2  equ        10_0000000000000b
DESC_DPL_3  equ        11_0000000000000b
DESC_S_CODE equ          1_000000000000b
DESC_S_DATA equ   DESC_S_CODE
DESC_S_sys  equ          0_000000000000b
DESC_TYPE_CODE  equ       1000_00000000b    ;x=1,c=0,r=0,a=0 代码段是可执行的,非依从的,不可读的,已访问位a清0.
DESC_TYPE_DATA  equ       0010_00000000b    ;x=0,e=0,w=1,a=0 数据段是不可执行的,向上扩展的,可写的,已访问位a清0.;code section
DESC_CODE_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + DESC_P + DESC_DPL_0 + DESC_S_CODE + DESC_TYPE_CODE + 0x00;data section
DESC_DATA_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x00;video section
DESC_VIDEO_HIGH4 equ (0x00 << 24) + DESC_G_4K + DESC_D_32 + DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + DESC_P + DESC_DPL_0 + DESC_S_DATA + DESC_TYPE_DATA + 0x0b;--------------   选择子属性  ---------------
RPL0  equ   00b
RPL1  equ   01b
RPL2  equ   10b
RPL3  equ   11b
TI_GDT   equ   000b
TI_LDT   equ   100b

mbr.s

;主引导程序
;------------------------------------------------------------
%include "boot.inc"
SECTION MBR vstart=0x7c00         mov ax,cs      mov ds,axmov es,axmov ss,axmov fs,axmov ax, 0xB800mov gs, axmov sp,0x7c00; 清屏 利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10   功能号:0x06       功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:mov     ax, 0x600mov     bx, 0x700mov     cx, 0           ; 左上角: (0, 0)mov     dx, 0x184f     ; 右下角: (80,25),; VGA文本模式中,一行只能容纳80个字符,共25行。; 下标从0开始,所以0x18=24,0x4f=79int     0x10            ; int 0x10;;;;;;;;;     打印字符串    ;;;;;;;;;;;mov cx, sx - msgmov si, msgmov di, 0
show_str:mov byte al, [si]mov byte ah, [sx]mov word [gs:di], axinc siadd di, 2loop show_strjmp L0msg db "enter mbr"sx db 0x24;;;;;;;;;      打字字符串结束    ;;;;;;;;;;;;;;;
L0:push dspush dimov eax, LBA_START_SECTORpush eaxmov ax, SECTOR_COUNTpush axmov ax, LOADER_BASE_ADDRpush axmov ax, LOADER_OFF_ADDRpush axcall read_diskadd sp, 10pop dipop dsjmp LOADER_ADDR;;;;;;;;;      read disk      ;;;;;;;;;; LBA: [bp+10]
; sector count: [bp+8]
; destination: sec=[bp+6], off=[bp+4]
read_disk:push bpmov bp, sp;sector_countmov dx,0x1f2mov ax, [bp+8]out dx, al;sector_addrmov dx, 0x1f3mov ax, [bp+10]out dx, almov dx, 0x1f4mov al, ahout dx, almov dx, 0x1f5mov ax, [bp+12]out dx, almov dx, 0x1f6mov al, ahand al, 0x0for al, 0xe0out dx, al;command_writemov dx, 0x1f7mov al, 0x20out dx, aldisk_test:nop          ;give disk a momentin al, dxand al, 0x88 ;7: BUSY, 3: READYcmp al, 0x08 ; (BUSY=0 & READY=1) or not?jnz disk_test;data_read:   mov ax, [bp+8]mov dx, 256mul dxmov cx, axmov bx, [bp+4]mov ax, [bp+6]mov ds, axmov dx, 0x1f0
go_on_read:in ax, dxmov [bx], axadd bx,2loop go_on_readmov sp, bppop bpret
;;;;;;;;;      read disk      ;;;;;;;;;times 510-($-$$) db 0db 0x55,0xaa

loader.s

%include "boot.inc"
section loader vstart=LOADER_ADDR
;;;;;;;;;     打印字符串    ;;;;;;;;;;;mov cx, sx-msg1mov si, msg1mov di, 160
show_str:mov byte al, [si]mov byte ah, [sx]mov word [gs:di], axinc siadd di, 2loop show_strjmp Jmp_theremsg1 db "enter loader"sx db 0x24;;;;;;;;;      打字字符串结束    ;;;;;;;;;;;;;;;
Jmp_there:
;----- open A20 -----in al, 0x92or al, 00000010bout 0x92, al;----- load gdtr-----lgdt [gdt_ptr];----- cr0 set -----mov eax, cr0or eax, 0x00000001mov cr0, eax;----- clear instruction pipeline -----jmp dword SELECTOR_CODE:p_m_start[bits 32]
p_m_start:mov ax, SELECTOR_DATAmov ds, axmov es, axmov ss, axmov esp, LOADER_ADDRmov ax, SELECTOR_VIDEOmov gs, axmov ecx, GDT_BASE-msg2mov si, msg2mov di, 320
show_str2:mov byte al, [si]mov byte [gs:di], alinc siadd di, 2loop show_str2jmp $;string
msg2 db "enter protect mode";GDT_CREATE
GDT_BASE:dd 0x00000000, 0x00000000CODE_DESC:dd 0x0000FFFF, DESC_CODE_HIGH4DATA_DESC:dd 0x0000FFFF, DESC_DATA_HIGH4VIDEO_DESC:dd 0x80000007, DESC_VIDEO_HIGH4GDT_SIZE equ $ - GDT_BASE
GDT_LIMIT equ GDT_SIZE - 1
times 30 dq 0;SELECTOR_SET
SELECTOR_CODE equ 0000000000001_000b + TI_GDT + RPL0
SELECTOR_DATA equ 0000000000010_000b + TI_GDT + RPL0
SELECTOR_VIDEO equ 0000000000011_000b + TI_GDT + RPL0;GDT_pointer
gdt_ptr dw GDT_LIMITdd GDT_BASE

编译并写入硬盘

nasm -I 配置文件所在目录 -o mbr.bin mbr.s所在目录/mbr.s
nasm -I 配置文件所在目录 -o loader.s.bin loader.s所在目录/loader.s
dd if=mbr.s所在目录/mbr.bin of=硬盘所在目录/hd60M.img bs=512 count=1 seek=0 conv=notrunc
dd if=loader.s所在目录/loader.bin of=硬盘所在目录/hd60M.img bs=512 count=4 seek=1 conv=notrunc

由于loader程序大小可能超过1个扇区的大小,所以此处一次性读取4个扇区

启动bochs执行

./bochs安装目录/bochs/bin/bochs -f bochs配置文件所在目录/boot.disk

操作系统真相还原_第4章:进入保护模式相关推荐

  1. 【操作系统真象还原】第4章:保护模式入门(4.4~4.5节)

    目录 4.4 处理器微架构简介 4.4.1 流水线 4.4.2 乱序执行 4.4.3 缓存 4.4.4 分支预测 4.5 使用远跳转指令清空流水线,更新段描述符缓冲寄存器 4.6 保护模式之内存段的保 ...

  2. 操作系统真相还原_第5章第4节:特权级

    文章目录 特权级 TSS简介 CPL和DPL入门 处理器提供的从低特权级到高特权级的方法 门.调用门和RPL序 特权级 保护模式下特权级按照权力大小分为0.1.2.3级 0特权级是操作系统内核所在的的 ...

  3. 操作系统真象还原_第零章_解惑

    第零章 解惑 1.操作系统是什么? 类比一 古代部落害怕手下的人滥用武器伤害他人,所以制造武器是要向部落申请.而人们只有申请的资格,申请结果有部落决定. 设计操作系统的人害怕使用者滥用硬件(例如把操作 ...

  4. 《操作系统真象还原》第六章 ---- 开启c语言编写函数时代 首挑打印函数小试牛刀 费心讨力重回gcc降级 终尝多日调试之喜悦

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 修改代码的小闲聊 编写print.S(实现打印函数) print.S代码 print.h代码和stdint.h代码 修改main ...

  5. 《操作系统真象还原》第七章

    <操作系统真象还原>第七章 本篇对应书籍第七章的内容 本篇内容介绍了操作系统的中断处理机制,建立中断描述符表,填充门描述符,以及中断处理程序,初始化8259A中断控制器实现外部中断功能,控 ...

  6. [操作系统] 操作系统真相还原读书笔记三:MBR加载loader到内存并跳转到loader执行

    为什么要有loader程序? 通过操作系统真相还原读书笔记二:编写MBR主引导记录我们已经能够正常运行MBR主引导记录(有些书籍也叫做boot)程序了,但该程序什么也没做.我们的MBR 受限于 512 ...

  7. 操作系统真相还原学习笔记

    录像51 操作系统真相还原–学习笔记 这个笔记是把郑钢先生的代码在windows上编译运行了,希望大家在win上也调试地愉快. 链接:https://pan.baidu.com/s/1T7Sj_ZwA ...

  8. 操作系统真相还原-编译遇到“__stack_chk_fail_local”错误

    编写操作系统真相还原 – 中断系统时, 在编译链接时遇到了一个问题 我先按照书上所说(如下方), 进行编译 gcc -m32 -I lib/kernel/ -I lib/ -I kernel/ -c ...

  9. 我是如何学习写一个操作系统(三):操作系统的启动之保护模式

    前言 上一篇其实已经说完了boot的大致工作,但是Linux在最后进入操作系统之前还有一些操作,比如进入保护模式.在我自己的FragileOS里进入保护模式是在引导程序结束后完成的. 实模式到保护模式 ...

最新文章

  1. oracle查询表中的某一行,oracle查看所有表及各表行数?
  2. ThinkPHP源码阅读1-------访问流程
  3. 非此即彼的逻辑错误_MBA逻辑攻略逻辑知识大全,快来收藏吧!
  4. python中plotly.express中线条图,Plotly在Python中表达的意外行
  5. python基础之删除文件及删除目录的方法
  6. 使用栈实现队列 Implement Queue using Stacks
  7. 小甲鱼Python笔记(下)
  8. Inter Thread Latency
  9. 什么是计算机计算机网络的主要功能是什么,计算机网络的三大主要功能是什么?-与非网...
  10. arrayfun用法
  11. C#string与char互转
  12. iconfont-阿里巴巴矢量图标库的使用方法
  13. VSCode中文版快捷键
  14. 二叉树前中后序遍历【非递归】
  15. c语言网络病毒代码大全,C语言病毒 - 各类源码 - 中国红客联盟 - Powered by HUC
  16. Allure清除历史记录
  17. cad线加粗怎么设置_CAD图形中线条如何加粗?
  18. 宣传单印刷价格明细报价的影响因素有哪些?
  19. 欧洲杯上链,区块链语境下的数字化有什么不一样?
  20. java 如何计算时间段_Java程序来计算两个时间段之间的时差

热门文章

  1. 编译linux系统到开发板,Linux系统有关交叉编译和移植到6410开发板上的简单过程...
  2. opentracing-02 dapper论文词汇摘要
  3. Node.js 官网入门教程(一) CommonJS 模块规范、Node.js REPL、console、CLI、exports
  4. linux 应用层gpio中断_linux gpio中断
  5. 暴雪正在物色接盘侠/ iOS16.2正式版发布/ 马斯克拍卖推特产品…今日更多新鲜事在此...
  6. git莫名其妙缓存5k+文件
  7. CVPR 2022 | 将X光图片用于垃圾分割,港中大(深圳)探索大规模智能垃圾分类
  8. Leetcode--SQL刷题(176-262)
  9. 【魔方网表】魔方网表涉及到的公式整理
  10. 如何使用AI进行SCI组图