本文将《自制OS(1) 从计算机结构到汇编程序入门》中的代码进一步改进成汇编代码形式
; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以下的记述用于标准FAT12格式的软盘 JMP 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 " RESB 18 ; 程序核心 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 ; 调用显卡BIOS JMP putloop fin: HLT ; 让CPU停止;等待指令 JMP fin ; 无限循环 msg: DB 0x0a, 0x0a ; 换行2次 DB "hello, world" DB 0x0a ; 换行 DB 0 RESB 0x7dfe-$ ; 填写0x00,直到0x001fe DB 0x55, 0xaa ; 以下是启动区以外部分的输出 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 4600 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 RESB 1469432
ORG指令告诉汇编语言编译器将指令装载到内存中的0x7c00地址
JMP跳转指令,entry标签声明。跳转到的入口地址
MOV指令是赋值的意思。
关于寄存器的相关内容可以参见《寄存器(cpu工作原理)》《寄存器(内存访问)》,这里不再赘述
虽然内存比寄存器的存储能力大很多个数量级,但是CPU访问内存的速度比寄存器慢很多
ADD是加法指令,ADD SI,1等价于SI+=1
CMP是比较指令,通俗点讲就是if语句的一部分
JE是条件跳转指令之一,就是根据结果来判断是否跳转。就JE指令而言,如果比较结果相等,则跳转到指定地址,如果不想等,则顺序执行下一条指令。
于是
CMP AL,0
JE fin
等价于
if(AL==0) {goto fin;}
INT是软件中断指令
电脑里面有个BIOS程序,出厂时就组装在电脑主板上的ROM单元里,电脑厂家在BIOS中预先写入了OS开发人员经常会用到的一些程序,INT就是用来调用这些函数的指令。INT后面是个数字,使用不同的数字可以调用不同的函数
INT 0x10(即16) 表示调用显卡BIOS
HLT是让CPU停止动作的指令,但是不是彻底的停止,而是让CPU进入等待,只要外部条件发生变化,就会醒过来继续执行程序
内存的0号地址,也就是最开始的部分,是BIOS程序用来实现各种不同功能的地方,如果随便使用会发生冲突,另外在内存的0xf0000号地址附近还存放着BIOS程序本身,也不能使用
制作启动区
新建文件ipl.bin,输入下面代码:
; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以下的记述用于标准FAT12格式的软盘 JMP 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 " RESB 18 ; 程序核心 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 ; 调用显卡BIOS JMP putloop fin: HLT ; 让CPU停止;等待指令 JMP fin ; 无限循环 msg: DB 0x0a, 0x0a ; 换行2次 DB "hello, world" DB 0x0a ; 换行 DB 0 RESB 0x7dfe-$ ; 填写0x00,直到0x001fe DB 0x55, 0xaa
增加一个makeimg.bat
..\z_tools\edimg.exe imgin:../z_tools/fdimg0at.tek wbinimg src:ipl.bin len:512 from:0 to:0 imgout:helloos.img
以ipl.bin为基础,制作磁盘映像文件hellos.img的批处理文件
从编译到测试的步骤变得非常简单了,双击!cons,然后依次输入:asm->makeimg->run即可
MakeFile入门
MakeFile是一个非常方面的批处理文件,写法相当的简单。首先生产不带 后缀名的MakeFile文件,编辑内容:
# 文件生成规则 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
ipl.bin : ipl.nas Makefile的意思是要向制作ipl.bin,必须准备好 ipl.nas和Makefile
需要调用make.exe来让MakeFile发挥作用,于是新建一个文件make.bat
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
接着使用!cons打开命令行窗口,输入make -r ipl.bin,这样就启动了make.exe
首先打开MakeFile文件寻找制作ipl.bin的方法,make.exe执行找到的相关命令,顺利生成ipl.bin
接着输入make -r helloos.img,果然还是会启动make.exe,并按照MakeFile指定的方法执行
如果把 helloos.img与ipl.bin都删除,重新执行make -r helloos.img,就会先生成helloos.img,发现ipl.bin文件不见了,重现生成之
修改MakeFile的内容,加入:
img :
../z_tools/make.exe -r helloos.img
这样就可以输入“make img”代替了
完整的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
make clean命令用来删除除了 helloos.img文件以外的所有中间文件
make src_only命令用来把源文件以外的文件全部删除掉
这样就只剩下4个文件即可
ipl.nas 、 make.bat 、!cons_9x.bat 、MakeFile

了解一下
@春熙路
呵呵