オプションを指定して GCC を使用してコードをコンパイルし-masm=intel
ます。カーネルは、GRUB などのマルチブート ローダーによってロードされます。
GDT のアドレスをロードしてから、すべてのセグメント レジスタをリロードしたいのですが、これによりトリプル フォールト (仮想マシンの再起動) が発生します。このコードは、ネイティブ アセンブリ (.asm ファイル) で使用すると機能します。
gdt.c:
#include "gdt.h"
GDT gdtp;
uint64_t gdt[GDT_ENTRIES];
void set_gdt_entry(int x, unsigned int base, unsigned int limit, int flags) {
gdt[x] = limit & 0xffffLL;
gdt[x] |= (base & 0xffffffLL) << 16;
gdt[x] |= ((flags >> 4) & 0xffLL) << 40;
gdt[x] |= ((limit >> 16) & 0xfLL) << 48;
gdt[x] |= (flags & 0xfLL) << 52;
gdt[x] |= ((base >> 24) & 0xffLL) << 56;
}
void gdt_init() {
gdtp.limit = GDT_ENTRIES * 8 - 1;
gdtp.pointer = gdt;
set_gdt_entry(0, 0, 0, 0);
set_gdt_entry(1, 0, 0xFFFFFFFF, GDT_SIZE | GDT_EXECUTABLE | GDT_SEGMENT | GDT_PRESENT);
set_gdt_entry(2, 0, 0xFFFFFFFF, GDT_SIZE | GDT_SEGMENT | GDT_PRESENT);
set_gdt_entry(3, 0, 0xFFFFFFFF, GDT_SIZE | GDT_EXECUTABLE | GDT_SEGMENT | GDT_PRESENT | GDT_RING3);
set_gdt_entry(4, 0, 0xFFFFFFFF, GDT_SIZE | GDT_SEGMENT | GDT_PRESENT | GDT_RING3);
asm volatile(
"lgdt %0\n"
"mov eax, 0x10\n"
"mov ss, eax\n"
"mov es, eax\n"
"mov ds, eax\n"
"mov gs, eax\n"
"mov fs, eax\n"
"jmp 0x08:1f\n"
"1:\n"
: : "m" (gdtp) : "eax"
);
}
これは私の gdt.h です:
#include <stdint.h>
#define GDT_ENTRIES 7
typedef enum {
GDT_AVAILABLE = 0x1,
GDT_LONG_MODE = 0x2,
GDT_SIZE = 0x3,
GDT_GRANULARITY = 0x8,
GDT_ACCESSED = 0x010,
GDT_READ_WRITE = 0x020,
GDT_CONFORMING = 0x040,
GDT_EXECUTABLE = 0x080,
GDT_SEGMENT = 0x100,
GDT_RING1 = 0x200,
GDT_RING2 = 0x400,
GDT_RING3 = 0x600,
GDT_PRESENT = 0x800
} GDT_FLAGS;
typedef struct {
uint16_t limit;
void *pointer;
}__attribute__((packed)) GDT;
void set_gdt_entry(int, unsigned int, unsigned int, int);
void gdt_init();
機能させるにはどうすればよいですか?