初めに
今回はOSを立ち上げずアセンブリ言語で画面描画をする。
今回はVRAM(0xA000)へ直接書き込むのではなくBIOSの機能を利用する。
操作
nasm -f bin dot.asm -o dot.bin
qemu-system-i386 -fda dot.bin # CFカードに書き込む前にQEMUで動作を確認
lsblk # 挿したCFカードのパスを調べる
sudo dd if=dot.bin of=/dev/sdb bs=512 count=1 conv=notrunc # CFカードに書き込む(lsblkで確認したパスに合わせる)
実験
コード
dot.asm
org 0x7c00
start:
; ビデオモードに設定 13h (320x200, 256 色)
mov ax, 0x0013
int 0x10
; 初期座標 (x=160, y=100)
mov cx, 160 ; x 座標
mov dx, 100 ; y 座標
main_loop:
; 画素描写
call draw_pixel
; 入力がくるまで待つ
mov ah, 0
int 0x16 ; 入力されたボタンの番号がAHに格納される
; 入力されたボタン毎にそれぞれの処理へ移動
cmp ah, 0x48 ; ↑
je move_up
cmp ah, 0x50 ; ↓
je move_down
cmp ah, 0x4B ; ←
je move_left
cmp ah, 0x4D ; →
je move_right
cmp al, 27 ; ESC
je exit
jmp main_loop
; 押された矢印を元に座標を描画する座標を計算(壁当たり判定付き)
move_up:
cmp dx, 0 ; 一番上に達した場合それ以上上には描画しない
je main_loop
dec dx ; 1減算→1画素上に上がる
jmp main_loop
move_down:
cmp dx, 199 ; 一番下に達した場合それ以上下には描画しない
je main_loop
inc dx ; 1加算→1画素下に下がる
jmp main_loop
move_left:
cmp cx, 0 ; 一番左に達した場合それ以上左には描画しない
je main_loop
dec cx ; 1減算→1画素左に移動
jmp main_loop
move_right:
cmp cx, 319 ; 一番右に達した場合それ以上左には描画しない
je main_loop
inc cx ; 1加算→1画素右に移動
jmp main_loop
draw_pixel:
; AL = 色(例:黄色 0x0E)
; CX = X,DX = Yの位置に指定した色を1画素分描画する
mov al, 0x0E ; 黄色
mov ah, 0x0C ; 機能番号:描画
mov bh, 0x00 ; ページ番号
int 0x10
ret
exit:
cli
hlt
times 510-($-$$) db 0
dw 0xAA55