处理器:Intel Celeron(R) Dual-Core CPU
操作系统:Windows7 专业版 x86
阅读《30天自制操作系统》—川合秀实[2015.03.12 – 03.14],[03.26整理]笔记。
在笔记中将《30天自制操作系统》称为“书”。以膜拜的心情采用光盘中的工具来进行笔记。
工具:../toolset/
如果将计算机的开机设置为从软盘启动,计算机开机会驱动软盘的磁头0读其0柱面1扇区的内容到内存0x7c00~ 0x7dff处,并检查扇区最后两2字节内容,如果为55AAH,则从0x7c00开始执行这段程序。软盘的结构在“书”中“第3天制作真正的IPL”节。
如果将一个好的软盘的磁头0对应的0柱面1扇区内含有一段(让显存)显示“Hello world”的机器指令,且将扇区最后2个字节的内容为55AAH。设置计算机开机时从软盘启动后就能够显示“Hello World”。
通过观察下载给软盘的.img文件,它的大小要跟软盘的大小一样(80* 18 * 512 * 2 = 1474560字节)。
“书”附带的光盘中含有很多有用的工具。采用“书”第一天中的“!cons_nt.bat”和“install.bat”工具。“!cons_nt.bat”打开命令行窗口并将命令行切换到“!cons_nt.bat”所在的目录下,在“!cons_nt.bat”打开的命令行下运行“install.bat”就可以将“helloos.img”文件中的内容下载到连接到电脑上的软盘中。
如果“helloos.img”文件内含有以上描述的“显示Hello World”加“55AAH”的内容,那么就此软盘就可以完成让计算机启动时显示“Hello world”。
helloos.img的内容最终在内存0x7c00~ 0x7dff处,CPU要能够执行这段内容,这段内容得是CPU能够识别的机器指令。所以在helloos.img中的内容就是让CPU驱动显存显示“Hello world”的二进制(与文本文件如“记事本”、“word”中的“10”序列不同)指令。
显示“hello world”的机器指令可以怎么来?
[1] 用二进制编辑器直接敲机器指令。(我不知道机器指令,不会干这事)
[2] 用汇编语言代替机器指令,然后用编译器将汇编程序转换成机器指令。(“书”的作者自己写了一个针对汇编程序的编译器nask.exe)
[3] 采用高级语言如C,再用对应的编译器将其转换成机器指令。(高级语言有的库函数依赖操作系统,如printf;计算机开机工作在实模式下,我手头无16位C语言编译器)
采取方法[2]。
查询到软盘的一个扇区能够容纳512字节的二进制位。那么显示“hello world”的程序可以这样写:
;hellowrold.nas ;tab = 8 ORG 0x7c00 ;让BIOS将这段程序装载到0:0x7c00处 ;可以写用户程序的地方 entry: MOV AX, 0 ;初始化段寄存器,段地址都为0 MOV DS, AX MOV SI,msg putloop: MOV AL,[SI] ;ds:si ADD SI,1 CMP AL,0 JE fin MOV AH,0x0e ;BIOS 10h程序的功能号参数,eh表示显示字符功能 MOV BX,15 ;AH = EH时,BL表字符前景色,AL表要显示的字符 INT 0x10 ;调用BIOS 10h号中断程序 JMP putloop fin: HLT ;省电:让CPU进入休眠状态,当复位信号或者中断来临时, JMP fin ;CPU再执行HLT的下一条指令,或者转去执行中断程序, ;当中断处理完后又执行一次HLT,CPU将再次进入休眠状态 msg: DB 0x0a, 0x0a ;0x0a表示换行 DB "hello, world" DB 0x0a DB 0 RESB 0x7dfe-$ ;从此处填0,直到0x7dfd(org 0x7c00使得这指令的偏移地址从0x7c00开始) DB 0x55, 0xaa ;对应扇区最后2个字节内容 RESB 1474560 + 0x7c00 - $
怀着膜拜“书”作者的心情用“nask.exe helloworld.nas helloos.img”工具得到helloos.img文件,然后打开cmd运行“书”中“install.bat”将helloos.img下载到软盘中。再将软盘插在一个开机以软盘启动的计算机上,得以下结果:
Figure1. 第一扇区的Hello world程序运行结果
在cmd中运行“run.bat”命令,QEMU虚拟机中也显示“hello world”字符串。
在往电脑中插含软盘的软驱的时候,给出格式化软盘的提示,格式化的格式为FAT12。此外,计算机开机读软盘的程序是BIOS的13h程序,此程序读取的磁头0对应的0柱面1扇区需要按照指定格式书写,这部分内容笔记在“软盘启动区格式”。除启动区外,另外两个地方也有固定的内容,见“软盘启动区外的内容”。
从表格中可以看出,软盘第一扇区(0磁头)从偏移62处开始的448字节可以写用户程序,其它区域的内容都已经固定,只有按照这样的格式内容,系统BIOS才能正确的读取这个扇区的内容到内存0x7c00~ 0xfdff中。
;hellowrold.nas ;tab = 8 ORG 0x7c00 ;让BIOS将这段程序装载到0:0x7c00处 ;FAT12格式软盘第一个扇区前61字节内容 JMP entry 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扇区) DB 0xf0 ;磁盘的种类(必须是0xf0) DW 9 ;FAT的长度(必须是9扇区) DW 18 ;1个磁道(track)有几个扇区(必?是18) DW 2 ;磁头个数(必是2) DD 0 ;不使用分区,必是0 DD 2880 ;重写一次磁盘的大小 DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS " ;磁盘的名称(11字节) DB "FAT12 " ;磁盘的格式名称(8字节) RESB 18 ;空出18字节 ;可以写用户程序的地方 entry: MOV AX, 0 ;初始化段寄存器,段地址都为0 MOV DS, AX MOV SI,msg putloop: MOV AL,[SI] ;ds:si ADD SI,1 CMP AL,0 JE fin MOV AH,0x0e ;BIOS 10h程序的功能号参数,eh表示显示字符功能, MOV BX,15 ;AH = EH时,BL表字符前景色,AL表要显示的字符 INT 0x10 ;调用BIOS 10h号中断程序 JMP putloop fin: HLT ;省电:让CPU进入休眠状态,当复位信号或者中断来临时, JMP fin ;CPU再执行HLT的下一条指令,或者转去执行中断程序, ;当中断处理完后又执行一次HLT,CPU将再次进入休眠状态 msg: DB 0x0a, 0x0a ;0x0a表示换行 DB "hello, world" DB 0x0a DB 0 RESB 0x7dfe-$ ;从此处填0,直到0x7dfd(org 0x7c00使得这指令的偏移地址从0x7c00开始) DB 0x55, 0xaa ;对应扇区最后2个字节内容 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB RESB 0x1400 + 0x7c00 - $ DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1474560 + 0x7c00 - $再编译helloworld.nas输出helloos.img使用run.bat命令将helloos.img加载到QEMU中,可以显示Hello world字样。再使用“install.bat”命令将helloos.img下载到软盘中。将软盘插到电脑上,开机选择从软盘启动,软盘咔擦几声响后,CPU执行HLT指令,在屏幕上留下以下结果:
[1] 软盘的“偏移”、“扇区”、“柱面”等格式都是逻辑层面的规定,了解BIOS13h程序的参数与软盘格式的对应关系,可参考“书”中第3天“制作真正IPL”章节
[2] 0x7c00、启动区格式(除0x55aa)等规定非必须
[3][ 实模式]内存地址空间分布 CPU合成内存地址的方式 程序中段的加载
计算机开机选择从软盘启动的设置
BIOS在调用int19h之前会让用户选择进入启动菜单界面(此台电脑是按esc键进入)。按F10就可以进行BIOS设置:System Configuration >> Boot Options >> Floppy Boot(Enable);System Configuration >> Boot Options >> Boot Order >> 将USB Floppy置顶。
再按F10“保存”设置退出,计算机将重新启动。按esc键后,再按F9键,选择从检测到(如果电脑上连接了软驱,软驱内含软盘)的软盘(USB Floppy)启动(回车),计算机就会去读软盘的第一个扇区到内存。
(不同的计算机选择从软盘启动的过程可能会不一样。)[X86OS] Note Over.
[2015.04.01]