起動するまでの長い道のり IPL編(10) qemuモニタリングの巻
カーネルが一括ビルドできるようになった。これで変更を加えてもコマンド一発で最新版が作れる。
だけど、デバッグはどうするのだろうか。文字表示はできるけど、まだ数字やレジスタの値を表示させることはできない。暴走したか単に無限ループで止まっているのかも分からない。
今回は、qemu実行中にマシンの状態をモニタする方法についてやろうと思う。
コンソール画面に行く
前回までに書き上げたカーネルを実行すると以下のような表示になると思う。
この時にウィンドウをクリックし、カーソルが消えた状態にしてCTRL+ALT+2(数字の2)キーを押下すると、下記のようなコンソール画面に行ける。
コンソール画面ではスクリーンキャプチャやレジスタ内容のダンプ・実行状態の記憶など色々なことが行える。
元のOS画面に戻るにはCTRL+ALT+1を押下する。カーソルを再び表示させるにはCTRL+ALTを押す。
レジスタの内容を表示させる
先述の方法でコンソール画面に行く。そこで「info registers」と打ち込んでEnterするとレジスタの内容が一覧表示される。
色々あってよく分からないだろう。私も分からない。でも最初のEAX・EBX等と表示されている部分くらいは分かるはずだ。これがアセンブラで色々操作したAX・BX等のレジスタの現在の値なのだ。(以前に説明したとおり、EAX・AX・AH・ALは全部重なっている)
先頭からEIPまでの9つのレジスタは説明しなくても分かると思う。ESPはスタック・ポインタでEIPはプログラム・カウンタだ。EIPはモニタ時にやや重要になってくる。これは今まさに実行しているコードの位置を指しているからだ。
EFLはEFLAGSの値で、すぐ右のブラケットに囲まれた部分にどのフラグが立っているか表示される。
その後のES・CS・SSなどはセグメント・レジスタの値だ。今はSSに0x0100が入っていて、アドレス0x1000がスタックボトムになっていることが分かる。DS・CSは0のままだ。
後半は浮動小数点レジスタとかMMX・XMMSレジスタが色々ずらずら並んでいる。GDTとIDT・CRレジスタに関しては今後見る機会があると思う。今はまだ使わない。
メモリの内容を表示させる
コンソール画面で「xp /16xb 0x1000」と打ち込むと、メモリの0x1000番地から16バイト分のデータが表示される。
「/16xb」の16は表示するデータの数で、xは表示フォーマット、bはデータ一つ当たりのサイズを表す。0x1000はもちろんアドレスだ。表示フォーマットにはx(16進数)のほかにd(符号付10進数)やu(符号なし10進数)・o(8進数)・c(文字)・i(アセンブラ命令)がある。サイズ指定にはb(バイト)、h(2バイト)、w(4バイト)、g(8バイト)がある。
アドレスの部分にはレジスタを指定することもできる。例えば「$eip」とすると、EIPレジスタの指すアドレスから指定フォーマットでデータが表示される。
実行中のコードを表示させる
先ほど少し説明したが、メモリ内容の表示でフォーマットにiを指定すると、バイト列がアセンブラ命令に変換されて表示される。
上記画面では、アドレス0x1200で無限ループに入っていることが確かめられる。表示はGNU asのアセンブラとは少し違うので注意。でも大体は分かると思う。
計算結果を表示させる
コンソール画面でprint(またはp)コマンドを使うと、レジスタや数字を組み合わせた数式を計算させ、表示させることができる。
たとえば「print /x $cs * 16 + $eip」と打ち込むと、実行中のコードの物理アドレスが分かる。10進数で表示したい場合はフォーマットを/dと指定する。xpコマンドと同じフォーマット指定が使える。
次回予告
いよいよリアルモードを脱してプロテクトモードに移行する。そのために必要となる各種データ構造について説明する。