#include "gdt.h" using seg = GDT::SegmentDescriptor; static_assert(sizeof(seg) == 8); static_assert(sizeof(seg::Access) == 1); static_assert((seg::Access{}) == 0x00); static_assert((seg::Access{.r_w = true, .exe = true, .segment = true, .present = true}) == 0x9a); static_assert((seg::Access{.r_w = true, .segment = true, .present = true}) == 0x92); GDT::SegmentDescriptor::SegmentDescriptor(uint32_t base, uint32_t limit, GDT::SegmentDescriptor::Access type) : access(type) { // store base base_15_0 = base & 0xffff; base_23_16 = (base >> 16) & 0xff; base_31_24 = (base >> 24) & 0xff; // store limit if (limit <= 0xffffu) { // 16-bit address space limit_15_0 = limit & 0xffff; limit_19_16 = 0; } else { db = 1; // limit is uint32_t, which we need to store in limit_19_16 and limit_15_0, a total of 20 bits limit = limit >> 12; limit_15_0 = limit & 0xffff; limit_19_16 = (limit >> 16) & 0xf; } granularity = 1; } uint32_t GDT::SegmentDescriptor::base() const { uint32_t base = base_31_24; base = (base << 8) + base_23_16; base = (base << 16) + base_15_0; return base; } uint32_t GDT::SegmentDescriptor::limit() const { uint32_t limit = 0; if (db == 1) { limit = limit_19_16; limit = limit << 16; } limit += limit_15_0; return 0; }