《30天自制操作系统》第2天

第2天 汇编语言学习与Makefile入门

温馨提示:建议大家使用VS Code编写程序,VS Code的代码提示功能非常好用,能够容错提示,另外还要安装ASM Code Lens扩展,此扩展可以实现汇编代码的高亮。

1.继续开发

再次对helloos.nas中的内容进行修改扩充。

        ORG 0x7c00          ; 指明程序的装载地址

首先是程序的装载地址,先介绍ORG指令吧。在开始执行的时候,它会指定把机器语言指令装载到内存中的哪个地址。没有它,有几个指令就不能被正确地翻译和执行。美元符($)的含义也随之变化,它不再是指输出文件的第几个字符,而是代表将要读入的内存地址。

ORG 0x7c00这段代码表示将程序装载在0x7c00地址中,你是否疑惑0x7c00是怎么来的?这就要说说内存的分布了,下面是一张内存分布图,这张图来自于https://www.cnblogs.com/flashsun/p/11626691.html这篇博客中。

可以看到0x7c00~0x7dff这512KB的空间启动区内容的装载地址,这是规定好的,所以就别问为什么这么规定了。

; 以下的技术用于标准FAT12格式的软盘
	JMP entry
	DB  0x90
	DB  "HELLOIPL"      ; 启动区的名称可以是任意的字符串(8字符)
	DW  512             ; 每个扇区(sector)的大小
	DB  1               ; 簇(cluster)的大小(必须为1个扇区)
	DW  1               ; FAT的起始位置(一般从第一个扇区开始)
	DB  2               ; FAT的个数(必须为2)
	DW  224             ; 根目录的大小(一般设成224项)
	DW  2880            ; 该磁盘的大小(必须是2880扇区)(软盘大小1440KB除以扇区大小512B得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标签所在的位置,其他部分并不需要执行,这些只是一些描述信息,在以后对操作系统的扩展中也基本不会修改(当然可以改改启动区和磁盘的名称,毕竟这取得太随意了)。

; 程序主体
entry:
	MOV AX, 0           ; 初始化寄存器
	MOV SS, AX
	MOV SP, 0x7c00
	MOV DS, AX
	MOV ES, AX

现在到了程序的主体部分了,如注释所示,这段代码就是用来初始化寄存器的。栈指针寄存器设置为0x7c00是准备把0x7c00以前的地址当栈使用,至于为什么把栈段寄存器、数据段寄存器和附加段寄存器设置成0,我就不知道为什么了。

这里简单介绍一下CPU的部分寄存器:

AX累计寄存器AL累计寄存器低位
CX计数寄存器CL计数寄存器低位
DX数据寄存器DL数据寄存器低位
BX基址寄存器BL基址寄存器低位
SP栈指针寄存器AH累计寄存器高位
BP基址指针寄存器CH计数寄存器高位
SI源变址寄存器DH数据寄存器高位
DI目的变址寄存器BH基址寄存器高位
ES附加段寄存器DS数据段寄存器
CS代码段寄存器FS没有名称
SS栈段寄存器GS没有名称

对于这些寄存器没有过多的要求,当看代码时看到这些寄存器名称不会懵就行。另外,除了AL、CL、DL、BL、AH、CH、DH、BH是8位寄存器以外,上面的寄存器都是16位的。

	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            ; 调用显卡BIOS
	JMP putloop

fin:
	HLT                 ; 让CPU停止,等待指令
	JMP fin             ; 无限循环

msg:
	DB  0x0a, 0x0a      ; 2个换行
	DB  "hello, world"
	DB  0x0a            ; 换行
	DB  0

这段代码是用来在屏幕上显示字符的。显示字符的核心代码在putloop中,是INT指令和其他寄存器合作的结果,INT指令是软件中断指令,可以使用BIOS功能。INT 0x10控制的是显示服务(Video Service),如果要显示一个字符,需要将AH赋值为0x0e,AL=要显示的字符,BH=页码(通常为0)、BL=字符颜色,该操作没有返回值。

CMP指令用来进行对比,JE指令表示等于则跳转(jump if equal),如此就可以理解上面的代码,如果AL等于0就跳转到fin(以后有机会会将条件转移指令罗列出来,方便记忆),否则就继续执行。

MOV SI, msg是将msg标签的地址送入SI寄存器中,MOV AL, [SI]是将SI寄存器的地址的内容送入AL中,最后将0送入AL中,通过CMP和JE指令跳转到fin标签,然后不断循环。

	RESB    0x7dfe-$    ; 填写0x00,直到0x7dfe(不包括0x7dfe)
	DB  0x55, 0xaa

这两句代码的意思是,将0x7dfe以前的空白地址都填写0x00,0x7dfe地址的内容为0x55,0x7dff地址的内容为0xaa。这样启动区从0x7c00开始,结束于0x7dff,大小刚好为512KB。

; 以下是启动区以外部分的输出
	DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
	RESB	4600
	DB		0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
	RESB	1469432

这段没有什么好介绍的,就是填充软盘的剩余空间,不填充满的话就等着报错吧。

最后双击运行asm.bat和run.bat,得到如下界面。


2.先制作启动区

首先把helloos..nas的后半部分删掉,就是把启动区以外部分给去掉,并把它重命名为ipl.nas。

然后是asm.bat,修改为:

..\z_tools\nask.exe ipl.nas ipl.bin ipl.lst

ipl.lst中的内容是ipl.nas对应的机器语言。

另外还新增了一个makeimg.bat。它以ipl.bin为基础,制作磁盘镜像文件。其内容如下所示:

..\z_tools\edimg.exe   imgin:../z_tools/fdimg0at.tek   wbinimg src:ipl.bin len:512 from:0 to:0   imgout:helloos.img

最后只要双击!cons_nt.bat,然后在命令行窗口中按顺序输入asm→makeimg→run这3个命令就完成了。

我寻思为什么不把这三个bat文件弄成一个文件,然后双击运行一个文件就完事了,就算出错了命令行里面也会有提示。

得到的界面如下:

界面还是没有什么变化,这学习真的是朴实无华且枯燥。


3.Makefile入门

如下是Makefile中的内容:

default :
	../z_tools/make.exe img

# 文件生成规则

ipl.bin : ipl.nas Makefile
	../z_tools/nask.exe ipl.nas ipl.bin ipl.lst

helloos.img : ipl.bin Makefile
	../z_tools/edimg.exe   imgin:../z_tools/fdimg0at.tek \
		wbinimg src:ipl.bin len:512 from:0 to:0   imgout:helloos.img

asm :
	../z_tools/make.exe -r ipl.bin

img :
	../z_tools/make.exe -r helloos.img

run :
	../z_tools/make.exe img
	copy helloos.img ..\z_tools\qemu\fdimage0.bin
	../z_tools/make.exe -C ../z_tools/qemu

install :
	../z_tools/make.exe img
	../z_tools/imgtol.com w a: helloos.img

clean :
	-del ipl.bin
	-del ipl.lst

src_only :
	../z_tools/make.exe clean
	-del helloos.img

#号表示注释。下一行“ipl.bin: ipl.nas Makefile”的意思是,如果想要只做文件ipl.bin,就先检查一下ipl.nas和Makefile这两个文件是否都准备好了。如果这两个文件都有了,make工具就会自动执行Makefile的下一行。

至于helloos.img,Makefile的写法也是完全一样的。其中的“\”是续行符号,表示这一行太长写不下,跳转到下一行继续写。

另外,要想使用Makefile,要从tolset/z_new_w文件夹中获取一个make.bat文件。

这样一来asm.bat、run.bat、makeimg.bat都用不着了。我还是觉得弄个run.bat,再弄个clean.bat,run.bat双击编译文件然后显示界面,clean.bat双击删除冗余文件,岂不是美滋滋。何必每次都要make一下,享受简单的快乐不好吗?

我也不知道为什么我运行到copy和del的时候总是报错,看别人写的博客好像没这种问题,难道是我电脑出问题了?不过,辛亏我电脑安装了Cygwin,并把它的bin目录添加到了系统变量里,用cp和rm代替了copy和del。但是在bat文件中使用copy和del却不报错。

双击!cons_nt.bat,在命令行中输入make run,按下回车键运行,最后得到如下界面:


第2天的内容就这么结束了。第2天的内容相比第1天要难上不少,需要了解启动盘的运行逻辑,也需要掌握不少额外的知识,但这些知识在以后的学习中必将成为重要的助力。期待你继续看第3天的博客!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建一个完整操作系统是一个复杂而庞大的项目,通常涉及到操作系统内核、驱动程序、系统架构等多个层面,对于30天的时间来说,这是不现实的。然而,如果你对操作系统编程有兴趣,你可以尝试学习和理解操作系统的基本原理,并用一些轻量级的框架或工具如QEMU、Minix等来进行实践。 以下是一个简化的步骤概述: 1. **理论学习**:阅读操作系统相关的书籍,如《深入理解计算机系统》(The Art of Computer Programming, Volume 3),了解进程管理、内存管理、文件系统等基础概念。 2. **选择平台**:决定从用户空间(比如Linux内核的clone() API)还是内核模式(比如使用QEMU模拟)开始,因为内核开发涉及更多底层硬件知识。 3. **编写基本结构**:创建进程控制块(PCB)、内存管理模块,开始实现基本的系统调用接口。 4. **进程管理**:实现进程的创建、调度、同步和通信机制。 5. **内存管理**:设计虚拟内存映射、内存分配和回收算法。 6. **I/O管理**:处理设备驱动程序,实现简单的输入输出操作。 7. **文件系统**:如果要做全功能操作系统,你需要实现一个基本的文件系统,用于存储和读取数据。 8. **构建测试环境**:编写单元测试和系统测试,确保每个部分都能正常工作。 9. **持续学习和改进**:在整个过程中,不断查阅文档、源代码和参考资料,以解决遇到的问题。 记住,这是一个高度概括的过程,实际操作中每一步都需要大量的研究和编码。如果你是初学者,可能需要投入更多时间来学习相关基础知识。关于30天的具体代码示例,由于这个项目的规模和复杂性,这里无法提供详细的代码片段,但你可以通过在线教程和开源项目如MINIX的学习来找到起点。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值