みず吉のプログラ日記

開発日記になる予定です。

MacでゼロからのOS自作入門 3-4章

今日やること

3章と4章を終わらせる!

3章

3.3章

カーネルファイルのコンパイルとリンクを行います。

$ OS_DIR=/workspaces/mikanos-devcontainer/mikanos
$ cd $OS_DIR
$ git checkout osbook_day03a
$ cd kernel
$ clang++ -O2 -Wall -g --target=x86_64-elf -ffreestanding -mno-red-zone -fno-exceptions -fno-rtti -std=c++17 -c main.cpp
$ ld.lld --entry KernelMain -z norelro --image-base 0x100000 --static -o kernel.elf main.o

$ cd ~/edk2
$ source edksetup.sh
$ build
$ ~/osbook/devenv/run_qemu.sh ~/edk2/Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi $OS_DIR/kernel/kernel.elf

この最後の一行が

(qemu) gtk initialization failed

のようなエラーのため実行できませんでした。 QEMUを起動できないのが原因ではないかと考えたため、私の場合はPC本体のターミナル上で、0章でやった

$ xhost + 127.0.0.1

をやり直してから最後の一行をやるとできた(気がします)。

(qemu) info registers

qemu上でコマンドを打つと、

RAX=000000003fb766ed RBX=000000003fec8580 RCX=000000003f305118 RDX=0000000000000000
RSI=000000000000001f RDI=000000003fec9cf0 RBP=0000000000000010 RSP=000000003feac878
R8 =000000003feac9c8 R9 =00000000b34a6290 R10=000000003feac7b8 R11=000000003e8aad40
R12=000000003fec88f6 R13=000000003fecc580 R14=000000003f305118 R15=000000003fec85f9
RIP=000000003fb778e1 RFL=00000206 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=1
(省略)

このように文字の羅列が出てきます。これがメモリマップです。

これのRIPの値(人によって異なります)を使って

(qemu) x /2i 0x3fb778e1

のように打つと、

0x~~~~~~ :     jmp

のように表示されるはずなのですが、RIPのメモリ領域内にjmpのアドレスがありませんでした... そのため、カーネルにはall doneが表示されないので無限ループはしてるっぽいのですが無限ループが確認できませんでした。なぜ。後で解決することにします。

3.4章~3.5章

3.4章以降は書いてある通りに実行できました! ちなみに3.4章と3.5章では似たようなことをしていますが、ブートローダカーネルピクセル描画の処理の場所が異なります。 どういうこと...?と思った人は本を読み返すか この記事 にわかりやすくまとめてくださっているので読むとスッキリするかもしれません。

3.6章

エラー処理を追加しようと思ったのですが、もう書かれているようでした。中身が気になる人は以下の手順で確認できます。Main.cの266行目あたりに書かれています。 ちなみにviで行数を表示するには コマンドモードで :set number を入力しましょう。

$ cd $OS_DIR
$ git checkout osbook_day03d
$ cd MikanLoaderPkg
$ vi Main.c 

4章

4.1章

早速makeするところでエラーが出ました。

$ cd $OS_DIR
$ git checkout osbook_day04a
$ cd kernel
$ make

このmakeで以下のようなエラーが出ました。

clang++  -O2 -Wall -g --target=x86_64-elf -ffreestanding -mno-red-zone -fno-exceptions -fno-rtti -std=c++17 -c main.cpp
main.cpp:1:10: fatal error: 'cstdint' file not found
#include <cstdint>
         ^~~~~~~~~
1 error generated.
make: *** [Makefile:20: main.o] Error 1

clangのエラー。ということは私が普段からgccを使っているからcstdintがないのでは... と思ったのでmain.cファイルを開いて一行目を #include から #include <stdint.h> に書き換えました。 ちなみにviのコマンドは xで削除、iで挿入、escキーでコマンドモードに切り替えて、:wq で保存して終了 の順でいけます。 これでmakeしなおしたらmakeもmake cleanもできました! 他のブランチに移動できるようgitにcommitしておきましょう。

$ git add kernel/main.cpp
$ git commit -m "main.cpp"

4.2章

$ cd $OS_DIR
$ git checkout osbook_day04b
$ cd kernel
$ source ~/osbook/devenv/buildenv.sh
$ make
$ cd ~/edk2
$ source edksetup.sh
$ build
$ ~/osbook/devenv/run_qemu.sh ~/edk2/Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi $OS_DIR/kernel/kernel.elf

書いてある通りです。緑色の四角が表示されました。わーい。

f:id:mizkitten:20210807224448p:plain
成功!

4.3章~

実行するには4.2章と同じようにします。問題なく実行できました。 4.3章についてですが、main.cppのPixelWriterクラスで virtual とついているのが仮想関数ですね。 抽象クラスとかに自信がない人はこの機会に復習するといいかもしれません。私もしました...