The segmentation functionality has been present on the Intel processors since early stages of the CPU manufacturing. In real-mode, segments were the basis of 16-bit memory management, allowing the operating system or application to specify separate memory areas for different types of information, i.e. code, regular data, stack and so on. When a more complex and powerful Protected Mode was introduced in the x86 processors, the usage (meaning) of the six segment registers was completely re-designed. From this point now on, these registers would no longer hold an explicit memory offset (as in real-mode), but instead they would be used to store so-called Segment Selector values, which are in turn pointers into one of the two segment descriptor tables: GDT or LDT (Global / Local Descriptor Table). Because of the introduction of another memory-management mechanism (paging), a great majority of the modern, main-stream operating systems don’t make extensive use of segmentation; they usually initialize GDT with trivial entries (e.g. base=0x00000000, size=0xffffffff), and then completely ignore the existence of segments (except for user ↔ kernel transitions). What is most important, however, is that even though the mechanism is ignored by the OS design, the systems make it possible for an application to set up its own LDT entries (e.g. sys_modify_ldt on Linux, or NtSetLdtEntries on Windows). Consequently, any process can locally make use of segmentation for its own purposes – e.g. in order to implement a somewhat safer execution environment, or other purposes.
More detailed information about segmentation and GDT/LDT management can be found in Intel 64 and IA-32 Architectures Software Developer’s Manual: Volume 3A: System Programming Guide Part 1, and GDT and LDT in Windows kernel vulnerability exploitation by me and Gynvael Coldwind. Any considerations made further in the post are provided with regard to the Windows operating system, which is the main subject of this write-up.