上机环境: win10 + 虚拟机VMware
成就:
读取2+18+10个柱面
启动区 将ipl.nas改写为ipl10.nas表示读取10个柱面
将haribote.nas改写为asmhead.nas
增加文件bootpack.c 这里的是正式主函数
又增加了naskfunc.nas 用于保存实现汇编函数库,之后就能在别的文件中调用这里面的函数了

需要文件
!cons_nt.bat
ipl.nas
Makefile


本次制作真正的启动区IPL

ipl.nas文件

; haribote-ipl 纸娃娃系统的的意思
; TAB=4

ORG 0x7c00 ; 指明程序装载地址
;因为内存地址0是用来保存BIOS程序的,所以必须向后延长,所以伟大的开发们就定义了0x7C00

; 以下是记叙标准FAT12格式软盘

JMP entry
DB 0x90
DB "HELLOIPL" ; 启动区名称可以是任意的字符串
DW 512 ; 每个扇区的大小必须是512
DB 1 ; 簇大小必须一个扇区
DW 1 ; FAT起始位置(一般为第一个扇区开始)
DB 2 ; FAT的个数
DW 224 ; 根目录大小
DW 2880 ; 磁盘大小
DB 0xf0 ; 硬盘种类
DW 9 ; FAT长度
DW 18 ; 一个磁道几个扇区
DW 2 ; 磁头数
DD 0 ; 不使用分区,必须是0
DD 2880 ; 重写一次磁盘大小
DB 0,0,0x29 ; 意义不明,固定写法
DD 0xffffffff ; 卷标号码
DB "HELLO-OS " ; 磁盘名称
DB "FAT12 " ; 磁盘格式名称
RESB 18 ; 先空出18个字节

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

; 读一个扇区的程序

MOV AX,0x0820
MOV ES,AX
MOV CH,0 ; 柱面
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2

MOV SI,0 ; 记录失败次数

retry:
MOV AH,0x02 ; AH=0x02 读磁盘
MOV AL,1 ; 读一个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘bios
JNC fin ; 没出错跳转

ADD SI,1
; SI++ 这里SI循环5次后确定真的是失败了,就失败了

CMP SI,5 ; SI与5比较
JAE error ; SI >= 5 出错
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry

; 主函数

fin: ;循环等待
HLT
JMP fin

error:
MOV SI,msg

putloop: ;用于显示字
MOV AL,[SI]
ADD SI,1 ; = SI++;
CMP AL,0
JE fin
MOV AH,0x0e ; 显示一个文字
MOV BX,15 ; 指定字符颜色
INT 0x10 ; 调用显卡BIOS
JMP putloop
msg: ;待打印信息
DB 0x0a, 0x0a ;
DB "load error"
DB 0x0a ;
DB 0

RESB 0x7dfe-$ ; 0x7dfe到0x00填写0x00

DB 0x55, 0xaa

以上已经读了两个扇区了,老板说还要继续读18个扇区,我也是醉了

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

; 读磁盘
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ;柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数
retry:
MOV AH,0x02 ; AH=0x02 : 读磁盘
MOV AL,1 ; 一个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错
ADD SI,1 ; 加到5确认出错
CMP SI,5 ;
JAE error ; SI >= 5
MOV AH,0x00 ;A驱动器
MOV DL,0x00
INT 0x13 ; 重置
JMP retry
next:
MOV AX,ES ; 内存地址后移0x200
ADD AX,0x0020
MOV ES,AX ; ADD ES,0x020
ADD CL,1 ; CL+1
CMP CL,18 ; CL与18比较
JBE readloop ; CL <= 18 ;连续读取18个扇区

fin: ;循环等待
HLT ;
JMP fin ;

以上已经读了20个扇区了,老板说还要继续读10个柱面,我也是醉了

注意开头定义
CYLS EQU 10 ; 相当于C语言中#define CYLS 10

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

