GDT

boot2.nasに書いてあるGDTの内容を引き出すために四苦八苦。そもそも[__GDT]と__GDTの違いすら知らない状態なので100回以上トライ&エラーしたでしょうか。[__GDT]と__GDTの違いに関しては「はじめて読む486」の付録と何十回ものトライ&エラーでなんとか理解しました。g_GDT64が1になっているのは微妙におかしいのですが(4バイトアラインとかが関係しているのかな?)、とりあえずの成果を晒します。


カーネルとページングの関係が全然わかりません。

  • カーネルはどこに読み込まれるのか?(0x400以降のような気はするのですが)
  • 読み込まれたカーネルは特権モードなのか?ユーザーモードなのか?
  • フラットアドレスでアクセスできるのか?
  • FFFF_FFFF_C000_0000にカーネルを配置するにはどうしたらいいのか?(link64.txtをその値にするとでかすぎてリンクできないらしい)


余談ですが、PekoeSDKが大活躍です。make run するだけでカーネルのビルドから実行テストまでできるなんて夢のようです。


以下課題

  • 上記4課題の解決
  • 64ビット下のGDTの扱いについて
  • 全く進展しないIDTの設定について
  • TSSの設定について
  • システムコールの実装

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
    );
}