目的
VGAの字体はA0000~の領域に格納されている。今回は自作の字体に切り替える前段階として、全字体を一つの字体に入れ替える実験をする。
font.asm
org 0x7C00
start:
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7C00
; ディスクから第2セクタを 0x7E00 に読み込む
mov ah, 0x02 ; INT 13h 2: 読み込み
mov al, 1 ; 読み込むセクタ数 = 1
mov ch, 0 ; シリンダ = 0
mov cl, 2 ; セクタ番号 = 2(1始まり)
mov dh, 0 ; ヘッド = 0
mov dl, 0x80 ; ドライブ番号
mov bx, 0x7E00 ; 読み込み先アドレス
int 0x13
jc disk_error ; エラー時
; 読み込んだコードへ跳ぶ(第2セクタ)
jmp 0x0000:0x7E00
disk_error:
cli
hlt
times 510-($-$$) db 0
dw 0xAA55
mov ax, 0x0003
int 0x10
; プレーン2 (フォント領域) への書き込み準備 ---
mov dx, 0x3C4
mov ax, 0x0402 ; Sequencer Index 2: Plane 2 に書き込み許可
out dx, ax
call delay
mov ax, 0x0704 ; Sequencer Index 4: Sequential Access (Chain4解除)
out dx, ax
call delay
mov dx, 0x3CE
mov ax, 0x0004 ; Graphics Index 4: Read Plane 2
out dx, ax
call delay
mov ax, 0x0005 ; Graphics Index 5: Write Mode 0
out dx, ax
call delay
mov ax, 0x0406 ; Graphics Index 6: Map to 0xA0000 (64KB)
out dx, ax
call delay
; --- ここで256文字全部に豆腐を登録 ---
mov ax, 0xA000
mov es, ax
xor di, di ; ES:DI = A000:0000
mov cx, 256 ; 256文字
.char_loop:
push cx
mov cx, 16 ; 1文字の高さ(16バイト)
.row_loop:
mov byte [es:di], 0xFF ; ■■■■■■■■
inc di
loop .row_loop
add di, 16 ; 残り16バイト飛ばす
pop cx
loop .char_loop
; 空白文字(0x20)だけ0x00を変更(そうしないと下の処理で全画面に豆腐を書き込んでしまう)
mov di, 32 * 32 ; 0x20 * 32バイト
mov cx, 16 ; 1文字分(16行)
.blank_loop:
mov byte [es:di], 0x00
inc di
loop .blank_loop
; 通常のテキストモード表示設定に戻す ---
mov dx, 0x3C4
mov ax, 0x0302 ; Sequencer Index 2: Plane 0,1 に書き込み許可
out dx, ax
call delay
mov ax, 0x0304 ; Sequencer Index 4: Odd/Even モード
out dx, ax
call delay
mov dx, 0x3CE
mov ax, 0x1005 ; Graphics Index 5: Odd/Even モード
out dx, ax
call delay
mov ax, 0x0E06 ; Graphics Index 6: Map to 0xB8000
out dx, ax
call delay
; --- VRAMにASCIIコードを順番に表示(字体の確認に使用) ---
mov ax, 0xB800
mov es, ax
xor di, di ; VRAM先頭
xor cx, cx ; CX = 文字コード 0~255
.next_char:
mov al, cl ; AL = 文字コード(CLに0~255が入る)
mov ah, 0x0E ; 文字色(黄色)
stosw ; ES:[DI] = AX
inc cl ; 次の文字コード
cmp cl, 0 ; CLは256bitなので8bitなので0に戻る
jne .next_char ; CL != 0 なら続行
cli
hlt
delay:
push cx
mov cx, 10000
.dl_loop:
nop
loop .dl_loop
pop cx
ret
times 1024-($-$$) db 0
QEMU
nasm -f bin font.asm -o font.bin
qemu-system-i386 -hda font.bin -boot a -no-reboot
実機
lsblk
sudo dd if=font.bin of=/dev/sdb bs=512 count=2 conv=notrunc