从零开始制作 MyOS(三)

news/2025/10/28 10:11:04/文章来源:https://www.cnblogs.com/wanghao-boke/p/19171084

从零开始制作 MyOS(三)—— 切换保护模式

目标

今天的目标是从实模式切换到保护模式

保护模式切换流程

  1. 设置GDT (lgdt)
  2. 启用A20地址线
  3. 设置CR0.PE标志
  4. 远跳转刷新流水线
  5. 初始化保护模式段寄存器

关键组件解析

  1. GDT 设置
  • gdt_start​:定义全局描述符表
    • 空描述符(必须存在)
    • 代码段描述符(可执行、只读)
    • 数据段描述符(可读写)
  • gdt_descriptor​:包含GDT大小和基地址
  1. 内存布局
  • 0x7C00-0x7DFF:引导扇区
  • 0x10000:内核加载位置(64KB处)
  • 0x90000:保护模式栈指针
  1. 关键寄存器作用​:

​+ CR0​:控制寄存器,PE位控制保护模式

  • ​GDTR​:存储GDT的基址和界限
    ​+ 段寄存器​:在保护模式下变为段选择子

代码

; boot.asm - BIOS boot sector with protected mode switch
org 0x7C00       ; BIOS加载引导扇区到内存0x7C00处
bits 16          ; 16位实模式代码start:; === 初始化环境 ===cli         ; 禁用中断(防止设置过程中被中断)xor ax, ax  ; AX清零(比mov ax,0更高效)mov ds, ax  ; 数据段寄存器DS=0mov es, ax  ; 额外段寄存器ES=0mov ss, ax  ; 堆栈段寄存器SS=0mov sp, 0x7C00 ; 栈指针SP=0x7C00(向下增长)sti         ; 启用中断; === 显示加载信息 ===mov si, loading_msgcall print_string; === 加载磁盘内容 ===call load_diskjc disk_error  ; 如果出错跳转到错误处理; === 显示加载成功信息 ===mov si, loading_disk_successcall print_string; === 准备保护模式 ===call setup_gdt    ; 设置全局描述符表(GDT)call enable_a20    ; 启用A20地址线call switch_to_pm  ; 切换到保护模式; === 永远不会执行到这里 ===jmp $;============= 磁盘加载函数 =============
load_disk:; 参数:;   dl = 驱动器号 (0x80=第一硬盘);   dh = 磁头号;   ch = 柱面号;   cl = 起始扇区号(1-based);   al = 要读取的扇区数;   es:bx = 目标缓冲区地址; 返回:;   CF = 1表示出错mov dl, 0x80    ; 驱动器号(0x80=第一硬盘)mov dh, 0       ; 磁头号mov ch, 0       ; 柱面号mov cl, 2       ; 起始扇区号(1-based)mov al, 8       ; 要读取的扇区数(8*512=4KB)mov bx, 0x8000  ; 目标偏移地址mov es, bx      ; ES:BX = 0x8000:0x0000xor bx, bx      ; BX清零mov ah, 0x02    ; BIOS读扇区功能号int 0x13        ; 调用BIOS磁盘服务; === 错误重试机制(最多3次) ===mov byte [retry_count], 3
.retry:jnc .success    ; 成功则跳转; === 重置磁盘控制器 ===pushaxor ah, ah      ; 功能号0=重置磁盘int 0x13popadec byte [retry_count]jz .failure     ; 重试次数用完; === 重新尝试读取 ===int 0x13jmp .retry.success:ret             ; 成功返回.failure:stc             ; 设置进位标志表示错误ret             ; 返回;============= 保护模式设置 =============
setup_gdt:; 加载GDT描述符到GDTR寄存器lgdt [gdt_descriptor]retenable_a20:; === 通过键盘控制器启用A20地址线 ===; 步骤1: 发送禁用键盘命令call .wait_kbdmov al, 0xADout 0x64, al; 步骤2: 发送读取输出端口命令call .wait_kbdmov al, 0xD0out 0x64, al; 步骤3: 读取输出端口值call .wait_kbdin al, 0x60push ax          ; 保存原始值; 步骤4: 发送写入输出端口命令call .wait_kbdmov al, 0xD1out 0x64, al; 步骤5: 写回输出端口值(启用A20)call .wait_kbdpop axor al, 2         ; 设置A20使能位out 0x60, alret.wait_kbd:; 等待键盘控制器就绪in al, 0x64test al, 0x02    ; 检查输入缓冲区状态jnz .wait_kbd    ; 缓冲区不为空则继续等待retswitch_to_pm:; === 切换到保护模式 ===cli              ; 禁用中断mov eax, cr0     ; 加载控制寄存器or eax, 0x1      ; 设置PE(保护模式使能)位mov cr0, eax     ; 写回控制寄存器; 远跳转刷新流水线并加载CS段选择子jmp CODE_SEG:init_pm;============= 32位保护模式代码 =============
bits 32
init_pm:; === 初始化保护模式段寄存器 ===mov ax, DATA_SEGmov ds, axmov es, axmov fs, axmov gs, axmov ss, axmov esp, 0x90000 ; 设置32位栈指针; === 清屏 ===mov edi, 0xB8000 ; VGA文本缓冲区基址mov ecx, 80*25   ; 80列25行mov ax, 0x0F20   ; 黑底白字的空格
.clear:stosw             ; 写入显存loop .clear; === 显示保护模式激活信息 ===mov edi, 0xB8000 + 160 ; 第二行开始显示mov esi, pm_msg   ; 字符串地址mov ah, 0x0F      ; 白字黑底属性
.print_loop:lodsb             ; 从esi加载字符到altest al, al       ; 检查字符串结束(0)jz .halt          ; 如果为0则跳转到haltstosw             ; 写入字符+属性jmp .print_loop.halt:clihlt               ; 停止CPU执行;============= 错误处理 =============
disk_error:mov si, error_msgcall print_stringjmp $print_string:; === 实模式字符串打印函数 ===lodsb           ; 加载SI指向的字符到ALtest al, al     ; 检查是否字符串结束jz .done        ; 如果是则结束mov ah, 0x0E    ; BIOS显示字符功能mov bh, 0       ; 显示页面0int 0x10        ; 调用BIOS视频服务jmp print_string ; 继续处理下一个字符
.done:ret             ; 返回;============= 数据区 =============
retry_count db 0    ; 磁盘重试计数器
loading_msg db "Loading protected mode...", 0xD, 0xA, 0
loading_disk_success db "Disk loaded successfully!", 0xD, 0xA, 0
error_msg db "Disk error! System halted.", 0
pm_msg db "32-bit Protected Mode Activated!", 0  ; 确保以0结尾;============= GDT 定义 =============
gdt_start:dq 0 ; 第一个描述符必须为空描述符; 代码段描述符
gdt_code:dw 0xFFFF    ; 段界限(低16位)dw 0         ; 段基址(低16位)db 0         ; 段基址(中8位)db 10011010b ; 访问字节(参见下方说明)db 11001111b ; 标志位 + 段界限(高4位)db 0         ; 段基址(高8位); 数据段描述符
gdt_data:dw 0xFFFF    ; 段界限(低16位)dw 0         ; 段基址(低16位)db 0         ; 段基址(中8位)db 10010010b ; 访问字节db 11001111b ; 标志位 + 段界限(高4位)db 0         ; 段基址(高8位)gdt_end:; GDT描述符(供LGDT指令使用)
gdt_descriptor:dw gdt_end - gdt_start - 1 ; GDT大小(16位)dd gdt_start               ; GDT基地址(32位); 段选择子常量
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start; 引导签名
times 510 - ($ - $$) db 0  ; 填充剩余空间(510字节)
dw 0xAA55                  ; 引导扇区签名(最后2字节)

