GDT
boot2.nasに書いてあるGDTの内容を引き出すために四苦八苦。そもそも[__GDT]と__GDTの違いすら知らない状態なので100回以上トライ&エラーしたでしょうか。[__GDT]と__GDTの違いに関しては「はじめて読む486」の付録と何十回ものトライ&エラーでなんとか理解しました。g_GDT64が1になっているのは微妙におかしいのですが(4バイトアラインとかが関係しているのかな?)、とりあえずの成果を晒します。
カーネルとページングの関係が全然わかりません。
- カーネルはどこに読み込まれるのか?(0x400以降のような気はするのですが)
- 読み込まれたカーネルは特権モードなのか?ユーザーモードなのか?
- フラットアドレスでアクセスできるのか?
- FFFF_FFFF_C000_0000にカーネルを配置するにはどうしたらいいのか?(link64.txtをその値にするとでかすぎてリンクできないらしい)
余談ですが、PekoeSDKが大活躍です。make run するだけでカーネルのビルドから実行テストまでできるなんて夢のようです。
以下課題
boot2.nas
;; GDT lgdt [cs:__GDT] ;; save GDT address mov eax, __GDT mov [gdt64_Base], eax : : memstat: acpiRecMemBase dd 0 acpiRecMemSize dd 0 acpiNVSMemBase dd 0 acpiNVSMemSize dd 0 szMidMem dd 0 szHiMem dd 0 szExtMem dq 0 szLowMem dw 0 _text_vram dw 0xB800 _apm_ver dw 0 _col db 0 _row db 0 gdt64_Base dw 0 memstat_end:
kernel.cpp
struct gdt64_entry { short limitL, baseL; char baseM, type, limitH, baseH; }; struct gdt64_table { short limit; int base; struct gdt64_entry entry[11]; }; struct gdt64_table* g_GDT64; : : g_GDT64 = (gdt64_table*)(intptr)(0x10000 + memstat.gdt64_Base); printf("GDT: limit = %xH, base = %xH\n", g_GDT64->limit & 0xffff, g_GDT64->base & 0xffffffff); printf(" limit, base, type\n"); for (int i = 0; i < 11; i++) { printf("%8xH, %8xH, %2xH\n", g_GDT64->entry[i].limitL & 0xffff, g_GDT64->entry[i].baseL & 0xffff | (g_GDT64->entry[i].baseM & 0xff) << 16 | (g_GDT64->entry[i].baseH & 0xff) << 24, g_GDT64->entry[i].type & 0xff ); }