GeminiならOSを作れるはず - その１-

# はじめに
以前、[簡易的なOSを作ってみる（未解決）](https://qiita.com/yam_dev/items/3ef93c61f9a52e0e6828)でOS作りに挑戦し、失敗。

しかし、Gemini 1.5 Pro なら作れるのではないかと思い、再挑戦です。
2024年6月、 Claude 3.5 Sonnet が話題になってますが、あえて Gemini を使います。

# 要件
- Docker で起動する
- 画面に「Hello, World!」と表示する

# 準備

1. ターミナル:  Dockerコマンドを使います
2. エディタ: VSCodeなど
3. Docker: OSを起動させる仮想環境として使います
4. VNCクライアント: 後ほど、Docker上で起動したOSの画面を表示するために使用
今回は[RealVNC Viewer](https://www.realvnc.com/en/connect/download/viewer/)

![スクリーンショット 2024-06-22 16.14.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/407b15ae-c44f-dc9b-7c79-b2b467d7cb64.png)

以下、Dockerfile、ブートセクタ、その他もろもろ、Gemini 1.5 Pro に質問しながら進めました。

# 実装
### Docker環境構築

まずは、プロジェクト用のディレクトリを作成。
```bash
mkdir my-os
cd my-os
```

**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 ["/bin/sh"]
```

* **Dockerfileの内容**
  * `FROM alpine:latest`:  OS開発の土台となる、軽量なAlpine Linuxのイメージを取得
  * `RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories`: Alpine Linuxのミラーサイトを、より安定したものに変更
  * `RUN apk update && apk add nasm qemu-system-x86_64 gcc make libc-dev`: OS開発に必要なツール(nasm, qemu-system-x86_64, gccなど)をインストール
  * `ENV PATH="${PATH}:/usr/bin"`:  qemu-system-x86_64コマンドを実行できるように、パスを通す
  * `WORKDIR /root/os`: Dockerコンテナ内の`/root/os`を作業ディレクトリに設定
  * `CMD ["/bin/sh"]`: コンテナ起動時に`/bin/sh`を実行

3. **Dockerイメージのビルド**

コマンドプロンプトまたはターミナルを開き、以下のコマンドを実行

   ```bash
   docker build -t os-dev . 
   ```


エラーが無ければ、これで、OS開発用Dockerの準備が完了です。

---

### ブートセクタ作成

次に、OSが起動した時に一番最初に読み込まれるプログラム「ブートセクタ」を作ります。

```assembly:boot.asm
[bits 16]
[org 0x7c00]

start:
    mov ah, 0x0e ; ビデオサービス(テレタイプモード)
    mov bx, 0x0007 ; 文字色(白)
    mov bp, msg ; メッセージのアドレス
       
.loop:
    mov al, [bp]
    cmp al, 0
    je .end
    int 0x10 ; ビデオサービス割り込み
    inc bp
    jmp .loop
       
.end:
   jmp $ ; 無限ループ

msg:
   db 'Hello, World!', 0

times 510-($-$$) db 0 ; 510バイト目まで0で埋める
dw 0xaa55           ; ブートセクタのマジックナンバー
```
バイナリに変換する際も、コメントはそのままで大丈夫でした。

* **コードの説明**
     * `[bits 16]`: 16ビットモードで動作することを指定します。
     * `[org 0x7c00]`: プログラムをメモリ上の0x7c00番地に配置することを指定します。
     * `start:`: プログラムの開始位置です。
     * `mov ah, 0x0e`:  ビデオサービス(テレタイプモード)を指定します。
     * `mov bx, 0x0007`: 文字色を白に設定します。
     * `mov bp, msg`: メッセージのアドレスを`bp`レジスタに格納します。
     * `.loop:`: 文字列の表示ループです。
     * `mov al, [bp]`: 表示する文字を`al`レジスタに取得します。
     * `cmp al, 0`: 文字がnull(終端)かどうか判定します。
     * `je .end`: nullの場合はループを終了します。
     * `int 0x10`: ビデオサービス割り込みを実行します。
     * `inc bp`: 次の文字へポインタを進めます。
     * `jmp .loop`: ループの先頭へジャンプします。
     * `.end:`: ループ終了位置です。
     * `jmp $`: 無限ループです。
     * `msg:`: 表示するメッセージを定義します。
     * `times 510-($-$$) db 0`: 510バイト目まで0で埋めます。
     * `dw 0xaa55`: ブートセクタのマジックナンバーです。

これで、OSの心臓部であるブートセクタの作成が完了。

---

### ステップ３：バイナリ変換

作成した「boot.asm」を、コンピュータが理解できる言葉(機械語)に変換します。

1. **バイナリ変換コマンドの実行**

   コマンドプロンプトまたはターミナルで、以下のコマンドを実行します。

   ```bash
   nasm -f bin boot.asm -o boot.bin
   ```
   * **コマンドの説明**
   `nasm -f bin boot.asm -o boot.bin`:  `boot.asm` をバイナリファイル(`boot.bin`)に変換します。

これで、OSを実行する準備が整いました。

---

### ステップ４：Docker上で実行

いよいよ、作成したOSをDocker上で実行します！

1. **Dockerコンテナの起動**

   コマンドプロンプトまたはターミナルで、以下のコマンドを実行します。

   ```bash
   docker run -it -p 5900:5900 -v $(pwd):/root/os os-dev qemu-system-x86_64 -vnc :0 -fda boot.bin 
   ```
    実行結果
    ```bash
    $ docker run -it -p 5900:5900 -v $(pwd):/root/os os-dev qemu-system-x86_64 -vnc :0 -fda boot.bin 
    WARNING: Image format was not specified for 'boot.bin' and probing guessed raw.
    Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
    Specify the 'raw' format explicitly to remove the restrictions.
    ```
    WARNINGが出てますが、とりあえず大丈夫そうですね。
    
   * **コマンドの説明**
     * `docker run -it -p 5900:5900 -v $(pwd):/root/os os-dev`: ステップ1で作成した「os-dev」イメージを使って、Dockerコンテナを起動します。 `-v $(pwd):/root/os` は、カレントディレクトリ(ここでは「my-os」フォルダ)を、Dockerコンテナ内の`/root/os`にマウントします。 `-p 5900:5900` で、Dockerホストとコンテナ間でポートフォワーディングを設定します。
     * `qemu-system-x86_64 -vnc :0 -fda boot.bin`:  QEMUを使って、`boot.bin`を実行します。`-vnc :0`オプションでVNCサーバーを起動します。



2. **VNCクライアントで接続**
    
    インストールしたVNCクライアントを起動し、 "127.0.0.1:5900" に接続します。

   うまくいけば、VNCクライアント上の黒い画面に「Hello, World!」と表示されます。

   ![スクリーンショット 2024-06-23 9.58.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407770/c101a06f-4ec3-61ab-2e6f-19dee78a5073.png)

---

ついに、、、OSが起動しました 🎉🎉
途中、何度かエラーがあったのですが、それも解決してもらいました。
さすがGemi兄さんですね！

# まとめ
今回は、Geminiの協力を得て、簡易的なOSを起動してみました。
まだ文字列を表示させただけのものですが、これから徐々に、進化させて行こうと思います。

AIを活用することで、自分が未経験の分野にもチャレンジすることができます。

みなさんも一緒にがんばりましょう！