def generate_gdt(self, fs, gs, fs_size=0xFFFFFFFF, gs_size=0xFFFFFFFF):
        """
        Generate a GlobalDescriptorTable object and populate it using the value of the gs and fs register

        :param fs:      value of the fs segment register
        :param gs:      value of the gs segment register
        :param fs_size: size of the fs segment register
        :param gs_size: size of the gs segment register
        :return: gdt a GlobalDescriptorTable object
        """
        A_PRESENT = 0x80
        A_DATA = 0x10
        A_DATA_WRITABLE = 0x2
        A_PRIV_0 = 0x0
        A_DIR_CON_BIT = 0x4
        F_PROT_32 = 0x4
        S_GDT = 0x0
        S_PRIV_0 = 0x0
        GDT_ADDR = 0x4000
        GDT_LIMIT = 0x1000

        normal_entry = self._create_gdt_entry(0, 0xFFFFFFFF,
                                             A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_0 | A_DIR_CON_BIT,
                                             F_PROT_32)
        stack_entry = self._create_gdt_entry(0, 0xFFFFFFFF, A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_0,
                                            F_PROT_32)
        fs_entry = self._create_gdt_entry(fs, fs_size,
                                         A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_0 | A_DIR_CON_BIT, F_PROT_32)
        gs_entry = self._create_gdt_entry(gs, gs_size,
                                         A_PRESENT | A_DATA | A_DATA_WRITABLE | A_PRIV_0 | A_DIR_CON_BIT, F_PROT_32)

        table = normal_entry + stack_entry + fs_entry + gs_entry
        gdt =  (GDT_ADDR << 16 | GDT_LIMIT)
        selector = self._create_selector(1, S_GDT | S_PRIV_0)
        cs = selector
        ds = selector
        es = selector
        selector = self._create_selector(2, S_GDT | S_PRIV_0)
        ss = selector
        selector = self._create_selector(3, S_GDT | S_PRIV_0)
        fs = selector
        selector = self._create_selector(4, S_GDT | S_PRIV_0)
        gs = selector
        global_descriptor_table = GlobalDescriptorTable(GDT_ADDR, GDT_LIMIT, table, gdt, cs, ds, es, ss, fs, gs)
        return global_descriptor_table
Generate a GlobalDescriptorTable object and populate it using the value of the gs and fs register

        :param fs:      value of the fs segment register
        :param gs:      value of the gs segment register
        :param fs_size: size of the fs segment register
        :param gs_size: size of the gs segment register
        :return: gdt a GlobalDescriptorTable object