; 读磁盘
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ;柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数
retry:
MOV AH,0x02 ; AH=0x02 : 读磁盘
MOV AL,1 ; 一个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错
ADD SI,1 ; 加到5确认出错
CMP SI,5 ;
JAE error ; SI >= 5
MOV AH,0x00 ;A驱动器
MOV DL,0x00
INT 0x13 ; 重置
JMP retry
next:
MOV AX,ES ; 内存地址后移0x200
ADD AX,0x0020
MOV ES,AX ;
ADD CL,1 ; CL+1
CMP CL,18 ;
JBE readloop ; CL <= 18

MOV CL,1
ADD DH,1
CMP DH,2
JB readloop ; DH < 2 跳转readloop
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop ; CH < CYLS 跳转readloop
fin:
HLT ;
JMP fin ;

现在启动区已经差不多了,现在已经可以将10218*512=180KB内容完整写入内存,
运行make install将程序安装到磁盘中


接下来正式开始制作操作系统

这里就是正式的程序内容了
增加haribote.nas文件
; haribote-os
; TAB=4

ORG 0xc200 ; 这个程序装载到内存的位置

MOV AL,0x13 ; VGA显卡调用,320X200X8位彩色
MOV AH,0x00
INT 0x10 ;调用显卡 BIOS
fin:
HLT
JMP fin

然后使用nask工具将上文件转为.sys文件,在保存到磁盘镜像中
生成的img文件中
在0x002600保存haribotesys标识文件名字
在0x004200保存的是文件内容
因此我们在haribote.nas里面
加ORG 0xc200 ;就是0x8000(启动区)+0x4200

这里面Makefile文件也做改动了

TOOLPATH = ../z_tools/
MAKE = $(TOOLPATH)make.exe -r
NASK = $(TOOLPATH)nask.exe
EDIMG = $(TOOLPATH)edimg.exe
IMGTOL = $(TOOLPATH)imgtol.com
COPY = copy
DEL = del

# 镜像制作

default :
$(MAKE) img

# 镜像生成规则

ipl.bin : ipl.nas Makefile
$(NASK) ipl.nas ipl.bin ipl.lst

haribote.sys : haribote.nas Makefile
$(NASK) haribote.nas haribote.sys haribote.lst

haribote.img : ipl.bin haribote.sys Makefile
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
wbinimg src:ipl.bin len:512 from:0 to:0 \
copy from:haribote.sys to:@: \
imgout:haribote.img

# 命令
img :
$(MAKE) haribote.img
run :
$(MAKE) img
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
$(MAKE) -C ../z_tools/qemu

install :
$(MAKE) img
$(IMGTOL) w a: haribote.img

clean :
-$(DEL) ipl.bin
-$(DEL) ipl.lst
-$(DEL) haribote.sys
-$(DEL) haribote.lst

src_only :
$(MAKE) clean
-$(DEL) haribote.img

上面运行后就是一片漆黑,因为只是调用了显卡,但是并没有写如颜色等


然后将文件ipl.nas修改为ipl10.nas表示能读10个柱面了


接下来进行正式的操作系统界面颜色填充
haribote.nas文件

; haribote-os
; TAB=4

; BOOT_INFO有关boot设定define
CYLS EQU 0x0ff0 ; 设定启动区
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 关于颜色数目信息,颜色位数
SCRNX EQU 0x0ff4 ; 分辨率X
SCRNY EQU 0x0ff6 ; 分辨率Y
VRAM EQU 0x0ff8 ; 图像缓冲的开始地址

ORG 0xc200 ; 这个程序将要被转载到内存的什么地方

MOV AL,0x13 ; VGA显卡 320x200x8bit彩色
MOV AH,0x00
INT 0x10

;设定 画面模式
MOV BYTE [VMODE],8
MOV WORD [SCRNX],320
MOV WORD [SCRNY],200
MOV DWORD [VRAM],0x000a0000

; 用BIOS取得键盘上各种LED指示灯的状态

