0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CUIOS自作 レジスタの値を表示するデバッグ関数作成

Posted at

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

この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は「手探りでCUI OS作成に挑む」連載目次を御覧下さい。

目的

CUIのOSを開発しています。
全てアセンブリで書いています。
デバッグを便利にする為、画面左上にレジスタの値を表示する機能を実装しました。

ソース

boot.asm
boot.asm
org 0x7C00

start:
    ; セグメント初期化
    xor ax, ax
    mov ds, ax
    mov es, ax

    ; スタック設定
    mov ss, ax
    mov sp, 0x7C00

    ; ディスクから第2セクタ(LBA=1)を 0x8000 に読み込む
    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, 0           ; ドライブ番号(通常フロッピーは 0x00)
    mov bx, 0x7E00      ; 読み込み先アドレス
    int 0x13
    jc disk_error       ; エラー時に無限ループ

    ; 読み込んだコードへジャンプ(第2セクタ)
    jmp 0x0000:0x7E00

disk_error:
    jmp $ ; 無限ループ(エラー時に停止)

times 510-($-$$) db 0
dw 0xAA55
kernel.asm
kernel.asm
org 0x7E00

start:
    ; レジスタ初期化
    xor ax, ax
    mov ds, ax
    mov es, ax
    
    ; スタック設定
    mov ss, ax
    mov sp, 0x7C00
    
    ; 画面クリア
    mov ax, 0x0003
    int 0x10
        
    mov bx, 0xABCD
    mov ax, bx
    call print_ax_hex
    
    cli
    hlt
    ret

%include "debug.asm"
debug.asm
debug.asm
print_ax_hex:
    pusha
    push ds
    push es

    mov dx, ax         ; AXの値を退避(DL=下位, DH=上位)

    ; DI = 0(VRAMオフセット、文字2バイト単位)
    mov di, 0

    ; ES = 0xB800(VRAM)
    mov ax, 0xB800
    mov es, ax

    ; DS = CS(hex_table参照用)
    mov ax, cs
    mov ds, ax

    ; --- DHの上位4bit ---
    mov al, dh
    shr al, 4
    and al, 0x0F
    mov bl, al
    mov bh, 0
    mov al, [hex_table + bx]
    mov [es:di], al
    mov byte [es:di+1], 0xE0
    add di, 2

    ; --- DHの下位4bit ---
    mov al, dh
    and al, 0x0F
    mov bl, al
    mov bh, 0
    mov al, [hex_table + bx]
    mov [es:di], al
    mov byte [es:di+1], 0xE0
    add di, 2

    ; --- DLの上位4bit ---
    mov al, dl
    shr al, 4
    and al, 0x0F
    mov bl, al
    mov bh, 0
    mov al, [hex_table + bx]
    mov [es:di], al
    mov byte [es:di+1], 0xE0
    add di, 2

    ; --- DLの下位4bit ---
    mov al, dl
    and al, 0x0F
    mov bl, al
    mov bh, 0
    mov al, [hex_table + bx]
    mov [es:di], al
    mov byte [es:di+1], 0xE0
    add di, 2

    pop es
    pop ds
    popa
    ret

hex_table:
    db '0123456789ABCDEF'
nasm -f bin boot.asm -o boot.bin
nasm -f bin kernel.asm -o kernel.bin
cat boot.bin kernel.bin > os-image.bin
qemu-system-i386 -fda os-image.bin

使い方

例えばBXの値(0xBCBC)を表示したい場合はAXにその値を入れてprint_ax_hex関数を呼び出します。

    mov bx, 0xABCD
    mov ax, bx
    call print_ax_hex

图片.png

仕組み

AX,BX,CX,DXレジスタの大きさはそれぞれ16ビット
16進数は4ビット毎に0〜Fまでを使って表示するので合計4文字を画面上に表示することになります。
以下のような処理を4回繰り返します。

    ; --- DHの上位4bit ---
    mov al, dh
    shr al, 4
    and al, 0x0F
    mov bl, al
    mov bh, 0
    mov al, [hex_table + bx]
    mov [es:di], al
    mov byte [es:di+1], 0xE0
    add di, 2

例:AX = 0011110011110011として説明します。
まずはDHの値をALに入れます。
9文字目から始まる1111が表示したい値です。

shrを使って右に4ビットずらして表示した値が下位4ビットにくるようにします。
AX = 0000001111001111

この時点でAL=11001111となっており先頭の11が邪魔です。

11001111及び00001111(0x0F)の論理積(AND)を取ることで残し上位4ビットを0にします。
AL=00001111

BLに格納して添字とします。BHは影響しないように0で埋めます。
そしてmov al, [hex_table + bx]のようにすることで、16進数の値に対応した文字がALに入ります。
例えば今回の例ではBL=00001111(10進数の15に相当)
[hex_table + bx]の結果はFとなる。

参考

hex_table:
    db '0123456789ABCDEF'
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?