当前位置: 首页 > news >正文

从零开始制作 MyOS(六)

从零开始制作 MyOS(六)

今天的任务是:添加异常处理代码——除零操作。

除零操作的过程概述:

C代码中的除零代码被编译成汇编语言,然后CPU在执行的时候发现除数为0后,直接触发除零错误,然后保存上下文,关中断,去读取IDT设置的错误类型是否有对应匹配,如果有就跳转到该错误处理方式。

背景知识

什么是中断

  1. 中断是CPU暂停当前执行流程,转去执行特定处理程序,完成后恢复原流程的机制。
  2. 中断分为硬件中断和软件中断:
    • 硬件中断是由外部设备,比如鼠标,键盘等发出,PIC/APIC 触发;
    • 软件中断是由 CPU 内部事件触发,比如异常:指令执行过程中产生的错误或特殊清空;比如软中断:通过指令 INT n 指令主动触发中断

中断的作用

  1. 实现设备异步通知
  2. 处理紧急事件
  3. 支持多任务调度
  4. 提供系统调用接口

什么异常

异常指CPU在执行指令过程中检测到的特殊条件或错误情况,会自动触发中断处理。

异常分为故障,陷阱,中止

  1. 故障:可修复,修复后可重新执行的异常:比如叶故障,段不存在,堆栈故障
  2. 陷阱:用于调试,执行后可继续下条指令,比如断点,单步执行,溢出等
  3. 中止:一种无法恢复的严重错误,通常需要终止程序,比如有双重故障,机器检查

如何处理异常

在保护模式下,异常通过中断描述符表(IDT) 来处理。IDT包含256个条目,每个条目描述一个中断或异常的处理程序

IDT

中断描述符表(Interrupt Descriptor Table),是 x86 架构在保护模式下用于处理中断和异常的数据结构,定义了 256 个中断向量的处理程序

IDT内存布局:
+----------------+ 0x00000000
| 条目0 | ← 异常0:除零错误
+----------------+
| 条目1 | ← 异常1:调试异常
+----------------+
| 条目2 | ← 异常2:NMI
+----------------+
| ... |
+----------------+
| 条目32 | ← IRQ0:定时器中断
+----------------+
| ... |
+----------------+
| 条目255 | ← 最后的中断向量
+----------------+

异常处理流程

除法指令 → 除数为0 → CPU自动保存状态 → 查找IDT[0] → 跳转到isr0 → 执行异常处理程序

代码

一、数据结构定义

  1. 中断描述符条目 (IDT Entry)
struct idt_entry {uint16_t base_low;    // 处理程序地址低16位uint16_t selector;    // 代码段选择子(0x08 = 内核代码段)uint8_t zero;         // 保留,必须为0uint8_t flags;        // 类型属性(0x8E = 32位中断门)uint16_t base_high;   // 处理程序地址高16位
} __attribute__((packed));

关键参数说明:

  • selector: 0x08 - 指向GDT中的内核代码段
  • flags: 0x8E - 表示32位中断门,DPL=0(最高权限)
  1. 中断帧 (Interrupt Frame)
struct interrupt_frame {uint32_t eip;        // 发生异常时的指令指针uint32_t cs;         // 代码段选择子uint32_t eflags;     // 标志寄存器状态uint32_t esp;        // 栈指针uint32_t ss;         // 栈段选择子uint32_t error_code; // 错误代码(某些异常才有)
};

当异常发生时,CPU会自动将寄存器值压入栈中,形成中断帧

二、IDT 初始化过程

void idt_init(void) {struct idt_ptr idtp;idtp.limit = (sizeof(struct idt_entry) * IDT_ENTRIES) - 1;idtp.base = (uint32_t)&idt;// 设置除零异常处理idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E);idt_load((uint32_t)&idtp);printf("IDT initialized with divide-by-zero handler\n");
}

关键步骤:

  1. 设置IDT指针(limit和base)
  2. 配置异常0的处理程序为isr0
  3. 使用lidt指令加载IDT

三、汇编异常处理程序


isr0:cli                 ; 关中断,防止嵌套异常pusha               ; 保存所有通用寄存器push esp            ; 传递栈指针(指向中断帧)call divide_by_zero_handler  ; 调用C处理程序; 处理程序不应返回,如果返回则继续执行add esp, 4popasti                 ; 开中断iret                ; 中断返回(不会执行到这里)

寄存器保存的意义:

  1. pusha - 保存EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI
  2. push esp - 将当前栈指针传递给C函数作为中断帧指针

四、C 语言处理异常程序

