30天自制操作系统 - 取代软盘,用U盘写入引导扇区

背景

作者是在2006年发布此书的(翻译版是在2012年在中国发售),当时可能还能找到带有软驱的计算机。但是时过境迁,现在已经不存在这种老古董东西了。

简单总结一下学习到第三天的一些更变。

更变

书籍里用的是nask这款作者自制的汇编语言编译器,ReactOS的实模式部分是用nasm写的,还是用nasm改造一下好。

已经有文章阐述如何把简单的代码改为nasm格式,《nask与nasm代码差异》这位朋友写的非常清晰,可以直接用于day02的代码上。

; hello-os
; TAB=4

		ORG		0x7c00			; 

		JMP		SHORT entry
		DB		0x90
		DB		"HELLOIPL"		; 
		DW		512				;
		DB		1				; 
		DW		1				; 
		DB		2				; 
		DW		224				; 
		DW		2880			; 
		DB		0xf0			; 
		DW		9				; 
		DW		18				; 
		DW		2				; 
		DD		0				; 
		DD		2880			; 
		DB		0,0,0x29		;
		DD		0xffffffff		; 
		DB		"HELLO-OS"	; 
		DB		"FAT12"		; 
		TIMES	18 DB 0				; 

; 

entry:
		MOV		AX,0			; 儗僕僗僞弶婜壔
		MOV		SS,AX
		MOV		SP,0x7c00
		MOV		DS,AX
		MOV		ES,AX

		MOV		SI,msg
putloop:
		MOV		AL,[SI]
		ADD		SI,1			; SI偵1傪懌偡
		CMP		AL,0
		JE		fin
		MOV		AH,0x0e			; 
		MOV		BX,15			;
		INT		0x10			; 
		JMP		putloop
fin:
		HLT						;
		JMP		fin				; 

msg:
		DB		0x0a, 0x0a		; 
		DB		"hello, world"
		DB		0x0a			;
		DB		0

		TIMES	0x1fe-($ - $$) DB 0	

		DB		0x55, 0xaa


		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		TIMES	4600 DB 0
		DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
		TIMES	1469432 DB 0

 由于下载的源码是Shift_JIS编码的,懒得转换就直接把注释那部分乱码部分删除了。

nasm helloos.nas

这样就可以在当前目录生成helloos的bin文件。

制作U盘启动盘

估计不少朋友都是在虚拟机上虚拟一个软驱来进行实验。由于我个人不喜欢虚拟机,一般都拿真机实验。没有软驱也不可能买到软盘的这个时代,打算用U盘取代这个实验。

原文作者是把bin生成image后写入软盘,但是我们实际上不用生成image。只要把引导扇区写入U盘就可以了。这里有两种方式:

1. 通过dd工具写入U盘:自己动手写操作系统 将引导程序成功写入优盘启动电脑

这种方式每次写入U盘都要先格式化U盘,不然会报另一个进程正在使用该分区(暂时没有找到原因)。

2. 直接通过CreateFile接口,通过符号链接方式打开磁盘分区:打造操作系统(1.3)如何写入引导扇区

然后WriteFile写入就可以了。

格式化U盘写入image后,有时候想再写入,会提示:“另一个程序正在使用此文件,进程无法访问”,的IO错误。

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第1张图片

这时候用“资源监视器”可以轻松看到谁占用了U盘:

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第2张图片

这里可以看到有时候资源管理器确实会占用着U盘,这时候把explorer.exe结束掉后(此时文件夹浏览以及底部Windows窗体栏会消失),用Alt+Tab切换一下到命令行,执行dd命令把image写入U盘即可,省去每次写入还要格式化的弊端。

无论哪种方式,写完后可以看到U盘的数据实际上已经被破坏,例如原本16GB的U盘现在就只有大小13MB还剩1MB。不用理会,因为引导分区覆盖了文件系统描述符。插入计算机后选择USB引导系统,启动系统即可。

INT 0x13/AH=2h读取数据

以下截取自《30天自制操作系统》:

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第3张图片 INT 0x13 BIOS说明

关于DL的驱动器号,书本上写的是0x00,表示A驱动器。但是实际上我们用的是U盘。所以直接执行day03里的harib00a肯定会输出Load error的失败消息。

在《Windows内核设计思想》25页里恰好有如下内容:

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第4张图片

于是把DL设置从0x80开始尝试读取,就快成功了。

由于插入的U盘应该不会是第一块磁盘,我实验到的是0x82的时候,读取成功了。在想BIOS是否暂时无法读取到非引导的硬盘,后面再来补充这点(2019-03-14)。

INT 0x13/AH=48h获取磁盘信息

最初我参考了这位朋友的信息:汇编--INT 13h功能,里面有记载着0x13/AH=48h的简单用法以及返回buffer的结构解析,还引用了Windows 7调用这个BIOS功能的x86汇编代码,参考价值不小。

在Google里也可以搜索到相关的更加详细的资料:点我跳转

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第5张图片

编码INT 0x13/AH=48h并把关键信息输出到屏幕

找了一下好像BIOS只有输出字符到屏幕的功能,没有类似C语言的printf()可以输出整型的相关调用。于是自己写了一个。

由于不可能真的每次调试的时候都刷入U盘启动计算机去看看输出是否正确,所以编写过程还是比较坎坷的。

  1. 首先我再VS2015上用x86内联汇编尽量靠近16位汇编写了一段关于数字转字符串的函数
  2. 再用DosBox使用MASM 5.0编译出16位汇编程序,在DOS模式下测试并调试
  3. 以上没有问题后,最终才转向MBR引导

在一台内置机械硬盘为500GB,U盘(启动盘)为16GB的笔记本电脑上测试的结果。

30天自制操作系统 - 取代软盘,用U盘写入引导扇区_第6张图片

最开始一直搞错,是因为结构体的偏移老写错,搞到读取到磁盘的大小大的匪夷所思。

源码

  1. 这里把修改后的day03的harib00a的ipl.nas修改了一下保存成ipl-U.nas。里面还保存了ipl.nas作为对比,各位可以参照一下:代码下载点我
  2. INT 0x13/AH=48h测试代码,包括:
    1. x86:VS2015上编写内联汇编实现字节转字符串并输出的代码
    2. DOS:基于上面1在DosBox上用MASM 5.0编写16位汇编代码
    3. MBR:最终跑在笔记本电脑上的MBR代码

你可能感兴趣的:(30天自制操作系统)