6.828: Operating System Engineering (9)
ええと以下の命令について
[f000:efe9] 0xfefe9: mov $0x8f,%eax 0x0000efe9 in ?? () (gdb) si [f000:efef] 0xfefef: out %al,$0x70 0x0000efef in ?? () (gdb) si [f000:eff1] 0xfeff1: in $0x71,%al 0x0000eff1 in ?? () (gdb)
色々確認していたのですが、Non Maskable Interrupt によれば
void NMI_enable(void) { outb(0x70, inb(0x70)&0x7F); } void NMI_disable(void) { outb(0x70, inb(0x70)|0x80); }
みたいな usage が例示されてました。
上記は disable にしようとしているのが分かりますが、何故に下 4 bits を立ててるのかが不明。先の NMI なスレッドでも 0x80 で disable にして 0x00 で enable にするような事は微妙てきな記述があったりするんですが、何故に 0x8f なのかは謎のママ。
とりあえずアツくなってるので一旦スルーします。
戻る
直前エントリな命令列を見てると cr0 の PE なフラグを立てて longjmp っぽいソレを実行してますね。BIOS の初期化な部分の中でプロテクトモードに移行したのかな。A20 を云々ってのはそーゆーことなのかどうかは不明ですが、んな訳ゃないでしょ的ソリューションですね。
そのままもう少し続けてみます。
The target architecture is assumed to be i386 => 0xffee1: mov $0x10,%eax 0x000ffee1 in ?? () (gdb) si => 0xffee6: mov %eax,%ds 0x000ffee6 in ?? () (gdb) si => 0xffee8: mov %eax,%es 0x000ffee8 in ?? () (gdb) si => 0xffeea: mov %eax,%ss 0x000ffeea in ?? () (gdb) si => 0xffeec: mov %eax,%fs 0x000ffeec in ?? () (gdb) si => 0xffeee: mov %eax,%gs 0x000ffeee in ?? () (gdb) si => 0xffef0: mov %ecx,%eax 0x000ffef0 in ?? () (gdb) si => 0xffef2: ret 0x000ffef2 in ?? () (gdb) si => 0xf194b: push %ebp 0x000f194b in ?? ()
なんとなくどこかで見たようなセグメントレジスタへの代入なのですがいきなり ret しとるな。しかも適当に si 続けてたらいつの間にか BIOS ROM なアドレスから脱出していたのでびっくり。最初からリトライしてみます。
すると 0xed965 を call してますね。
=> 0xf1957: mov %dl,%al 0x000f1957 in ?? () (gdb) si => 0xf1959: out %al,$0xd 0x000f1959 in ?? () (gdb) si => 0xf195b: out %al,$0xda 0x000f195b in ?? () (gdb) si => 0xf195d: mov $0xc0,%al 0x000f195d in ?? () (gdb) si => 0xf195f: out %al,$0xd6 0x000f195f in ?? () (gdb) si => 0xf1961: mov %dl,%al 0x000f1961 in ?? () (gdb) si => 0xf1963: out %al,$0xd4 0x000f1963 in ?? () (gdb) si => 0xf1965: push $0xf5420 0x000f1965 in ?? () (gdb) si => 0xf196a: push $0xf4f90 0x000f196a in ?? () (gdb) si => 0xf196f: call 0xed965 0x000f196f in ?? ()
なんかふつーに手続きを call しちゃってるカンジです。
=> 0xed965: lea 0x8(%esp),%ecx 0x000ed965 in ?? () (gdb) si => 0xed969: mov 0x4(%esp),%edx 0x000ed969 in ?? () (gdb) si => 0xed96d: mov $0xf7288,%eax 0x000ed96d in ?? () (gdb) si => 0xed972: call 0xed1e0 0x000ed972 in ?? () (gdb) si => 0xed1e0: push %ebp 0x000ed1e0 in ?? ()
これは一体どーゆーことなのだろうか。ここもスルーしちゃってメセジ出力するまでひたすら si してみようかな。てか途中で直前コマンドと同じなら空で Enter タタけば良かったことを思いだしたorz
眠くなってきたので止める
次はどうも 0x7c00 に breakpoint 張って云々とあるな。si の途中だがセット。
(gdb) b *0x7c00 Breakpoint 1 at 0x7c00 (gdb)
で、continue
(gdb) c Continuing. The target architecture is assumed to be i8086 [ 0:7c00] => 0x7c00: cli Breakpoint 1, 0x00007c00 in ?? () (gdb)
どうやって breakpoint を、って一瞬思ったんですが、こうやるのか。で、メモリの中身確認しながら以下の質問に答えられるようになれ、とあるのかな。
- At what point does the processor start executing 32-bit code? What exactly causes the switch from 16- to 32-bit mode?
- What is the last instruction of the boot loader executed, and what is the first instruction of the kernel it just loaded?
- Where is the first instruction of the kernel?
- How does the boot loader decide how many sectors it must read in order to fetch the entire kernel from disk? Where does it find this information?
ちょっとここから先はエントリを改めます。