如何写出一个操作系统

想要学习做操作系统其实并不难 也不是那么简单 所以我这里简述 因为需要之前的庞大知识体系

首先准备linux系统 下载bochs这个是用来调试系统并且运行系统 再准备一个80386代码
1.原理
因为系统是通过bios芯片进行检测 初始化各种硬件 比如显示器 硬盘 而且bios不只是一个芯片 显示器对应有他的bios 硬盘也有他的bios 所以不仅仅是一个 然后我们把准备好的代码 512b 放到引导扇区0 我们这里的硬盘有2048个扇区 0号扇区是引导扇区 所以呢 我们要把这个引导扇区0号 装载进去我们的程序
bios会自动加载到物理内存 0x7c00到0x7dff位置 我们这里的代码是实模式运行
2.接下来就可以运行这个操作系统了 属于我们自己的操作系统
这里准备一个测试代码
.code16 ;用来表示代码运行在实模式下 16位
BOOTSEG = 0x7c0
ljmp $BOOTSEG, $go
go:
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw $msg, %bp
movb $0x13, %ah
movb $0x01, %al
movb $2, %bl
movw msg_len, %cx
movb $0, %dh
movb $0, %dl
int $0x10
jmp .;进入cpu死循环 为了防止 机器码组 运行完毕 进入数据组
msg: ; 这里指的是数据组 默认存储到数据段 数据逻辑地址会默认右移4bit 存储ds段
.ascii “hello, world.”
msg_len:
.word . - msg
.org 0x1fe
.word 0xaa55

这个是.s文件 我们需要用as 汇编器 进行汇编代码 然后通过ld 进行连接 这个代码用来简单的显示一个helloworld 字符串
3.逻辑地址和物理地址区别
逻辑地址:指的是我们在内存里面为了方便我们的内存分段 而准备的cs:ip寄存器
物理地址:本来我们的寄存器 16位 但是是逻辑地址通过地址加法器 进行整合成20位 形成物理地址 然后存入对应的物理内存块
4.引导扇区标志
我们的结尾为什么要准备一个字 0xaa55 因为我们的521b 的操作系统内存 通过bios进行的装载内存 如果不是这个标志 那么bios不会进行装载
5.我们的操作系统必须先做一个硬盘镜像 因为linux系统一切皆文件 所以我们的操作系统导入到这个硬盘 然后将这个硬盘的引导扇区导入到bios
6.伪指令和机器码区别
伪指令 在我们的as汇编器 进行汇编时候 并不会产生实际内存 符号常量 后面代表的就是一个伪指令 因为我们的伪指令在运行的时候不会产生机器码 所以在我们的ds段进行伪指令运算时候 不需要加$ 因为没用意义 他本身不会产生实际内存 当有.出现的时候就是伪指令
7.如何产生一个硬盘镜像
dd if=/dev/zero of=…/c.img bs=512 count=2048
dd 是文件拷贝命令,其中:
• if=/dev/zero:表示拷贝的源文件的路径,“/dev/zero” 是一个特殊的文件,可以提供 n 个 0(n 的
值等于 bs 和 count 参数的积);
• of=…/c.img:表示拷贝的目标文件路径。若不存在,则创建该文件;
• bs=512:表示块大小,单位为 B;
• count=2048:表示拷贝的文件的块的数量。
由 bs 和 count 参数可知,硬盘镜像文件的大小为:2048*512B=1MB。硬盘镜像文件制作好后,将可执
行文件 bootsect.bin 拷贝到硬盘镜像文件 c.img(硬盘)的引导扇区的命令如下:
dd if=bootsect.bin of=…/c.img bs=512 seek=0 conv=notrunc
其中:
• seek=0:表示把可执行文件 bootsect.bin 拷贝到硬盘镜像文件 c.img 的引导扇区(扇区号为 0)。
• conv=notrunc:表示不改变目标文件的大小,若没有该选项,则硬盘镜像文件 c.img 的大小会由
1MB 变为可执行文件 bootsect.bin 的大小 512B。
这两条命令也保存在脚本 run_test1.sh 中。
8.配置配置文件
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
ata0-master: type=disk, path=“c.img”
megs: 16
cpu: count=1
boot: disk
其中:
• romimage:指定 bochs 运行过程中使用的 ROM-BIOS 的路径。
• vgaromimage:指定 bochs 运行过程中使用的 VGA 的 ROM-BIOS 的路径。
• ata0-master:指定硬盘镜像文件 c.img 的路径。
• megs:指定物理内存的大小,单位为 MB,本书中的实验使用的 bochs 只有 16MB 物理内存。
• cpu:指定 cpu 的个数,本书中的实验使用的 bochs 只有 1 个 cpu。
• boot:指定启动方式,本书中的实验都是从硬盘启动。
在 test 目录下,启动 bochs 的命令如下:
bochs -q -f bochsrc.bxrc
其中:
• -q:跳过 bochs 启动后的配置界面。
• -f bochsrc.bxrc:指定配置文件的路径。
这条命令保存在脚本 run.sh 中,所以只要在 test 目录下运行该脚本即课
9.汇编和链接
在 test1 目录下,把汇编程序 bootsect.s 汇编成可执行文件 bootsect.o 的命令如下:
as -o bootsect.o bootsect.s
as 是本书中使用的汇编器,其中,-o bootsect.o 表示生成的可执行文件的文件名为 bootsect.o。可执
行文件 bootsect.o 需要经过链接后才能在 cpu 上运行。
在 test1 目录下,把可执行文件 bootsect.o 链接成可执行文件 bootsect.bin 的命令如下:
ld --oformat binary -Ttext=0 -o bootsect.bin bootsect.o
ld 是本书中使用的链接器,其中:
• --oformat binary:表示可执行文件 bootsect.bin 中只包含机器指令和数据;
-Ttext:表示第一条机器码指令的偏移地址 也就是代码组的第几条机器码
总结: 最后如果你想写出一个高级的系统 需要了解内核 还有驱动 需要c和内嵌汇编结合 也就是AT&T标准
下面的结果图:

如何写出一个操作系统