void divide_by_zero_handler(struct interrupt_frame* frame) {printf("\n=== DIVIDE BY ZERO EXCEPTION ===\n");printf("Instruction Pointer: 0x%x\n", frame->eip);printf("Code Segment: 0x%x\n", frame->cs);printf("Stack Pointer: 0x%x\n", frame->esp);printf("=== SYSTEM HALTED ===\n");// 彻底挂起系统asm volatile("cli");while(1) {asm volatile("hlt");}
}

调试信息的意义:

  1. EIP - 显示触发异常的指令位置
  2. CS - 显示代码段,验证运行在保护模式
  3. ESP - 显示栈指针,帮助调试栈相关问题

开发经验总结

  1. 一直遇到 Qemu 界面窗口闪烁,也就是系统一直在重启
  • 问题是在于 extern void idt_load(void) 声明的时候是不带参数的,而在 interrupt.asm 汇编中,使用了 mov eax, [esp + 4] ; 获取IDT指针 , IDT 参数加载缺失

其他常见问题

  1. 栈帧结构不匹配 - C函数接收到错误参数
  2. 段寄存器未设置 - 在保护模式下调用C函数前需要正确设置数据段
http://www.jsqmd.com/news/33442/

相关文章:

  • 2025年11月介电常数测试仪推荐厂家排行:应该如何选择靠谱供应商
  • 2025年11月电阻率测试仪工厂推荐:北京冠测精电——信誉、口碑与售后的三重保障
  • SaaS版MES系统PC端后台特性清单与设计说明
  • 【2025臻选指南】酸角糕十大品牌深度解析:传承古法与现代创新的完美融合
  • 2025年水上游乐及泳池设备标杆厂家推荐:山东汇川,室内水上乐园/儿童水上乐园/大型水上乐园/室内泳池/定制化服务引领行业新标​
  • 深入解析:开源 C++ QT QML 开发(十四)进程用途
  • 各种扩展模块
  • 2025年冷冻式干燥机标杆厂家最新推荐:凌宇机械,冷冻式压缩空气干燥机/风冷高温冷冻式干燥机/水冷高温冷冻式干燥机/吸附式干燥机/以高效节能与全场景方案树立行业新标准
  • 2025全日制艺考生文化课机构推荐榜:全日制艺考生文化课,小众优质机构精准适配需求
  • 2025艺术涂料厂家推荐榜:进口艺术涂料、意大利进口艺术涂料、意大利艺术涂料厂家,装修选品不踩坑
  • 2025济南艺考文化课培训推荐榜:艺考文化课培训,艺考文化课培训机构适配不同艺考生需求
  • For xinye666
  • 从手写周报到智能生成:PandaCoder如何让你的工作汇报效率提升10倍
  • 2025优质媒体服务商推荐榜:媒体邀约靠谱平台助力品牌高效传播
  • 2025大连汽车凹陷修复厂家推荐榜:震城汽车领衔,汽车数据修复厂家靠谱机构守护原厂漆质感
  • 详细介绍:iBizModel 实体主状态(PSDEMAINSTATE)及主状态逻辑(PSDELOGIC`MAINSTATELOGIC`)模型详解
  • 2025氮化硼陶瓷推荐榜:福维科(山东)五星领跑,氮化硼陶瓷高温绝缘体/坩埚/套管/基板/高温构件/耐腐蚀构件优质厂家赋能产业升级
  • Maui 实践:JavaScript 动态生成集合属性的 get/set 代理
  • 2025小王子亚麻籽薯片工厂推荐榜:小王子亚麻籽薯片厂家实力派承包休闲时光
  • 2025大连养老院机构推荐榜:养老院中心、社区养老院守护舒心晚年
  • Apache是干嘛用的?Apache服务器搭建教程
  • ewomail docker搭建
  • Playwright为什么老是跑不稳?12个坑踩完我终于懂了!
  • 阿里云微服务引擎 MSE 及 API 网关 2025 年 10 月产品动态
  • 2025年厂房降温设备厂家新推荐排行榜白皮书,厂房降温设备哪个厂家好
  • 无畏级战列舰(HMS Dreadnought)
  • android音频低延时设计:Fast Mixer官方文档 - 详解
  • 华人数学家反击AI!一场关于和差集问题的突破接力赛
  • raft 写请求源码走读
  • 2025 年在线监测系统厂家最新推荐榜单:洁净环境、尘埃粒子、洁净室、无尘室等设备品牌技术与应用全面解析尘埃粒子在线监测系统/无尘室在线监测系统公司推荐