编译

添加 Makefile 文件


make cleanmake

运行


# 在 ubuntu 的终端
make run-vga

结果

保护模式切换成功

遇到的问题

  1. 保护模式切换时,qemu 面板输出的内容一直刷新闪烁
  • 在保护模式下调用实模式的print_string函数段寄存器未正确设置导致内存访问错误
  1. 执行运行命令后打印不出切换成功的日志
  • 检查 qemu 执行时是否使用 serial 参数,代码中使用的 vga 模式输出字符串

后续开发任务

​内核开发​:

  • 实现基本屏幕输出(VGA文本模式)
  • 添加中断描述符表(IDT)
  • 支持键盘输入

​内存管理​:

  • 实现分页机制
  • 添加物理内存管理器

​高级功能​:

  • 多任务支持
  • 文件系统驱动
  • 用户模式切换

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/948486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年口碑好的富氢水机招商加盟项目合作

2025年口碑好的富氢水机招商加盟项目合作指南 随着健康饮水理念的普及,富氢水机因其抗氧化、促进新陈代谢等功效,成为净水行业的新宠。2025年,富氢水机市场迎来爆发式增长,众多企业纷纷布局招商加盟业务。本文精选…

2025年评价高的澳洲海外仓一件代发跨境电商优选平台榜

2025年评价高的澳洲海外仓一件代发跨境电商优选平台榜 引言 随着跨境电商的蓬勃发展,澳洲市场因其稳定的消费能力和成熟的电商环境,成为众多中国卖家的首选目标。然而,物流和仓储问题一直是跨境卖家的痛点,尤其是…

