0xFE 序言

赶上吾爱破解十五周年开放注册, 注册了个账号. 随便翻了翻精品帖子, 看到从0到-1写一个操作系统-0xFF-!!完结撒花!!, 感觉还不错, 于是开始动手实践, 开一个博客记录, 也是督促自己坚持下去.

0xFF 操作系统的启动

实模式

刚开机时CPU进入实模式, 因为此时只能使用物理地址.
实模式地址的分布是固定的,以8086为例, BIOS入口在0xFFFF0到0xFFFFF之间, 其中是一个jmp指令, 跳转到真正的BIOS位置. 中断向量表在0x00000到0x003FF. MBR加载地址在0x7C00到0x7DFF.

BIOS(Basic Input/Output System)

基本输入输出系统. 早期存储在ROM中, 现在存储在主板上的一个或多个芯片中. 目前其继承者UEFI(Unified Extensible Firmware Interface)正在全面取代BIOS.
BIOS首先进行加电自检(Power-On Self-Test), 缩写为POST, 检查CPU, 内存, 主板, 硬盘, 显卡等设备. POST结束后系统BIOS调用其他设备的BIOS对各个设备进行检测和初始化. 如果自检没有出现问题, 将执行启动程序.

Boot

BOOT(靴子), 意为"to load a program into a computer from a disk; to start or ready for use especially by booting a program." BOOTSTRAP(鞋带)

pull oneself up by one’s bootstraps 靠自己自立自强 by one’s own bootstraps 自己努力, 自强

必须先运行程序, 计算机才能启动, 但是计算机不启动就无法运行程序. 这与人没法拽着鞋带把自己拉起来类似. 于是早期工程师们设法先将一小段程序装入内存, 称之为"boot", 意为"自引导程序".

MBR(Master boot record)

BIOS按照设定的启动顺序, 将控制权转移给启动顺序首位的存储设备. BIOS首先寻找他们的MBR, 如果该磁盘的主引导扇区(0柱头, 0磁头, 1扇区, 即前512个字节)最后两字节为0x55和0xaa, BIOS则认为MBR有效, 并将控制权转交给MBR. 如果未找到MBR, BIOS会去启动顺序中下一顺位的设备中寻找. MBR由三部分组成: 启动代码(446字节), 磁盘分区表(16x4字节), 结束标志(0x55, 0xaa 两字节).

Boot Loader

Boot Loader(启动引导程序)用于加载操作系统内核文件. 用户可以用Boot Loader来选择启动不同的操作系统. Windows的Boot Loader是Windows Boot Manager.

操作系统

操作系统内核被载入内存后, 再经过一系列初始化过程完成操作系统的启动.

参考文献

计算机是如何启动的


0x00 分割线

显然我完全没坚持下去。
转眼一年半过去了,已经到了上操作系统实验课的时间。


0x01 实验环境搭建

搭建实验的基本环境,熟悉开发与调试工具

实验目标

• 搭建基本实验环境,熟悉基本开发与调试工具 • 对应章节:第一、二章

本次实验内容

  1. 认真阅读章节资料
  2. 在实验机上安装虚拟运行环境,并安装ubuntu(实验 室机器已安装,若需要可在自己笔记本电脑另行安装)
  3. 安装ubuntu开发环境,32位环境 笔者实体机使用archlinux x86_64
  4. 下载bochs源码,编译并安装bochs环境 qemu+gdb
  5. 使用bochs自带工具bximageqemu-img创建虚拟软驱
  6. 阅读、编译boot.asm,并反汇编阅读
  7. ~~修改bochsrc,~~运行并调试你的第一个程序
  8. 完成实验练习要求 实验要求运行的代码为OrangeS第一章osfs1

实验练习要求

删除0xAA55,观察程序效果,找出原因

会显示No bootable device。 原因具体见0xFF部分的MBR介绍。
test.bin中的代码是作为MBR使用的,没有校验位0x55aa,BIOS会认为该MBR无效,也就不会装载运行其代码。

修改程序中输出为,一个包含自己名字的字符串,调试程序

注意修改字符串后,需要同时修改参数cx:字符串的长度。此处修改为结尾-开头,编译时自动计算长度。

把生成的可执行文件反汇编,看看输出的内容是怎样的,并在虚拟机启动过程,设置断点进行调试,在实验报告中截图

注意此处遇到一个问题:gdb 调试 qemu 程序时,会与 qemu 通信获取架构,且无法用 set arch 指令覆盖。这导致在使用 32 位的 qemu 在实模式下运行 16 位的程序时,gdb 无法 正确识别架构。 解 决 方 法 参 考 How to disassemble 16-bit x86 boot sector code in GDB with “x/i $pc”? It gets treated as 32-bit里面的这篇回答,手动修改tdesc。

为什么要jmp $,如何改造程序,让这个输出过程执行100次

jmp $含义为跳转回当前指令,也就是无限循环。因为这句代码下面没有别的代码了,所以为了防止误将数据当代码执行,要放一个无限循环。

为什么要对段寄存器进行赋值

程序加载后,code段寄存器为0x7c00,而通过赋值段寄存器将data段和extra段寄存器为与cs相同,这样可以寻址到输出的字符串。

如何在该程序中调用系统中断

使用int指令。

0x02 保护模式工作机理