- 指令JC —— “jump if carry”的缩写,意思是如果进位标志(carry flag)是1的话,就跳转
- INT 0x13—— 调用BIOS的0x13号函数,用来进行磁盘读、写,扇区校验(verify),以及寻道(seek)
- AH=0x02;(读盘)AH=0x03;(写盘)AH=0x04;(校验)AH=0x0c;(寻道)
- AL=处理对象的扇区数;(只能同时处理连续的扇区)
- CH=柱面号 &0xff;
- CL=扇区号(0-5位)|(柱面号&0x300)* * 2;
- DH=磁头号;
- DL=驱动器号;
在有多个软盘驱动器的时候,用磁盘驱动器号来指定从哪个驱动器的软盘上读取数据。现在的电脑,基本都只有1个软盘驱动器,指定0号就行了- ES:BX=缓冲地址;(校验及寻道时不使用)
- 返回值:FLACS.CF==0:没有错误,AH==0
FLAGS.CF==1:有错误,错误号码存入AH内(与重置(reset)功能一样)
这里FLAGS.CF表示进位标志,也就是说调用这个函数之后,如果没有错,进位标志就是0;如果有错,进位标志就是1。
AH=0x00,DL=0x00,INT 0x13 这是“系统复位”。它的功能是复位软盘状态,再读一次。
- JNC —— “Jump if not carry”进位标志是0的话就跳转
- JAE —— “Jump if above or equal” 大于或等于时跳转
- JBE——“jump if below or equal” 小于等于则跳转
- JB —— “jump if below” 如果小于的话,就跳转。
- EQU指令—— “equal” 相当于C语言的#define命令,用来声明常数。“CYLS EQU 10”意思是“CYLS = 10”。
软盘的结构:
- 软盘拆开后可以看到,中间有一个8厘米的黑色圆盘,那是一层薄薄的磁性胶片。从外向内,
一圈一圈圆环状的区域,分别称为柱面0,柱面1,……,柱面79。一共有80个柱面。柱面
在英文中是cylinder。 - 磁头是个针状的磁性设备,既可以从软盘正面接触磁盘,也可以从软盘背面接触磁盘。与光盘不同,软盘磁盘是两面都能记录数据的。因此我们有正面和反面两个磁头,分别是磁头0号和磁头1号。
- 扇区在磁盘的这个圆环上,还能记录很多位信息,按照整个圆环为单位读写的话,实在有点多,所以
我们又把这个圆环均等地分成了几份。软盘分为18份,每一份称为一个扇区。一个圆环有18个扇区,分别称为扇区1、扇区2、……扇区18。扇区在英文中是sector,意思是指领域、扇形。
综上所述,1张软盘有80个柱面,2个磁头,18个扇区,且一个扇区有
512字节。所以,一张软盘的容量是:
80
∗
2
∗
18
∗
512
=
1474560
B
y
t
e
=
1440
K
B
80*2*18*512 =1474560Byte = 1440KB
80∗2∗18∗512=1474560Byte=1440KB
含有IPL(Initial ProgramLoader,启动程序装载器)的启动区,位于C0-H0-S1(柱面0,磁头0,扇区1的缩写),下一个扇区是C0-H0-S2。这次我们想要装载的就是这个扇区。
缓冲区地址:是个内存地址,表明我们要把从软盘上读出的数据装载到内存的哪个位置。ES:BX代表ES×16+BX的内存地址,这样如果在ES里代入0xffff,在BX里也代入0xffff,就是1114095(0xffff*16+0xffff)字节,也就是说可以指定1M以内的内存地址了,这里指定指定了ES=0x0820,BX=0,软盘的数据将被装载到内存中0x8200到0x83ff的地方(512字节)。
程序中必须指定段寄存器,如果省略的话,使用“DS:”作为段寄存器,例如:
MOV CX,[1234] => MOV CX,[DS:1234]
MOV AL,[SI] => MOV AL,[DS:SI]
装载下一个512字节的ipl.nas为:
; haribote-ipl
; TAB=4
ORG 0x7c00 ; 指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT12的起始位置(一般从第一个扇区开始)
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 "HARIBOTEOS " ; 磁盘的名称(11字节)
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 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JC error
; 虽然读完了,但是因为没有要做的事情所以睡了
fin:
HLT ; 让CPU停止,等待指令
JMP fin ; 无限循环
error:
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
msg:
DB 0x0a, 0x0a ; 换行2次
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填写0x00,直到 0x7dfe
DB 0x55, 0xaa
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
如果考虑读取过程中出错,重试5次,
- 使用SI记录错误次数,超过5次则显示error
- 每次读取失败都需要复位软盘状态(AH=0x00)
则修改后的ipl.nas为:
; haribote-ipl
; TAB=4
ORG 0x7c00 ; 指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT12的起始位置(一般从第一个扇区开始)
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 "HARIBOTEOS " ; 磁盘的名称(11字节)
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 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC fin ; 没出错的话跳转到fin
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5时,跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
; 虽然读完了,但是因为没有要做的事情所以睡了
fin:
HLT ; 让CPU停止,等待指令
JMP fin ; 无限循环
error:
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
msg:
DB 0x0a, 0x0a ; 换行2次
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填写0x00,直到 0x7dfe
DB 0x55, 0xaa
如果需要读18个扇区,
1、读下一个扇区需要将缓冲地址+512(0x200),这里可以改变段寄存器的大小
2、CL表示扇区号
3、SI为重试次数,所以每次读一个新的扇区需要将SI清0
修改后代码如下:
; haribote-ipl
; TAB=4
ORG 0x7c00 ; 指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT12的起始位置(一般从第一个扇区开始)
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 "HARIBOTEOS " ; 磁盘的名称(11字节)
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 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错的话跳转到fin
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5时,跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX,ES
ADD AX,0x0020 ;下一个扇区在内存中的缓存
MOV ES,AX
ADD CL,1
CMP CL,18
JBE readloop
; 虽然读完了,但是因为没有要做的事情所以睡了
fin:
HLT ; 让CPU停止,等待指令
JMP fin ; 无限循环
error:
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
msg:
DB 0x0a, 0x0a ; 换行2次
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填写0x00,直到 0x7dfe
DB 0x55, 0xaa
读入10个柱面:
1、读完第一个18个扇区后,需要将扇区(CL)从1开始计数,这是因为第一个扇区为启动区;
2、软盘分为上下两个磁头,所以需要将上下两个磁头的数据都读出来(DH)
3、柱面(CH)读取从1~10
代码如下
; haribote-ipl
; TAB=4
CYLS EQU 10
ORG 0x7c00 ; 指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT12的起始位置(一般从第一个扇区开始)
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 "HARIBOTEOS " ; 磁盘的名称(11字节)
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 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错的话跳转到fin
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5时,跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX,ES
ADD AX,0x0020 ;下一个扇区在内存中的缓存
MOV ES,AX
ADD CL,1
CMP CL,18
JBE readloop
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop
; 虽然读完了,但是因为没有要做的事情所以睡了
fin:
HLT ; 让CPU停止,等待指令
JMP fin ; 无限循环
error:
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
msg:
DB 0x0a, 0x0a ; 换行2次
DB "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填写0x00,直到 0x7dfe
DB 0x55, 0xaa
着手开发操作系统
新建文件haribote.nas:
fin:
HLT
JMP fin
用nask编译,输出成hanbote.sys:
haribote.sys : haribote.nas Makefile
$(NASK) haribote.nas haribote.sys haribote.lst
接下来,将这个文件保存到磁盘映像haribote.img里:
#磁盘映像管理工具 edimg.exe,先读入一个空白的磁盘映像文件,然后在开头写入
#ipl.bin的内容,最后将结果输出为名为helloos.img的磁盘映像文件。
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
完整的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
#磁盘映像管理工具 edimg.exe,先读入一个空白的磁盘映像文件,然后在开头写入
#ipl.bin的内容,最后将结果输出为名为helloos.img的磁盘映像文件。
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
使用make img制作镜像文件,使用二进制工具打开haribote.img发现,在0x2600处保存haribote.sys的文件名
在0x4200保存haribote.sys的文件内容:
所以一般向一个空软盘保存文件时,
- 文件名会写在0x002600以后的地方;
- 文件的内容会写在0x004200以后的地方。
这样我们就可以将操作系统本身的内容写到名为haribote.sys中,再将它保存到磁盘映像,然后再从启动区执行haribote.sys。
0x8000 - 0x81FF这512字节是留给(copy)启动区的,要将启动区的内容读到那里。0x7c00 - 0x7DFF(512字节)用于启动区。
那么要怎样才能执行磁盘映像上位于0x004200号地址的程序呢?
程序是从启动区开始,把磁盘上的内容装载到内存0x8000号地址,所以磁盘0x4200处的内容就应该位于内存0x8000+0x4200=0xc200号地址。
这样的话,我们就往haribote.nas里加上ORG 0xc200,然后在ipl.nas处理的最后加上JMP 0xc200这个指令。
haribote.nas
; haribote-os
; TAB=4
ORG 0xc200 ; 指明程序的装载地址
fin:
HLT
JMP fin
ipl.nas
; haribote-ipl
; TAB=4
CYLS EQU 10
ORG 0x7c00 ; 指明程序的装载地址
; 以下这段是标准FAT12格式软盘专用的代码
JMP entry
DB 0x90
DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
DW 512 ; 每个扇区(sector)的大小(必须为512字节)
DB 1 ; 簇(cluster)的大小(必须为1个扇区)
DW 1 ; FAT12的起始位置(一般从第一个扇区开始)
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 "HARIBOTEOS " ; 磁盘的名称(11字节)
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 ; 柱面0
MOV DH,0 ; 磁头0
MOV CL,2 ; 扇区2
readloop:
MOV SI,0 ; 记录失败次数的寄存器
retry:
MOV AH,0x02 ; AH=0x02 : 读盘
MOV AL,1 ; 1个扇区
MOV BX,0
MOV DL,0x00 ; A驱动器
INT 0x13 ; 调用磁盘BIOS
JNC next ; 没出错的话跳转到fin
ADD SI,1 ; 往SI加1
CMP SI,5 ; 比较SI与5
JAE error ; SI >= 5时,跳转到error
MOV AH,0x00
MOV DL,0x00 ; A驱动器
INT 0x13 ; 重置驱动器
JMP retry
next:
MOV AX,ES
ADD AX,0x0020 ;下一个扇区在内存中的缓存
MOV ES,AX
ADD CL,1
CMP CL,18
JBE readloop
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop
; haribote.sys执行
JMP 0xc200
error:
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 "load error"
DB 0x0a ; 换行
DB 0
RESB 0x7dfe-$ ; 填写0x00,直到 0x7dfe
DB 0x55, 0xaa
AH=00/INT 10H 是用来设定显示模式的服务程序,AL 寄存器表示欲设定的模式:
- 0x03:16色字符模式,80 × 25
- 0x12:VGA 图形模式,640 × 480 × 4位彩色模式,独特的4面存储模式
- 0x13:VGA 图形模式,320 × 200 × 8位彩色模式,调色板模式
- 0x6a:扩展VGA 图形模式,800 × 600 × 4位彩色模式,独特的4面存储模式(有的显卡不支持这个模式)
返回值:无
这种画面模式下显卡内存(video RAM)是0xa0000~0xaffff的64KB
键盘I/O中断调用(INT 16H)
格式:MOV AH, 02H INT 16H
功能:检查键盘上各特殊功能键的状态。执行后,各种特殊功能键的状态放入AL寄存器中
如果我们想设置显卡模式为0x13,从BIOS获取键盘状态(所谓键盘状态,是指NumLock是ON还是OFF等这些状态。)
haribote.nas
; haribote-os
; TAB=4
; 有关BOOT_INFO
CYLS EQU 0x0ff0 ; 设定启动区
LEDS EQU 0x0ff1
VMODE EQU 0x0ff2 ; 关于颜色数目的信息。颜色的位数。
SCRNX EQU 0x0ff4 ; 分辨率的X(screen x)
SCRNY EQU 0x0ff6 ; 分辨率的Y(screen y)
VRAM EQU 0x0ff8 ; 图像缓冲区的开始地址
ORG 0xc200 ; 这个程序将要被装载到内存的什么地方呢?
MOV AL,0x13 ; VGA 显卡,320x200x8位彩色
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
fin:
HLT
JMP fin