点阵游戏
前两天心血来潮,在 Loader 里加入了中文支持:我在实模式下将系统切换到图形模式,基于 16*16 的 HZK16 点阵字库循环写像素点,还是挺好玩的。

核心的代码如下,nasm 编译:
;
; WriteGraphicsPixel()
;
WriteGraphicsPixel:
;
; 计算像素点所在的页及偏移量
;
pusha
mov bp, sp
shr bx, 0x03
mov cx, SCAN_LENGTH
mul cx
add ax, bx
mov di, ax
;
; 写映象屏蔽寄存器,使四个位面全部可写
;
mov dx, SEQUENCE_CTRL
mov al, 0x02
out dx, al
mov dx, SEQUENCE_DATA
mov al, 0x0f
out dx, al
;
; 写图形控制器的模式寄存器,选择写方式2
;
mov dx, GRAPHICS_CTRL
mov al, 0x05
out dx, al
mov dx, GRAPHICS_DATA
mov al, 0x02
out dx, al
;
; 写图形控制器的位屏蔽寄存器,计算屏蔽码
;
mov dx, GRAPHICS_CTRL
mov al, 0x08
out dx, al
mov cx, [bp+0x08]
and cl, 0x07
mov al, 0x80
shr al, cl
mov dx, GRAPHICS_DATA
out dx, al
;
; 操作图形模式下的显卡缓存首地址
; 写操作之前先进行一次读操作,使得屏蔽码装入锁存器
;
mov ax, VGA_SEGMENT
mov es, ax
mov ax, [bp+0x0c]
mov ah, byte [es:di]
mov byte [es:di], al
popa
ret
汉字的中文编码表为:
; ==================================================== ;
; .: keenjoy95 2009 :. ;
; .: keenjoy95_at_gmail_dot_com :. ;
; ==================================================== ;
;
; 待显示中文个数
;
CHINESE_UNIT equ 0x0f
;
; 待显示中文颜色
;
CHINESE_COLR equ 0x0e
;
; 待显示中文间距
;
SPACING_UNIT equ 0x0014
;
; 待显示中文编码
;
CHINESE_CODE:
dw 0x0200, 0x0200, 0x0208, 0x03FC, 0x0200, 0x0210, 0x3FF8, 0x2010
dw 0x2010, 0x2010, 0x3FF0, 0x0000, 0x2910, 0x24C8, 0x4444, 0x8004
dw 0x0080, 0x7884, 0x4FFE, 0x5080, 0x50A0, 0x6120, 0x5128, 0x4BFC
dw 0x4820, 0x4820, 0x6824, 0x57FE, 0x4020, 0x4020, 0x4020, 0x4020
dw 0x0210, 0x4114, 0x201E, 0x2FE0, 0x8240, 0x623E, 0x2384, 0x0288
dw 0x1288, 0x22FE, 0xE288, 0x2488, 0x2488, 0x2888, 0x31A8, 0x2010
dw 0x0040, 0x0050, 0x7E48, 0x0240, 0x43FE, 0x2440, 0x1444, 0x1444
dw 0x0848, 0x1448, 0x1250, 0x2220, 0x4060, 0x8092, 0x010A, 0x0206
dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFE
dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFE
dw 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
dw 0x0200, 0x0104, 0xFFFE, 0x0000, 0x1FF0, 0x1010, 0x1010, 0x1FF0
dw 0x0004, 0x7FFE, 0x4004, 0x4FE4, 0x4824, 0x4824, 0x4FE4, 0x400C
dw 0x0020, 0x2020, 0x1124, 0x1124, 0xFD24, 0x01FC, 0x4800, 0x4BFE
dw 0x4844, 0x49FE, 0x4954, 0x1154, 0x1D54, 0xE154, 0x4104, 0x010C
dw 0x4004, 0x27FE, 0x2444, 0x0444, 0x05F4, 0xE444, 0x2454, 0x27FC
dw 0x2404, 0x25F4, 0x2514, 0x2D14, 0x35F4, 0x2504, 0x0814, 0x1008
dw 0x0020, 0x4028, 0x2024, 0x2020, 0x0FFE, 0x0020, 0xE020, 0x27E0
dw 0x2120, 0x2110, 0x2110, 0x2110, 0x29D2, 0x3712, 0x220A, 0x0004
dw 0x2008, 0x13FC, 0x1208, 0x0208, 0xFE08, 0x0A08, 0x1208, 0x3BF8
dw 0x56A8, 0x90A0, 0x10A0, 0x1120, 0x1122, 0x1222, 0x141E, 0x1800
dw 0x0900, 0x0900, 0x13FC, 0x1204, 0x3448, 0x5940, 0x9150, 0x124C
dw 0x1444, 0x1140, 0x1080, 0x0200, 0x5184, 0x5092, 0x9012, 0x0FF0
dw 0x1080, 0x1080, 0x1080, 0x1088, 0x5BFC, 0x5488, 0x5088, 0x9088
dw 0x1088, 0x1FFE, 0x1080, 0x1140, 0x1120, 0x1210, 0x140E, 0x1804
dw 0x0020, 0x00F0, 0x1F00, 0x1000, 0x1100, 0x1100, 0x2104, 0x7FFE
dw 0x0100, 0x0100, 0x0920, 0x0910, 0x1108, 0x210C, 0x4504, 0x0200
dw 0x0000, 0x0180, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x0180
dw 0x0180, 0x0180, 0x0000, 0x0180, 0x03C0, 0x0180, 0x0000, 0x0000
在用 Bochs 调试上述代码的时候,我们可以清楚的看到每个字的产生过程 —— 调试真的非常有趣:

我把 BIN 文件放出来,在 这里 可以下载 (boot.img 是一个软盘镜像文件) 。
您可以选择用 Bochs 启动 / 调试,也可以用 VMWare 等虚拟机选择从软盘镜像启动系统。
WANGyu aka keenjoy95