MOV AH,0x02
INT 0x16 ; keyboard BIOS
MOV [LEDS],AL ;将AL(key源)传到LEDS

fin:
HLT
JMP fin

接下来开始导入C语言,尽量用C语言开始写代码
首先将haribote.nas改名为asmhead.nas,同时添加了很多代码,但是在这里老师并为解释,作为以后慢慢理解吧


下面看一下.c文件
void HariMain(void) //主函数 函数名不能错,程序就是从这个函数开始运行的
{
fin:
/* ここにHLTを入れたいのだが、C言語ではHLTが使えない! */
goto fin;
}

C语言如何变成机器语言的呢? 先生成.gas->.nas->->->最后
asmhead和bootpack单纯结合起来生成haribote.sys


接下来写个汇编函数库naskfunc.nas文件

; naskfunc
; TAB=4

[FORMAT "WCOFF"] ; 制作目标文件的模式
[BITS 32] ; 制作32位模式用的机械语言
; 制作目标文件的信息
[FILE "naskfunc.nas"] ; 源文件名信息
GLOBAL _io_hlt ; 程序中包含的函数名
;GLOBAL表示声明 define _表示C语言相链接 io_hlt 函数名
; 以下是实现函数功能

[SECTION .text] ; 目标文件中谢了这些之后在写程序
_io_hlt: ; void io_hlt(void);
HLT
RET ;相当于return

Makefile文件也做了改变

TOOLPATH = ../z_tools/
INCPATH = ../z_tools/haribote/

MAKE = $(TOOLPATH)make.exe -r
NASK = $(TOOLPATH)nask.exe
CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM = $(TOOLPATH)obj2bim.exe
BIM2HRB = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG = $(TOOLPATH)edimg.exe
IMGTOL = $(TOOLPATH)imgtol.com
COPY = copy
DEL = del

#

default :
$(MAKE) img

# 规则

ipl10.bin : ipl10.nas Makefile
$(NASK) ipl10.nas ipl10.bin ipl10.lst

asmhead.bin : asmhead.nas Makefile
$(NASK) asmhead.nas asmhead.bin asmhead.lst

bootpack.gas : bootpack.c Makefile
$(CC1) -o bootpack.gas bootpack.c

bootpack.nas : bootpack.gas Makefile
$(GAS2NASK) bootpack.gas bootpack.nas

bootpack.obj : bootpack.nas Makefile
$(NASK) bootpack.nas bootpack.obj bootpack.lst

naskfunc.obj : naskfunc.nas Makefile
$(NASK) naskfunc.nas naskfunc.obj naskfunc.lst

bootpack.bim : bootpack.obj naskfunc.obj Makefile
$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
bootpack.obj naskfunc.obj
# 3MB+64KB=3136KB

bootpack.hrb : bootpack.bim Makefile
$(BIM2HRB) bootpack.bim bootpack.hrb 0

haribote.sys : asmhead.bin bootpack.hrb Makefile
copy /B asmhead.bin+bootpack.hrb haribote.sys

haribote.img : ipl10.bin haribote.sys Makefile
$(EDIMG) imgin:../z_tools/fdimg0at.tek \
wbinimg src:ipl10.bin len:512 from:0 to:0 \
copy from:haribote.sys to:@: \
imgout:haribote.img

# 命令

img :
$(MAKE) haribote.img

run :
$(MAKE) img
$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin
$(MAKE) -C ../z_tools/qemu

install :
$(MAKE) img
$(IMGTOL) w a: haribote.img

clean :
-$(DEL) *.bin
-$(DEL) *.lst
-$(DEL) *.gas
-$(DEL) *.obj
-$(DEL) bootpack.nas
-$(DEL) bootpack.map
-$(DEL) bootpack.bim
-$(DEL) bootpack.hrb
-$(DEL) haribote.sys

src_only :
$(MAKE) clean
-$(DEL) haribote.img

运行后就是黑屏,不客气