「手探りでCUI OS作成に挑む」問題解決篇　文字列表示がうまく行かなかった理由

## 「手探りでCUI OS作成に挑む」連載

この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は[「手探りでCUI OS作成に挑む」連載目次](https://qiita.com/earthen94/items/b5d77f98f0cf85a13346)を御覧下さい。

## 目的
昨日正常に動かずハマった原因がスタックとは関係がなかったようなので、その原因を記録する

## 昨日正常に動かなかったコード
```load.asm
[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


; 0埋め（512バイト×3のコードサイズを保証）
times 512 * 3-($-$$) db 0
```

## 昨日上手く表示されなかった例
![9f4fb34608539b2d55a9b676013a89b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/c59b9fb7-945c-467d-bb32-4617ba2c1a65.png)

```
clear
nasm -f bin boot.asm -o boot.bin
nasm -f bin load.asm -o load.bin

rm testdisk.img
dd if=/dev/zero of=testdisk.img bs=512 count=2880
mkdosfs -F 12 -v testdisk.img

# 第1セクタにブートローダーを書き込み
dd if=boot.bin of=testdisk.img bs=512 seek=0 count=1 conv=notrunc
# 第2〜4セクタに拡張ローダーを書き込み
dd if=load.bin of=testdisk.img bs=512 seek=1 count=3 conv=notrunc

rm boot.bin
rm load.bin

#sudo mkdir /mnt/floppy

# マウント
sudo mount -o loop,fat=12 testdisk.img /mnt/floppy

# ファイル書き込み
echo "Hello FAT12!" | sudo tee /mnt/floppy/test.txt
echo 'Hello FAT12!aaaaa' | sudo tee /mnt/floppy/test2.txt #2komeha singuru
sudo mkdir /mnt/floppy/TEST_DIR

# 書き込み結果確認
ls -l /mnt/floppy

# アンマウント
sudo umount /mnt/floppy

qemu-system-i386 -fda testdisk.img
```

## 今日うまく行った動作手順
ファイル書き込みをやめ、この手順で動作させると正常に動作した
![bc14fe69254f1d34dbde7db3b0fa9e3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/52c15cf9-381f-409c-a849-522124f35743.png)

```
clear
nasm -f bin boot.asm -o boot.bin
nasm -f bin load.asm -o load.bin

rm testdisk.img
dd if=/dev/zero of=testdisk.img bs=512 count=2880
mkdosfs -F 12 -v testdisk.img

# 第1セクタにブートローダーを書き込み
dd if=boot.bin of=testdisk.img bs=512 seek=0 count=1 conv=notrunc
# 第2〜4セクタに拡張ローダーを書き込み
dd if=load.bin of=testdisk.img bs=512 seek=1 count=3 conv=notrunc

# rm boot.bin
# rm load.bin

qemu-system-i386 -fda testdisk.img
```
## バイナリ比較
以下の手順で、動かない場合と動く場合とのイメージをバイナリ比較する。
```
dd if=testdisk.img bs=512 count=4 of=ugokanai.bin
dd if=testdisk.img bs=512 count=4 of=ugoku.bin
diff <(xxd ugokanai.bin) <(xxd ugoku.bin)
```
その結果は以下。
大きな問題が２つあることが分かった。
文字列のあとの終端文字(0)がf0ff ff0fに置き換わっている。これでは終端を判別できずに次の文字列まで表示しようとしてしまう。
改行の0d0aが0dfaに代わっている。

```
ubuntu@ubuntu:~/kaihatsu/test3$ 
diff <(xxd ugokanai.bin) <(xxd ugoku.bin)
37c37
< 00000240: 4c54 0dfa ff44 414d 4d59 0d0a f0ff ff0f  LT...DAMMY......
---
> 00000240: 4c54 0d0a 0044 414d 4d59 0d0a 0000 0000  LT...DAMMY......
```

## 考察
はっきりとした原因は分からないが動作確認用のファイルを書き込んだ時にプログラムの領域が破壊されている。
これから調べていく。

## 余談
筆者は中国で働いており、今週は端午の節句で三連休でした。
南京の方へ遊びにでも行こうかと思っていたのですが、結局バグの調査に3日間使ってしまいました。
有料の自習室で作業することが多いです。風景を貼ります。
![db466469e0e8ac40ca7b1b1a22eb91b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/bdab28f3-df00-49e1-a65d-31b615f29b90.jpeg)