「手探りでCUI OS作成に挑む」連載
この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は「手探りでCUI OS作成に挑む」連載目次を御覧下さい。
ソースコード
今回の追加機能
clear
コマンドでの画面クリア
バックスペースで入力文字の削除
動作結果
画面クリア
80文字×25行のテキストモードでは0xB800から線形に2000文字(80×25)分が並んでいる。
2000回ループを回して全て空白で埋め、最後にカーソルを画面左上(0)に移動する。
vga.asm
screen_clear:
pusha
push es
push di
mov ax, 0xB800 ; VRAM開始アドレス
mov es, ax
xor di, di ; ES:DI = 0xB800:0x0000
mov cx, 80*25 ; 全2000文字
mov ah, 0x07 ; 属性(黒背景+灰色文字)
mov al, ' ' ; 空白
.clear_loop:
stosw ; [ES:DI] ← AX
loop .clear_loop
; カーソルの位置を画面左上へ移動させる
mov bx, 0
call update_hardware_cursor
mov word [cursor_pos], 0
pop di
pop es
popa
ret
バックスペースを押すと1文字削除
"C:>"の長さは4文字なので、現在のカーソル位置÷80>4の場合にのみ、削除処理を行う。※ プロンプト「C:>」の部分は消せないように制御しています。
消したい文字は空白で上書きする。
カーソル位置から1を引く。
keyboard.asm
; バックスペースが押された場合の処理(1文字削除)
cmp al, 0x08
je .do_delete_last_char
...省略...
.do_delete_last_char:
cmp cx, 0 ; 入力バッファが空なら無視
je .read_char
dec di ; バッファ位置を1文字戻す
dec cx ; 入力文字数カウントを減らす
call delete_last_char
jmp .read_char
vga.asm
delete_last_char:
pusha
push es
; 現在のカーソル位置を取得
mov ax, [cursor_pos]
push ax ; div bxでAXが破壊される為、一時退避
; カーソル位置がC:\>まで動いたら消さない
; AX ÷ 80 → 行と列を求める
mov bx, 80
xor dx, dx
div bx ; AX = 行番号, DX = 列番号(あまり)
pop ax
; DX = 現在の列位置、プロンプト長(C:\>の長さ=4)以下なら消さない
cmp dx, 4
jbe .done
; カーソル位置を1文字分戻す
dec ax
push ax
; VRAMアドレス計算(1文字2バイト)
mov di, ax
shl di, 1
; VRAMセグメント設定
mov ax, 0xB800
mov es, ax
; 空白と属性を書き込む(属性は0x07=黒背景+灰色文字に調整してください)
mov byte [es:di], ' ' ; 空白文字
mov byte [es:di+1], 0x07 ; 属性
; カーソル位置更新
pop ax
mov [cursor_pos], ax
; ハードウェアカーソル更新
mov bx, ax
call update_hardware_cursor
.done:
pop es
popa
ret