「手探りでCUI OS作成に挑む」連載
この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は「手探りでCUI OS作成に挑む」連載目次を御覧下さい。
現象
以下のように表示される
TEST
. DAMMY
≡ 雪印
又は
- HALT
HALT
カーソル
本来は以下の筈
TEST
HALT
プログラム
ブートローダーから以下のプログラムを読み込む。
読み込み自体は問題ないように思う。
[org 0x7E00]
[bits 16]
;********************************************************************************
; システム初期化ブロック
;********************************************************************************
start:
; === セグメントレジスタ初期化 スタック設定===
cli
xor ax, ax
mov ds, ax ; データセグメントは 0 にしておく(test_string などの参照に対応)
mov es, ax
mov si, 0x7E00
mov ax, 0x9000 ; 安全な場所にスタックを置く(0x9000:FFFF = 0x9FFFF)
mov ss, ax
mov sp, 0xFFFE ; FFFEが望ましい(偶数)
sti
mov si, test_string
call print_str
mov si, hlt_msg
call print_str
cli
.loop:
hlt
jmp .loop
print_str:
push ax
push si
mov ah, 0x0E ; BIOSテレタイプ機能
.loop:
lodsb ; 次の文字をALにロード
test al, al ; ヌル文字チェック
jz .done
int 0x10 ; BIOS文字表示
jmp .loop
.done:
pop si
pop ax
ret
halt:
cli
.loop:
hlt
jmp .loop
test_string db 'TEST',0x0D,0x0A,0
hlt_msg db 'HALT',0x0D,0x0A,0
DAMMY db 'DAMMY',0x0D,0x0A,0
; パディング(512バイト×3のコードサイズを保証)
times 512 * 3-($-$$) db 0
ラベルの指定は正しいことを確認
文字列のオフセットを確認
hexdump -C load.bin > loadhexdump.txt
00000030 5e 58 c3 fa f4 eb fd 54 45 53 54 0d 0a 00 48 41 |^X.....TEST...HA|
00000040 4c 54 0d 0a 00 44 41 4d 4d 59 0d 0a 00 00 00 00 |LT...DAMMY......|
T
は0x37
H
は0x3E
から始まる。
逆アセンブル
ndisasm -b16 load.bin > loaddisasm.txt
mov si, test_string → mov si,0x7e37
mov si, hlt_msg → mov si,0x7e3e
ラベルのアドレス指定に問題は無い
変な現象
popa/pushaに変更しても正常に動かない
ax,siのみをpop/pushしても正常に動かないが、
ax,bx,siをpop/pushするか、ax,cx,siをpop/pushもしくはまともに動く。
CXでもBXでもよいことからレジスタそのものの問題ではなく、スタックに起因するものと思われる。
以下は正常に動作する例
print_str:
push ax
push bx
push si
mov ah, 0x0E
.loop:
lodsb
test al, al
jz .done
int 0x10
jmp .loop
.done:
pop si
pop bx
pop ax
ret
halt:
cli
.loop:
hlt
jmp .loop
割り込みが入りスタックがずれた可能性を考え、以下のように割り込みを禁止するも表示は不正なまま。
print_str:
cli
push ax
push si
sti
mov ah, 0x0E
.loop:
lodsb
test al, al
jz .done
int 0x10
jmp .loop
.done:
cli
pop si
pop ax
sti
ret
原因はさっぱり分からない
一旦AX、BX、SIをPUSH/POPしたら動くのでこのまま開発を進める。
何日かして頭が整理されたら改めて調べる。