OS自作入門 3日目-2 【Linux】| デバッグして実行順序を追ってみる

30日でできる!OS自作入門の3日目は実行される順序が複雑でしたので
デバッグして実行される順序を追ってみます。

 
 
 


使用環境

$ uname -a
Linux ***-E200HA 4.10.0-37-generic #41-Ubuntu SMP Fri Oct 6 20:20:37 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ nasm -version
NASM version 2.13.01
$ qemu-system-i386 --version
QEMU emulator version 2.10.1(Debian 1:2.10+dfsg-0ubuntu13)
$ gcc --version
gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413

 
 
 


デバッグの方法

$ qemu-system-i386 -m 32 -localtime -vga std -fda os.img -gdb tcp::10000 -S &
<略>
gdb

このコマンドでqemuがスタート直後に停止し、gdbが起動します。

-gdbオプションでgdbの接続を待つ
-SオプションはスタートアップでCPUをフリーズさせるオプション

(gdb) target remote localhost:10000

qemuに接続されてデバッグ可能な状態になります。

 
 
 


デバッグして処理を追ってみる

処理を追うのに先立って、前回記事で作ったimgファイルとメモリマップ、
それと処理の順序を図示してみました。
今回の内容に関係のないところは省略しています。

 

 
右側がimgファイルの概略。
左側がメモリの中身のイメージです。

最初メモリ内は空っぽの状態です。

BIOSはimgファイルの先頭512byte(0x0200byte)に格納されている
ipl部分をメモリの0x7c00に読み込みます。

この部分までブレークポイントを張って処理を進めます。

(gdb) b *0x7c00
(gdb) c

  
0x7c00地点をダンプしてみるとipl.binの先頭と一致しているのが分かります。

(gdb) x/16bx $eip
0x7c00: 0xeb    0x4e    0x90    0x48    0x45    0x4c    0x4c    0x4f

  
そして同じくこれを命令としてみると、

(gdb) x/i $eip
=> 0x7c00: jmp 0x7c50

0x7c50地点へのジャンプ命令となっています。
以降のデバッグは単調なので、
図のみで説明していきます。

そして0x7c50以降のipl内の命令によって
最初に1セクタを除く10シリンダ分が0x8200以降へ読み込まれます。

 
 
0xc200へ読み込んだのち、
JMP 0xc200でnasmheadに処理が移ります。

 
 
0xc200地点にはnasmheadが読み込まれているので、
nasmheadに処理が移ります。

nasmheadには0x00280000地点へos部分をコピーする
処理が行われます。

 
 
nasmheadではほかにもいろいろやっているのですが、
3日目の内容では解説がないので、
その時に書きます。
さらにほかにもメモリ上にマップしているところもあるのですが、
今回の動作に影響しないので、それも省略します。

そしてnasmheadの最後のほうに書かれている、
JMP DWORD 2*8:0x0000001b
の部分で 0x0028001b へジャンプします。

なぜこの命令で 0x00280001b にジャンプするのかは
GDTの知識が必要なのでその時に改めて書きます。

そして0x00280000 がどこなのかというと、
hrbヘッダーのど真ん中です。
このヘッダー、実はよくよくみてみると、
ヘッダーにもかかわらず、JMP命令になっているんです。

hrb形式のファイルのヘッダーは以下のようになっています。
+ 0 : stack+.data+heap の大きさ(4KBの倍数)
+ 4 : シグネチャ “Hari”
+ 8 : mmarea の大きさ(4KBの倍数)
+12 : スタック初期値&.data転送先
+16 : .dataのサイズ
+20 : .dataの初期値列の位置
+24 : 0xe9000000
+28 : エントリアドレス-0x20
+32 : heap領域(malloc領域)開始アドレス

そして0x1b(27byte目)以降を見てみると(リトルエディアン)
0xe9 0x00000009
これを逆アセンブルするとhrbファイルの先頭(つまりHariMain関数)
へのジャンプになります。

以降HariMain関数の処理が進められるという流れです。

【関連記事】
OS自作入門 1日目
OS自作入門 2日目
OS自作入門 3日目-1
OS自作入門 4日目
30日でできる!OS自作入門 まとめ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です