MCFAJ一戦筑波、エントリーしました。悩んでたんだけど。今日がエントリー締
切。今年からエントリフィーが、筑波29000円、富士32000円(MCFAJの会員じゃ
ない場合)なのだ。
出れるうちに出ておこうということで。
マクガイバーのせいで作業が進んでいません。どれもこれもいい話だ。必要以 上に暴力的な場面が出ないのがいいね。
今日はここまで。フェンダーにフレームよけの穴を開けました。

机は7回塗り終了で、まぁなんとか。塗装は終了でここから仕上げの磨きです。

出れるうちに出ておこうということで。
マクガイバーのせいで作業が進んでいません。どれもこれもいい話だ。必要以 上に暴力的な場面が出ないのがいいね。
今日はここまで。フェンダーにフレームよけの穴を開けました。

机は7回塗り終了で、まぁなんとか。塗装は終了でここから仕上げの磨きです。

x86続き。保護モードに移行するのをいろいろ試してみた。
例えば二段階目を0x20000にロード。そのリアルモードのプログラムは
CS,DS,SS=0x2000になるように設定。ここから保護モードに移る。
保護モードのデスクリプタの設定は
struct gdt_config
{
uint32_t base;
uint32_t size;
uint8_t unit;
uint8_t mode;
uint8_t type;
} gdt_config [] = {
{ 0x20000, 0x100, SIZE_UNIT_4KB, CODE_32, CODE_SEGMENT },
{ 0x20000, 0x100, SIZE_UNIT_4KB, CODE_32, DATA_SEGMENT },
{ 0x40000, 0x100, SIZE_UNIT_4KB, CODE_32, STACK_SEGMENT },
};
と、0x20000オフセットしたものに。
lgdtに設定するのはリニアアドレスでないといけないので、0x20000の下駄を。
.section .data
.balign 4
lgdt_arg:
.word 0x1f // 0, Code, Data, Stack.
.long _gdt + 0x20000
このように移行。
lgdt lgdt_arg
movl %cr0, %eax
orl $0x1, %eax
movl %eax, %cr0
// Load CS(0x08) with pipeline flush.
// DATA32 ljmp $0x08, $protect_mode_start
ljmp $0x08, $protect_mode_start
protect_mode_start:
.code32
lgdtは16bitと32bitの二命令がある。それはオペランドの処理の方法で、
16bit命令の場合(このサンプル)、設定したGDTRのベースに0xffffffがANDされ
るかどうかだけ。リアルモードから移行する場合は0xffffffを越えることはあ
りえないので16bit命令でいい。
ljmpは「保護モードのCS」が自動的に更新されているからフェッチできるはず。
オフセットについて。このljmpで先にロードしたGDTの設定(0x08)をCSにロード
して、それに基ずいてアドレスを計算する。設定では0x20000がベースになって
いるので、下駄をはかせる必要はない。
この状態ではまだCSがロードされてないからDビットは16bitモードだ。
DATA32でオペランドサイズプリフィックスをつけた場合、0x66がついてるので
オペランドの解釈を32bitモードだとする。(その変換の寄りどころはCPUによって
自動的に更新されている保護モードのCS)
1af: 66 ea b7 01 00 00 08 ljmpl $0x8,$0x1b7 //DATA32あり
これを32bitとしてオペランドを解釈
つけなかった場合16bitとしてオペランドを解釈。(まだDビットは16bit)
1af: ea b4 01 08 00 ljmp $0x8,$0x1b4
なので、どっちでも同じはず。
そしてその他のセグメントの設定。
movw $0x10, %ax
movw %ax, %ds
// Load SS
#if 1
movw $0x18, %ax
movw %ax, %ss
// Reset stack pointer.
movl $0, %esp
movl $0, %ebp
#else
movw %ax, %ss
// Reset stack pointer.
movl $0xfff0, %esp
#endif
スタックセグメントの設定は、インテルが想定していた設定はベースにスタッ
クの最大アドレスを設定して、ESPは0からはじまってマイナスに伸張するもの。
(上のコードの#if 1)、これだと同じアドレスでもデータセグメントからと
スタックセグメントからでポインタが異なる。
一般には(#if 0)のようにデータセグメントと同じように設定する。
今回、インテルの想定したような使い方を試してみた。普通にpush,popする分
にはいいのだけれど、varargsがだめ。今の状態ではきっちり追うことはできな
いけれど、スタックをがりがりいじるようなところで予想外のことになってい
るのかな...。スタックポインタ、コピーしてアクセスできないんじゃ、いくら
なんでも地獄過ぎだね。
保護モードに移ったテストはVGAにベタ書き込み。リアルモードの内に320x240 16bppに
しておきます。
movl $0x80000,%eax
movl $32000, %ecx
1: movb $5, (%eax)
inc %eax
loop 1b
ここで0x80000になっているのはセグメントが0x20000オフセットされているの
で、本来のV-RAM 0xa0000になる。もう既に気が狂いそうだ。