向JKS(Java KeyStore)文件中添加证书

向JKS(Java KeyStore)文件中添加证书向JKS(Java KeyStore)文件中添加证书是一个常见的操作,主要用于配置SSL/TLS。下面我将为你详细介绍操作方法、注意事项以及相关概念。 🗂️ 理解JKS的类型 首先,理解JKS的两…

2025年评价高的企业目视化规划最新品牌实力榜品牌

2025年评价高的企业目视化规划最新品牌实力榜在当今竞争激烈的商业环境中,企业目视化管理已成为提升运营效率、增强安全性和塑造品牌形象的关键战略。目视化规划通过直观的视觉元素将复杂的管理流程简化,使信息传递更…

2025年口碑好的河南公司注册代理记账企业推荐榜

2025年口碑好的河南公司注册代理记账企业推荐榜 在当今竞争激烈的商业环境中,选择一家专业、可靠的代理记账公司对企业的发展至关重要。河南作为中部地区的重要经济省份,拥有众多优秀的财税服务企业,它们凭借专业的…

若干思维题总结

P6005 [USACO20JAN] Time is Mooney G 题目描述 Bessie 正在安排前往牛尼亚的一次出差,那里有 \(N\)(\(2 \leq N \leq 1000\))个编号为 \(1 \ldots N\) 的城市,由 \(M\)(\(1 \leq M \leq 2000\))条单向的道路连接…

2025年热门的窖藏坛装涪陵榨菜品牌

2025年热门的窖藏坛装涪陵榨菜品牌推荐指南 在涪陵这片被誉为“中国榨菜之乡”的土地上,榨菜产业历经百年沉淀,已成为中国饮食文化的重要符号。随着消费者对健康、品质和传统工艺的追求,窖藏坛装榨菜凭借其独特的风…

2025年度印刷机专用稳压器生产商TOP3综合实力榜单:干式稳压器/智能型稳压器/无触点稳压器源头厂家精选。

在印刷行业,电压稳定性直接决定印刷品质与设备寿命,一款高性能专用稳压器能有效保障设备持续稳定运行。 本文将根据技术性能、场景适配性与市场反馈,为您推荐三家在印刷机专用稳压器领域表现卓越的生产商,帮助印刷…

【译】在 Visual Studio 中引入计划功能(公开预览版)

快速提示对于小的修改很有用,但在大型项目中就力不从心了。您最终会不断重写指令、反复调整,还得指望模型能按计划进行。它为 Copilot 提供了一条清晰、结构化的路径去遵循,这条路径会随着工作的推进而更新,并且让…

2025年口碑好的企业VI设计实力公司

