漫漫 OSDEV 之路

2024年4月20日
2020年8月21日

高中的时候,有次我看到《30 天自制操作系统》这本书,是个日本老哥写的,岛国人们的科技树和西方的科技树点的总不太一样,这本书点亮后的第一件事就是画鼠标、画桌面、画窗口,这其实都还好,最邪恶的是这本书用的工具链全是作者魔改的,但是提供了 windows 版本(这一点值得好评。当时就跟了他学了一点输出字符就没有继续下去了(这古书写的还是为软盘启动设计的。虽然但是,开发操作系统之路就从此开始了。

来自旧世代的记录

这里本来是记的一些古早时期开发操作系统(其实主要就是写汇编和 bootloader)时的零碎问题,单留着看着感觉东一点西一点的,就和新的文章并在一起了。

MBR 程序在 bochs 可以正常运行但是在 VMware 中表现异常

经尝试后大致推测原因为没有设定 SSSP 的值,导致 retIP 寄存器被被赋予了未定义的值。但是此问题在 bochs 中并没有表现出来。

ret 返回到了一个错误的地址

当时程序表现为引导程序持续重启,后调试发现某次 ret 后跳转至了内存 0x81e9 处,而此地址不在引导程序的范围内。检查堆栈发现此程序使用 0x7c00 作为栈底,0x81e9 恰好于程序头两个字节一致。最后检查代码发现实为原本应该用 call 的地方误用了 jmp,导致 ret 时发生错误。

《30天自制操作系统》中为何引导程序要跳转至 0xc200 处

起初简单认为是某个约定的值,但在自己实践时始终无法成功跳出 MBR 进入后续部分。后来我认为是书中所使用的镜像制作工具有特殊操作导致的,但经实验被证否,使用 WinImage 和书中的程序是可以正常运行的。了解 FAT12 文件系统的结构后发现其数据区从偏移 0x4200 处开始,而且数据被从头开始加载至 0x8000 处,两者叠加就有了 0xc200。若直接将软盘 0x4200 偏移处的数据加载至 0x8000 处,则直接 jmp 0x8000 就可以了。

使用 BIOS 的 int 0x15 0xe820 获取内存结构失败

这里的失败不是中断按照约定返回了一个错误码,而是导致程序不正常运行或给出了不正常的数据。经过多次试验,现发现当 ES:DI 指向的缓冲区在当前程序数据内,且偏移小于 0xff 时(即使通过变换段寄存器的值使 DI 的值大于等于 0xff 也会失败,就会根据 DI 的具体数值触发诸如宕机,在 BIOS 代码内死循环,底端内存被全部覆写为 0x8a,返回数据为乱码等问题。导致此情况的原因未知。最后采用将数据段置于代码段之后(拉高偏移值)的方法。