ウォンツテック

そでやまのーと

OS作成

諸悪の根源を突き止めた。
タスクスイッチから帰ってくるljmp命令直後(セグメント間命令によりタスクスイッチし、再び自分にスイッチした時に戻ってくる)にpopをするとその値が壊れている。メモリダンプでその時のesp付近のメモリを丹念に調べてみると完全に正しい(iretするためのeip, cs, eflagsの値とかpushaした時の汎用レジスタの値とかは全て正しい)。ssの値も正しいし、なぜここでpopが正常に動かないのかわからない。。。

調査

見えてきた。
popの値がおかしいというよりljmp後のespの値が一定じゃない。要するにタスクスイッチから帰ってくるべきkernelとPIC割り込みより発生するタスクスイッチ関数とが同じスタック空間を使っているのでタスクが発生するたびにespの値が変わってしまい元のkernelに戻るころには期待しているespの値とは違うものになってしまっている模様。
ってことは割り込みのたびにおかしくなってるespやらebpをきっちり制御すれば正常に動作しそう。

調査

popの値が変なので試しにpushをしてみてそれがメモリ上のどこにあるか調べてみようと思った。
push 0x33333333
push 0x44444444
ってのをやってとりあえずljmp直後のesp値である0x9bfa0付近を調べてみるが無い。全メモリ空間をダンプする機能はqemu&bochsでは(さらっと調べた限りでは)無さそうなのでgrepをするわけにもいかない。
うーん困ったということでssのベースアドレスが0x9c000で今のespが0x9bfa0だから試しにこれらを足したアドレス0x137fa0を見てみたら。。。なんとありましたw 久々に嬉しいw
あともう少し

成功

YEEEEEEEEEEEEEES!
ついにTSSを使ったマルチタスク(kernelとnew process間のswitch)化に成功!
原因は先ほどの通りで対処方としてはとりあえずGDTの0x18(Stack segment用)のbaseaddressを0x0に変更。(後でstackセグメントにおけるリアルメモリ番地の算出方法見直そう)
マルチタスク記念にリビジョンアップ
Sodex svn rev5

次の目標はTSSを使わないタスクスイッチだけどちょっとMinix本やら詳解Linuxカーネルやらの本を読み直して頭を整理しよう。(Linuxカーネル解読室はコードと一緒に解説してあるから中々良さそう)