LoginSignup
1
0

はじめに

こんにちは!
前回、以下の記事で、OSの起動と文字列の表示ができました。
GeminiならOSを作れるはず - その1-

今回は、キーボード入力ができるようにしてみます。

要件

  • Docker で起動する
  • プロンプトを表示する
  • キーボード入力を受け付ける

完成イメージ

とりあえず文字を入力できればOK

スクリーンショット 2024-06-23 22.46.49.png

準備

前回の続きになるので、
GeminiならOSを作れるはず - その1-
をご確認ください。

実装

前回の続きですが、必要ファイルは全て記載しておきます。

Dockerfile

Dockerfile
FROM alpine:latest

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

RUN apk update && apk add nasm qemu-system-x86_64 gcc make libc-dev 

ENV PATH="${PATH}:/usr/bin" 

WORKDIR /root/os

CMD ["qemu-system-x86_64", "-vga", "cirrus", "-vnc", ":0", "-k", "ja", "-drive", "format=raw,file=boot.bin", "-drive", "format=raw,file=floppy.img"]

boot.asm

boot.asm
[bits 16]
[org 0x7c00]

; --- グローバル変数 ---
cursor_x dw 0  ; カーソルX座標
cursor_y dw 0  ; カーソルY座標
input_buffer db 256 dup(0)  ; 入力バッファ
input_buffer_len dw 0  ; 入力バッファの文字数

start:
    ; レジスタの初期化
    xor ax, ax
    mov es, ax

    ; 画面モードの設定 (80x25 テキストモード)
    mov ah, 0x00
    mov al, 0x03
    int 0x10

    ; プロンプトの表示
    call print_prompt

.loop:
    ; キーボード入力処理
    call handle_keyboard

    jmp .loop 

; --- プロンプト表示 ---
print_prompt:
    mov ah, 0x0e    ; ビデオサービス(テレタイプモード)
    mov bx, 0x0007 ; 文字色(白)
    mov bp, prompt_msg ; メッセージのアドレス
.print_prompt_loop:
    mov al, [bp]     ; 文字を取得
    cmp al, 0       ; 文字列の終端であれば終了
    je .print_prompt_end
    int 0x10        ; 文字を表示
    inc bp          ; 次の文字へ
    jmp .print_prompt_loop
.print_prompt_end:
    ret

; --- キーボード入力処理 ---
handle_keyboard:
    mov ah, 0x00    ; キーボード入力待ち
    int 0x16        ; キーボードBIOS割り込み

    ; スキャンコードをASCIIコードに変換
    mov bl, al      ; スキャンコードを bl に保存
    call scancode_to_ascii

    ; --- キー入力処理 ---
    cmp al, 0x0D  ; Enterキー?
    je .handle_enter
    cmp al, 0x08  ; Backspaceキー?
    je .handle_backspace
    jmp .handle_char

.handle_enter:
    ; コマンド実行処理 (ここではプロンプトを再表示するだけ)
    mov word [cursor_x], 0  ; カーソル位置を先頭に
    inc word [cursor_y]      ; 次の行へ
    mov word [input_buffer_len], 0  ; 入力バッファをクリア

    ; カーソル位置を更新
    mov ah, 0x02     ; カーソル位置設定
    mov bh, 0        ; ページ番号 (通常は0)
    mov dh, [cursor_y]  ; 行番号
    mov dl, [cursor_x]  ; 列番号
    int 0x10

    call print_prompt
    jmp .end_input

.handle_backspace:
    ; バッファから最後の文字を削除
    cmp word [input_buffer_len], 0  ; バッファが空なら何もしない
    je .end_input
    dec word [input_buffer_len]
    mov di, input_buffer
    add di, [input_buffer_len]
    mov byte [di], 0  ; バッファの最後を0でクリア

    ; カーソルを左に移動して文字を削除
    mov al, 0x08  ; Backspace
    int 0x10
    mov al, ' '   ; 空白文字
    int 0x10
    mov al, 0x08  ; Backspace
    int 0x10
    jmp .end_input

.handle_char:
    ; 入力バッファに文字を追加
    mov di, input_buffer
    add di, [input_buffer_len]
    mov byte [di], al
    inc word [input_buffer_len]

    ; 画面に文字を表示
    mov ah, 0x0e    ; テレタイプ出力
    mov bx, 0x0007  ; 属性 (白文字、黒背景)
    int 0x10

.end_input:
    ret


; --- スキャンコード - ASCIIコード 変換テーブル ---
scancode_to_ascii:
    ; 一旦そのまま返す
    mov al, bl
    ret

; --- プロンプトメッセージ ---
prompt_msg:
    db 'user@os> ', 0

; --- 残り部分を0で埋める ---
times 510-($-$$) db 0
dw 0xaa55

起動してみる

まずはDockerfileをビルド

docker build -t os-dev .

続いてバイナリ変換コマンドの実行

nasm -f bin boot.asm -o boot.bin

コンテナを起動

docker run -it -p 5900:5900 -v $(pwd):/root/os os-dev

RealVNC Viewer でlocalhost:5900にアクセス

スクリーンショット 2024-06-23 22.43.53.png

OSが起動し、プロンプトが表示されました!
文字を入力して、Enterを押してみます。

スクリーンショット 2024-06-23 22.45.27.png

入力できました!

スクリーンショット 2024-06-23 22.46.49.png

まだ、シェルやファイルシステムが入ってないのでコマンドは反応しません。

次のステップをどうするか、Geminiに相談しながら考えます。

まとめ

今回は、OSを起動し、キーボードからの入力ができるようにしてみました。
私はOS開発の知識が皆無なので、AIの助けが無いと、何もできません。

しかし、AIを活用することで、まずはここまで来れたのです、、そう考えると、凄いですね。

まだまだ準備運動のスタートラインレベルです。
これから少しずつ進めて、OSに軽量なAIを組み込むところまでは行きたいと思います!

みなさんも一緒に頑張りましょう😀

1
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
1
0