bios系统调用_自制操作系统(1)——启动分区

出于兴趣,开始研究自制操作系统,具体的学习路线可以在知乎查一下:“如何自制操作系统”之类的。在被安利了一些书之后兴冲冲跑去图书馆借了川合秀实的《30天自制操作系统》,开始入了这个巨坑

启动分区格式

经过几天的学习,大致明白了一些关键点。首先是系统的入口。操作系统的启动前计算机会先启动BIOS。BIOS会读取磁盘的第一个扇区(前512字节),如果最后两个字节的值是 0x55, 0xAA。那么就认为这个是启动分区(引导分区)。这个时候就会开始运行这个磁盘上的程序。

因为《30天》中作者用的是自制的编译器(这是真的强),并且用了很多他自制的工具。虽然方便但是不利于我们掌握更常见的工具(gcc、nasm等)。所以我打算自己写一个引导程序。很快就踩了无数坑。

首先,这一段引导程序无法用C语言完成,所以用的是汇编,但是需要注意的是不同文件格式的开头要求不同

其次,另一个难处是如何将自己的程序做成镜像运行在虚拟机中,我参考了

自制操作系统:引导扇区的实现 - JollyWing - 博客园​www.cnblogs.com
d07c1e97bfdc33e12a649c4d8396e01b.png

不过很可惜,这篇的作者没有考虑到文件格式的问题(可能他的环境跟我不一样?)。

因为没有理解程序运行的原理,直接照搬(因为比较简单所以偷个懒)了上个链接里的一段程序以为可以跑,折腾了一天才通过对比作者的代码发现了端倪,FAT12格式的开头有一个JMP语句,跳到汇编程序的开头。具体可以参考这篇

FAT和NTFS启动扇区结构​blog.csdn.net

这里贴出代码分享一下

;; BIOS会把512字节的引导扇区加载到 0000:7c00 处,
;; 然后跳转到0000:7c00处,将控制权交给引导代码。
org 07c00h                  ;这一行告诉编译器,我们的代码将被加载到7c00处。

jmp start
DB		0x90
DB		"HELLOIPL"		; 启动扇区名称(8字节)
DW		512				; 每个扇区(sector)大小(必须512字节)
DB		1				; 簇(cluster)大小(必须为1个扇区)
DW		1				; FAT起始位置(一般为第一个扇区)
DB		2				; FAT个数(必须为2)
DW		224				; 根目录大小(一般为224项)
DW		2880			; 该磁盘大小(必须为2880扇区1440*1024/512)
DB		0xf0			; 磁盘类型(必须为0xf0)
DW		9				; FAT的长度(必??9扇区)
DW		18				; 一个磁道(track)有几个扇区(必须为18)
DW		2				; 磁头数(必??2)
DD		0				; 不使用分区,必须是0
DD		2880			; 重写一次磁盘大小
DB		0,0,0x29		; 意义不明(固定)
DD		0xffffffff		; (可能是)卷标号码
DB		"HELLO-OS   "	; 磁盘的名称(必须为11字?,不足填空格)
DB		"FAT12   "		; 磁盘格式名称(必??8字?,不足填空格)

start:
mov ax, cs                  ;将代码段寄存器的值送入AX
mov ds, ax                  ;将数据段的地址置为代码段的地址?
mov es, ax                  ;将附加段的地址置为代码段的地址?
mov sp, 0x7c00
call  DispStr               ;调用显示字符串例程
jmp $                       ;无限循环, $表示当前行编译后的地址

DispStr:
mov ax, BootMessage         ;将字符串首地址传给寄存器ax
mov bp, ax                  ;CPU将用ES:BP来寻址字符串
mov cx, 16                  ;通过CX,CPU知道字符串的长度
mov ax, 01301h              ;AH=13表示13号中断, AL=01H,表示目标字符串仅仅包含字符,属性在BL中包含,移动光标
mov bx, 000ch               ;黑底红字, BL=0CH,高亮
mov dl, 0                   ;dh表示在第几行显示,dl表示第几列显示
int 10h                     ;BIOS的10H中断的13号中断用于显示字符串
ret
BootMessage:    db "Hello, OS world!" ;对NASM来讲,标号和变量的作用一样, db表示define byte
;; $当前行被汇编后的地址,$$表示一个section开始处的地址,本程序只有一个section,所以指0x7c00
times 510-($-$$) db 0           ;填充剩下空间,使生成的二进制恰好为512字节

db 0x55, 0xaa                       ;结束标志,如果发现扇区以0xAA55结束,则BIOS认为它是一个引导扇区,dw表示define word

当然,上面的代码并没有实现跳着到kernel的操作(待补充)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值