30日でできる!OS自作入門を Linux & GAS で行う (3日目)
さて、めっきり更新が遅くなってしまいましたが、3日目です。
ポイントは
- いかにして32ビットプロテクトモードへ突入するか
- いかにしてCのソースが吐いたバイナリにjmpするか
です。
いかにして32ビットプロテクトモードへ突入するか
32ビットプロテクトモードに飛び、32ビットのコードを動作させるには、ちょっとした準備が必要です。
- 割り込みを禁止しておく
- A20信号線をONにする。
- グローバルディスクリプタテーブルを準備し、CPUに認識させておく
これを行うコードを抜粋すると、以下のようなコードになります:
# stop interrupts from PIC movb $0xff,%al outb %al,$0x21 nop outb %al,$0xa1 # stop to accept interrupt cli # enable A20 signal line call waitkbdout movb $0xd1,%al outb %al,$0x64 call waitkbdout movb $0xdf,%al outb %al,$0x60 call waitkbdout # load discripter table lgdtl (gdtr0) ... ... ... .align 8 gdt0: # null selector. .skip 8,0x00 # 1st GDT. .word 0xffff,0x0000,0x9200,0x00cf # 2nd GDT. .word 0xffff,0x0000,0x9a28,0x0047 # last GDT. .word 0x0000 gdtr0: .word 8*3-1 # Size of Global Descriptor Table .int gdt0 # where is the entry of the gdt?
まず、割り込みの禁止です。PICからCPUへの割り込みを通らないようにし、その上でcli命令を発行してCPUサイドでも割り込みの受付を禁止しています。
次に、キーボードコントローラを叩いてA20信号線をアサートしています。詳細はOS自作本をご覧ください。
最後に、lgdtl命令を使って、グローバルディスクリプタテーブルを読み込んでいます。()がついているので、特定の番地から読み込んでいることが分かります。テーブルの本体は、gdtr0ラベル以下にあります。グローバルディスクリプタテーブルの先頭2バイトはディスクリプタテーブルの大きさで、次の32ビットがテーブル本体のアドレスとなります。
さて、前準備が終わったら、念願のプロテクトモードに突入です!具体的には、以下のような手順を踏む必要があります:
これをコードにして表すと、以下のようになります:
andl $0x7fffffff,%eax movl %cr0,%eax orl $0x01,%eax movl %eax,%cr0 jmp pipelineflash pipelineflash: movw $8,%ax movw %ax,%ds movw %ax,%es movw %ax,%fs movw %ax,%gs movw %ax,%ss
いかにしてC言語のソースファイルから吐き出されたバイナリにジャンプするか
これでプロテクトモードには移行しましたが、実はまだ32bitのコードを読めるようにはなっていません。どうしたら32ビット用のコードを実行できるのでしょうか?実は、あらかじめ準備しておいたグローバルディスクリプタテーブルに用意されているセグメントにジャンプすると、コードセグメントが切り替わり、本格的に32ビットモードに突入することができるのです。コードセグメントを切り替えつつジャンプする、セグメント間ジャンプをGASで記述するには、jmp命令を使用します。ただし、普通のjmp命令(セグメント内のjmp命令)とは文法が異なるので注意です。具体的には、以下のような記述をします:
jmp 飛んだ先で使用するコードセグメント,番地
詳しくは、はじめて読む486―32ビットコンピュータをやさしく語るあたりを読むと詳細に書いてありますので、ぜひそちらを参照してみてください。当然ですが、ジャンプした先には32ビットの実行可能なバイナリがあるひつようがあります。これは、セグメント間ジャンプする前に予め読み込んでおいてください。例としては、以下のようなコードになります:
# Copy bootpack.c code to 0x00280000 movl $bootpack,%esi movl $botpak,%edi movl $512*1024/4,%ecx call memcpy
そんなわけで、本日のソースコードを公開します。3日目ともなると結構な分量なので、こちらから落としてください。それと、誤りなどありましたらご指摘頂けますと、大変うれしいです。そんな感じで今日は終了〜。