本文将《自制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
了解一下
@春熙路
呵呵