2025年口碑最佳的企业VI设计实力公司权威推荐指南 在品牌竞争日益激烈的商业环境中,企业视觉识别系统(VIS)已从简单的视觉包装升维为企业战略的核心组成部分。优秀的VI设计不仅能提升品牌辨识度,更能通过系统化的…

2025年评价高的团餐配送最新用户口碑榜品牌

2025年评价高的团餐配送最新用户口碑榜品牌 在快节奏的现代生活中,团餐配送服务已成为企事业单位、学校、医院等机构的重要后勤保障。随着消费者对食品安全、营养搭配和服务效率的要求不断提高,优质的团餐品牌凭借规…

2025 年深圳餐饮设计公司最新推荐榜,聚焦机构专业能力与项目落地成效深度剖析潮流引领 / 功能优化 / 成本精控 / 品牌塑造公司推荐

引言 为助力深圳餐饮经营者精准选择专业设计机构,本次推荐榜由餐饮品牌建设协会联合深圳餐饮行业协会共同发起测评,历时 3 个月完成数据采集与分析。测评采用 “三维九项” 评估体系,从专业能力(包括 IP 策划深度、…

pwn中常用函数

pwn中常用函数 输入输出类 write()函数 *函数原型:**ssize_t write(int fd, const void *buf, size_t count) 函数功能:由fd指定输出的位置,将buf的内容进行输出,输出的长度为n 函数参数:fd:文件描述符;write一…

2025 年模压桥架厂家最新推荐榜,技术实力与市场口碑深度解析:高承重耐腐蚀品牌甄选

引言 模压桥架作为电力传输与电缆管理的核心设备,其品质直接决定基础设施运维安全。据电力企业联合会 2025 年专项测评数据显示,国内模压桥架市场合格率仅 78%,32% 的故障源于工艺缺陷导致的承重不足或防腐失效。为…

为什么在componentDidMount()中请求数据?

componentDidMount()是React 生命周期重要部分 先理解生命周期顺序 在 React 类组件(Class Component) 中,组件的主要生命周期顺序如下:constructor() → 初始化 state、绑定方法render() → 渲染 UI(但此时 DOM …

2025年质量好的云南房屋加固用户好评榜

2025年质量好的云南房屋加固用户好评榜 在建筑结构安全日益受到重视的今天,房屋加固已成为保障建筑安全、延长使用寿命的重要手段。云南省地处地震多发带,房屋抗震加固需求尤为突出。2025年,随着技术的进步和市场的…

关心安全与效率?内外网文件交换系统有哪些,一文讲透!

在数字化时代,企业与机构的业务运转高度依赖数据流转,而内外网隔离作为保障网络安全的核心手段,使得“内外网文件交换”成为刚需场景。所谓内外网文件交换系统,是指在物理或逻辑隔离的内网(如企业核心业务网、涉密…

2025年耐用的覆盖膜离型纸厂家选购指南与推荐

2025年耐用的覆盖膜离型纸厂家选购指南与推荐在电子制造、医疗设备和包装行业等领域,覆盖膜离型纸作为关键材料之一,其质量直接影响产品性能和成本效益。随着2025年新材料技术的快速发展,选择一家可靠的覆盖膜离型纸…

2025年煤矿人工智能厂家权威推荐榜单:矿山人员三违智能检测系统 /矿山工作面AI智能检测系统/矿山主运输AI智能检测系统源头厂家精选

随着智能化浪潮席卷煤炭行业,人工智能技术正深刻改变着传统煤矿的生产模式与安全管理模式。据权威机构统计,2024年我国煤矿智能化市场规模已突破650亿元,其中AI相关解决方案占比达到35%,年均增长率维持在28% 以上。…

2025年知名的称重地磅TOP实力厂家推荐榜

2025年知名的称重地磅TOP实力厂家推荐榜 在工业、物流、农业等领域,称重地磅是不可或缺的基础设备。随着技术的进步,称重设备的精准度、稳定性和智能化程度不断提升,市场对高品质称重设备的需求也日益增长。2025年…