📑

「ゼロからのOS自作入門」の リベンジ Part3 🍊

2021/05/27に公開

https://zenn.dev/omiso/articles/9b33c7b6b997ee
の続き

第3章 画面表示の練習とブートローダ

QEMUモニタでのデバック方法

run_qemu.sh 実行中に、確認することが可能

レジスタの現在値の確認

CPUの各レジスタの現在値を確認する

(qemu) info registers

メモリダンプ

フォーマット

(qemu) x /fmt addr

RIPレジスタのメモリダンプ見る(例)

(qemu) x /4xb 0x03e665416
000000003e665416: 0xeb 0xfe 0x55 0x41
(qemu) x /4xb 0x003e665416
000000003e665416: 0xeb 0xfe 0x55 0x41

逆アセンブルで表示

(qemu) x /2i 0x003e665416
0x000000003e665416:  jmp    0x3e665416
0x000000003e665418:  push   %rbp

jmp命令は、「0x3e665416」に jmp するという命令ですが、この状態だと同じ命令に jmp するということで、while(1) をやっている個所になる

カーネルを作ろう

カーネルのソースコード

// extern C は c言語定義することを意味している
extern "C" void KernelMain() {
	while(1) __asm__("hlt");
}
// __asm__はインラインアセンブラ
// hlt は CPU を停止させる命令

カーネルのビルド

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

-ffreestanding・・・フリースタンディング環境[1]向けのコンパイル
-mno-red-zone・・・Red Zone機能無効

作ったカーネルを動かせるようにする

https://github.com/uchan-nos/mikanos/releases/tag/osbook_day03a
らへんに作ったカーネルファイルを読み込む記述があるソースコードがあるので参照。
※書くのがめんどくさい。

作ったものからデバックしてみる

CPUのレジスタの中身を見てみる

(qemu) info registers
RAX=0000000000000032 RBX=0000000000000064 RCX=000000003fea8828 RDX=00000000eadeadc4
RSI=0000000000000041 RDI=0000000000004000 RBP=000000003fea8850 RSP=000000003fea8810
R8 =000000003fea8828 R9 =000000003fb7b48f R10=000000003fbcd018 R11=fffffffffffffffc
R12=000000003effee20 R13=000000003feac8d0 R14=000000003fea8818 R15=00000000000000c8
★RIP=0000000000101311 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=1

(qemu) x /2i 0x101311
0x0000000000101311:  jmp    0x101310
0x0000000000101313:  int3   
(qemu) x /2i 0x101310
0x0000000000101310:  hlt    
0x0000000000101311:  jmp    0x101310

RIP は、CPUが次に実行する命令を指している

脚注
  1. フリースタンディングはOSがない環境を指す ↩︎

Discussion