PageSourceSearch

https://0xc0ffee.netlify.app/assets/14-memory-segments.html-DzJfJwBM.js

js 0xc0ffee.netlify.app collected 2026-10-03 10:23:36 UTC 57,555 bytes, 243 lines download raw bytes

1import{_ as e,c as n,e as a,o as t}from"./app-CjUkjRdW.js";const i={};function l(p,s){return t(),n("div",null,s[0]||(s[0]=[a(`<h1 id="memory-segments" tabindex="-1"><a class="header-anchor" href="#memory-segments"><span>Memory Segments</span></a></h1><p>In the x86 architecture (including x86_64), all memory access is subject to segmentation. Even though in 64-bit mode segment boundaries are ignored (they&#39;re all set to the full 64-bit address space), we still need a number of them to differentiate between code and data access, and between kernel mode and user mode privileges. This is done through the <strong>Global Descriptor Table</strong> (GDT), which is a table of segment descriptors that the CPU uses to determine the access rights of memory accesses.</p><h2 id="segment-descriptors" tabindex="-1"><a class="header-anchor" href="#segment-descriptors"><span>Segment Descriptors</span></a></h2><p>Segments are basically regions of memory with certain properties, including their base address and size, whether they hold code or data, whether they&#39;re writable (for data segments) or readable (for code segments), whether they&#39;re accessible from user mode or kernel mode, and a few other things. This technique of managing memory is called <strong>segmentation</strong>, which offered a flexible way to allocate regions of memory in a protected manner. It&#39;
1s no longer used in modern operating systems as they tend to use paging only for memory management and protection. It is, however, still used by modern CPUs in a limited way. In x86-64, all segments assume a flat memory model, which means that each segment occupies the entire 64-bit address space. The most important features of segments for our purpose are two things:</p><ul><li>Their privilege level, which determines whether they&#39;re accessible from user mode or kernel mode.</li><li>Their type, which determines whether they&#39;re code or data segments. (There&#39;s also a third type called a system segment, which we&#39;ll come back to later.)</li></ul><p>This gives us four possible combinations:</p><ul><li>Kernel code segment</li><li>Kernel data segment</li><li>User code segment</li><li>User data segment</li></ul><p>However, even though we&#39;ll need two code segments, we can use only one data segment for both kernel and user mode (I explain below, under Segment Selectors, why this is the case). So we&#39;ll end up with only three segments.</p><p>All three segments will have the same base address (0) and the same size (the entire 64-bit address space). The only difference between them will be their privilege level and type. We&#39;ll need to define a segment descriptor for each of them. A segment descriptor is a 64-bit value that contains all the information about the segment. Here&#39;s a diagram of the segment descriptor format:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line"> 31                   24 23 22 21 20 19       16 15 14 13 12 11       08 07                   00</span>
2<span class="line">┌───────────────────────┬──┬──┬──┬──┬───────────┬──┬─────┬──┬───────────┬───────────────────────┐</span>
3<span class="line">│      Base Address     │G │D │L │A │   Limit   │P │ DPL │S │   Type    │     Base Address      │</span>
4<span class="line">│        [31:24]        │  │/ │  │V │  [19:16]  │  │     │  │           │        [23:16]        │ 4</span>
5<span class="line">│                       │  │B │  │L │           │  │     │  │           │                       │</span>
6<span class="line">└───────────────────────┴──┴──┴──┴──┴───────────┴──┴─────┴──┴───────────┴───────────────────────┘</span>
7<span class="line"> 31                                           16 15                                           00</span>
8<span class="line">┌───────────────────────────────────────────────┬───────────────────────────────────────────────┐</span>
9<span class="line">│                  Base Address                 │                     Limit                     │ 0</span>
10<span class="line">│                    [15:00]                    │                    [15:00]                    │</span>
11<span class="line">└───────────────────────────────────────────────┴───────────────────────────────────────────────┘</span>
12<span class="line"></span>
13<span class="line">Base        Segment base address</span>
14<span class="line">Limit       Segment Limit</span>
15<span class="line">Type        Segment type</span>
16<span class="line">S           Descriptor type (0 = system; 1 = code or data)</span>
17<span class="line">DPL         Descriptor privilege level</span>
18<span class="line">P           Segment present</span>
19<span class="line">AVL         Available for use by system software (unused by the CPU)</span>
20<span class="line">
20L           64-bit code segment (IA-32e mode only)</span>
21<span class="line">D/B         Default operation size (0 = 16-bit segment; 1 = 32-bit segment)</span>
22<span class="line">G           Granularity</span>
23<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The meaning of these fields is quite involved, they&#39;re described in detail in the Intel Software Developer&#39;s Manual, section 3.2. I&#39;m going to go over them here briefly, but I recommend reading the manual for more details.</p><dl><dt><strong>Base Address</strong></dt><dd>Since we&#39;re using a flat memory model, the base address is always 0.</dd><dt><strong>Limit</strong></dt><dd>This is the last valid offset in the segment. In long mode (64-bit), the processor does not perform segment limit checks, so this field is ignored.</dd><dt><strong>Type</strong></dt><dd>This determines whether the segment is a code segment or a data segment. It has the following subfields:</dd></dl><ul><li>Bit 11: <code>0</code> for data segments, <code>1</code> for code segments.</li><li>Bit 10: <ul><li>For code segments: <strong>C</strong> - Conforming. If set, code in this segment can be executed from a lower privilege level (under the current privilege level). If clear, code in this segment can only be executed from the same privilege level.</li><li>For data segments: <strong>E</strong> - Expand down. If set, the segment grows down, otherwise it grows up. This is used for stacks.</li></ul></li><li>Bit 9: <ul><li>For code segments: <strong>R</strong> - Readable. If set, read access for this segment is allowed. Note that code doesn&#39;t need to be readable to be executable.</li><li>For data segments: <strong>W</strong> - Writable. If set, write access for this segment is allowed.</li></ul></li><li>Bit 8: <strong>A</strong> - Accessed. This is set by the CPU when the segment is accessed. The OS can use this to keep track of which segments are used and which aren&#39;t.</li></ul><dl><dt><strong>S</strong></dt><dd>This determines whether the segment is a system segment or a code or data segment. It&#39;s set for code and data segments. It&#39;s clear for system segments, which are used for special purposes, such as task state segments (we&#39;ll cover this later when we implement multitasking).</dd><dt><strong>DPL</strong></dt><dd>This is the privilege level required to access the segment. It&#39;s a 2-bit field, so it can have one of four values: 0, 1, 2, or 3. DPL 0 is the most privileged level, under which the kernel runs. DPL 3 is the least privileged level, under which user programs run.</dd><dt><strong>P</strong></dt><dd>This determines whether the segment is present in memory. If it&#39;s clear, the CPU will raise an exception when the segment is accessed.</dd><dt><strong>AVL</strong></dt><dd>This is available for use by the OS. The CPU doesn&#39;t use it.</dd><dt><strong>L</strong></dt><dd>This determines whether the segment is a 64-bit code segment. If not set, the code segment will be executed in compatibility mode, which is 32-bit mode.</dd><dt><strong>D/B</strong></dt><dd>This determines the default operand size for the segment. It must be set to zero for 64-bit code segments (i.e., when L is set).</dd><dt><strong>G</strong></dt><dd>This determines the granularity of the segment limit. If clear, the limit is interpreted as the number of bytes. If set, the limit is interpreted as the number of 4 KiB pages.</dd></dl><h3 id="segment-selectors" tabindex="-1"><a class="header-anchor" href="#segment-selectors"><span>Segment Selectors</span></a></h3><p>Accessing a segment happens through a <strong>segment selector</strong>, which is a 16-bit value loaded into a segment register (CS, DS, ES, FS, GS, SS) containing the offset of a particular segment descriptor in the GDT. Only 13 bits are used to store the offset. The remaining 3 bits are used to store two things: the <strong>RPL</strong> (Requestor Privilege Level) and the <strong>TI</strong> (Table Indicator). Here&#39;s a diagram of the segment selector format:</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line"> 15                                  03 02 01 00</span>
24<span class="line">┌──────────────────────────────────────┬──┬─────┐</span>
25<span class="line">│                Index                 │TI│ RPL │</span>
26<span class="line">└──────────────────────────────────────┴──┴─────┘</span>
27<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The TI is a 1-bit field that indicates whether the segment selector is a GDT selector (TI = 0) or an LDT (Local Descriptor Table) selector (TI = 1). We&#39;ll only be using the GDT, so TI will always be 0.</p><p>The RPL is a 2-bit field that stores the request privilege level of a segment selector (not a descriptor). It&#39;s a way to override the CPL (Current Privilege Level) of the currently running code. The effective privilege level is <em>max(CPL, RPL)</em>, which is checked against the DPL of the target segment, and access is only allowed if the effective privilege level is numerically equal to or less than the DPL of the target segment. This means that RPL in user mode has no effect (since CPL is 3, so RPL doesn&#39;t matter). In kernel mode, the kernel has access to all segments (since its CPL is 0). A higher RPL can be used by the kernel to ensure that privileged code does not access a segment on behalf of an application program unless the program itself has access privileges for that segment.</p><p>For the purpose of our kernel, we&#39;ll use a single data segment with DPL=3 and selector with RPL=3 for both kernel and user mode. The data segment will be subject to the following access checks:</p><ul><li>Kernel mode: max(CPL = 0, RPL = 3) = 3, DPL = 3 ==&gt; access allowed</li><li>User mode: max(CPL = 3, RPL = 3) = 3, DPL = 3 ==&gt; access allowed</li></ul><p>Protection of kernel memory will be done through paging, not segmentation. As a nice side effect, we don&#39;t have to save and restore the data segment registers when switching between kernel mode and user mode.</p><p>One exception to the access checks done on segment registers is the stack segment register SS. The Intel manual says:</p><blockquote><p><strong>
275.7 PRIVILEGE LEVEL CHECKING WHEN LOADING THE SS REGISTER</strong></p><p>Privilege level checking also occurs when the SS register is loaded with the segment selector for a stack segment. Here all privilege levels related to the stack segment must match the CPL; that is, the CPL, the RPL of the stack-segment selector, and the DPL of the stack-segment descriptor must be the same. If the RPL and DPL are not equal to the CPL, a general-protection exception (#GP) is generated.</p></blockquote><p>So our strategy to use a single data segment for both kernel and user mode sounds like it may not work for the stack segment. However, the manual mentions this about stack switching in long mode:</p><blockquote><p><strong>6.14.4 Stack Switching in IA-32e Mode</strong></p><p>... When stacks are switched as part of a 64-bit mode privilege-level change (resulting from an interrupt), a new SS descriptor is not loaded. IA-32e mode loads only an inner-level RSP from the TSS. The new SS selector is forced to NULL and the SS selector’s RPL field is set to the new CPL. [...] The old SS and RSP are saved on the new stack (Figure 6-9). On the subsequent IRET, the old SS is popped from the stack and loaded into the SS register.</p></blockquote><p>So if I understand this correctly, we can use a NULL SS selector for the kernel. When we switch to user mode we&#39;ll set SS to the data segment selector (where CPL = RPL = DPL = 3), and upon switching to kernel mode, the CPU will force SS to NULL again, saving the user mode SS on the kernel stack (to be popped later by IRET).</p><h2 id="global-descriptor-table" tabindex="-1"><a class="header-anchor" href="#global-descriptor-table"><span>Global Descriptor Table</span></a></h2><p>When we want to use a new segment, we need to create a segment descriptor for it and store it in the GDT. The GDT is stored in memory, and we tell the CPU where it is by loading its address into a special register called the <strong>GDTR</strong>. The GDTR contains the base address (64-bit address) of the GDT and its limit (16-bit value representing the last valid offset in the GDT).</p><p>As I mentioned above, we&#39;ll need three segments: a kernel code segment, a user code segment, and a shared data segment. We also need a null segment, which is a segment with all fields set to zero. The null segment needs to be the first segment in the GDT.</p><p>Here&#39;s a diagram illustrating the layout of the GDT and the GDTR. Technically, the order of the segments doesn&#39;t matter (except for the null segment, which must be the first one), but I chose this order in particular because it will make setting up system calls easier later.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">                          GDT</span>
28<span class="line"></span>
29<span class="line">   offset    segment descriptor</span>
30<span class="line">             ┌───────────────────────────┐ ◄──┐</span>
31<span class="line">   0x18      │ User Code Segment         │    │</span>
32<span class="line">             ├───────────────────────────┤    │</span>
33<span class="line">   0x10      │ Data Segment (shared)     │    │</span>
34<span class="line">             ├───────────────────────────┤    ├── GDTR Limit</span>
35<span class="line">   0x08      │ Kernel Code Segment       │    │</span>
36<span class="line">             ├───────────────────────────┤    │</span>
37<span class="line">   0x00      │ Null Segment              │    │</span>
38<span class="line">             └───────────────────────────┘ ◄──┴── GDTR Base</span>
39<span class="line">    ▲</span>
40<span class="line">    │</span>
41<span class="line">  segment</span>
42<span class="line">  selector</span>
43<span class="line">    │········┐ ·······┐ ·······┐ ·······┐ ·······┐</span>
44<span class="line"> ┌──┴───┐ ┌──┴───┐ ┌──┴───┐ ┌──┴───┐ ┌──┴───┐ ┌──┴───┐</span>
45<span class="line"> │  CS  │ │  DS  │ │  ES  │ │  FS  │ │  GS  │ │  SS  │  ◄── segment registers</span>
46<span class="line"> └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘</span>
47<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The diagram also shows the segment registers, which store the segment selector (i.e. offset) of the currently active segment descriptor for that register. For example, when executing in user mode, the CS register will c
47ontain the user code segment selector <code>0x18</code>, and the DS register will contain the data segment selector <code>0x10</code>. If the CPU is interrupted, or the user program makes a system call, the CPU will switch to kernel mode, and the CS register will be updated to the kernel code segment selector <code>0x08</code> (the data segment selector will remain the same, <code>0x10</code>, when entering the kernel).</p><p>Enough theory, let&#39;s define the types for the segment descriptors and the GDT in a new file <code>src/kernel/gdt.nim</code>. I&#39;m defining three types (not instances) for the segment descriptors: <code>CodeSegmentDescriptor</code>, <code>DataSegmentDescriptor</code>, and <code>SegmentDescriptorValue</code>. I use the latter mainly use for the null segment descriptor constant <code>NullSegmentDescriptor</code>.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/gdt.nim</span></span>
48<span class="line"></span>
49<span class="line"><span class="token keyword">type</span></span>
50<span class="line">  CodeSegmentDescriptor<span class="token operator">*</span> <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
51<span class="line">    limit00<span class="token operator">:</span> uint16 <span class="token operator">=</span> <span class="token number">0xffff</span></span>
52<span class="line">    base00<span class="token operator">:</span> uint16 <span class="token operator">=</span> <span class="token number">0</span></span>
53<span class="line">    base16<span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
54<span class="line">    code <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
55<span class="line">    conforming<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
56<span class="line">    readable<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
57<span class="line">    accessed<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
58<span class="line">    s <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
59<span class="line">    dpl<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">2.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8</span>
60<span class="line">    p<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
61<span class="line">    limit16 <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">4.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0xf</span></span>
62<span class="line">    avl<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
63<span class="line">
63    l <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
64<span class="line">    d <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
65<span class="line">    g <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
66<span class="line">    base24<span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
67<span class="line"></span>
68<span class="line">  DataSegmentDescriptor<span class="token operator">*</span> <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
69<span class="line">    limit00<span class="token operator">:</span> uint16 <span class="token operator">=</span> <span class="token number">0xffff</span></span>
70<span class="line">    base00<span class="token operator">:</span> uint16 <span class="token operator">=</span> <span class="token number">0</span></span>
71<span class="line">    base16<span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
72<span class="line">    code <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
73<span class="line">    expandDown<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
74<span class="line">    writable<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
75<span class="line">    accessed<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
76<span class="line">    s <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
77<span class="line">    dpl<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">2.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8</span>
78<span class="line">    p<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">1</span></span>
79<span class="line">    limit16 <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">4.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0xf</span></span>
80<span class="line">    avl<span class="token operator">*</span> <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
81<span class="line">
81    l <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
82<span class="line">    b <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
83<span class="line">    g <span class="token punctuation">{.</span>bitsize<span class="token operator">:</span> <span class="token number">1.</span><span class="token punctuation">}</span><span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
84<span class="line">    base24<span class="token operator">:</span> uint8 <span class="token operator">=</span> <span class="token number">0</span></span>
85<span class="line"></span>
86<span class="line">  SegmentDescriptorValue <span class="token operator">=</span> <span class="token keyword">distinct</span> uint32</span>
87<span class="line"></span>
88<span class="line">  SegmentDescriptor <span class="token operator">=</span></span>
89<span class="line">    CodeSegmentDescriptor <span class="token operator">|</span></span>
90<span class="line">    DataSegmentDescriptor <span class="token operator">|</span></span>
91<span class="line">    SegmentDescriptorValue</span>
92<span class="line"></span>
93<span class="line">  GdtDescriptor<span class="token operator">*</span> <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
94<span class="line">    limit<span class="token operator">*:</span> uint16</span>
95<span class="line">    base<span class="token operator">*:</span> pointer</span>
96<span class="line"></span>
97<span class="line"><span class="token keyword">const</span></span>
98<span class="line">  NullSegmentDescriptor<span class="token operator">*</span> <span class="token operator">=</span> <span class="token function">SegmentDescriptorValue</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span></span>
99<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We will almost never need to change the default values for the segment descriptors, which makes creating them simple: we only need to set the <code>dpl</code> field to the desired privilege level.</p><p>Since we need to store the segment descriptors in an array, they all need to be of the same type. Unfortunately we can&#39;t use a variant object for this, because it introduces a <code>kind</code> field that shouldn&#39;t be part of the segment descriptor. Also, we can&#39;t use the union type <code>SegmentDescriptor</code> declared above, because it&#39;
99s not a true union type (in the C sense); an array cannot hold mixed types of this union type. The simplest solution is to let the array hold simple <code>uint64</code> values representing the segment descriptors. We can then define a proc to convert a segment descriptor object to a <code>uint64</code> value:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/gdt.nim</span></span>
100<span class="line"></span>
101<span class="line"><span class="token keyword">proc</span> <span class="token function">value<span class="token operator">*</span></span><span class="token punctuation">(</span>sd<span class="token operator">:</span> SegmentDescriptor<span class="token punctuation">)</span><span class="token operator">:</span> uint64 <span class="token operator">=</span></span>
102<span class="line">  result <span class="token operator">=</span> <span class="token function">cast[uint64]</span><span class="token punctuation">(</span>sd<span class="token punctuation">)</span></span>
103<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Then we can define the GDT as follows:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/gdt.nim</span></span>
104<span class="line"></span>
105<span class="line"><span class="token keyword">const</span></span>
106<span class="line">  KernelCodeSegmentSelector<span class="token operator">*</span> <span class="token operator">=</span> <span class="token number">0x08</span></span>
107<span class="line">  DataSegmentSelector<span class="token operator">*</span>       <span class="token operator">=</span> <span class="token number">0x10</span> <span class="token operator">or</span> <span class="token number">3</span> <span class="token comment"># RPL = 3</span></span>
108<span class="line">  UserCodeSegmentSelector<span class="token operator">*</span>   <span class="token operator">=</span> <span class="token number">0x18</span> <span class="token operator">or</span> <span class="token number">3</span> <span class="token comment"># RPL = 3</span></span>
109<span class="line"></span>
110<span class="line"><span class="token keyword">let</span></span>
111<span class="line">  gdtEntries <span class="token operator">=</span> <span class="token punctuation">[</span></span>
112<span class="line">    NullSegmentDescriptor<span class="token operator">.</span>value<span class="token punctuation">,</span></span>
113<span class="line">    <span class="token function">CodeSegmentDescriptor</span><span class="token punctuation">(</span>dpl<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">.</span>value<span class="token punctuation">,</span> <span class="token comment"># Kernel code segment</span></span>
114<span class="line">    <span class="token function">DataSegmentDescriptor</span><span class="token punctuation">(</span>dpl<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token operator">.</span>value<span class="token punctuation">,</span> <span class="token comment"># Data segment (shared)</span></span>
115<span class="line">    <span class="token function">CodeSegmentDescriptor</span><span class="token punctuation">(</span>dpl<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token operator">.</span>value<span class="token punctuation">,</span> <span class="token comment"># User code segment</span></span>
116<span class="line">  <span class="token punctuation">]</span></span>
117<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>
117Now we can define the GDT descriptor type and a single instance of it:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/gdt.nim</span></span>
118<span class="line"></span>
119<span class="line"><span class="token keyword">type</span></span>
120<span class="line">  GdtDescriptor<span class="token operator">*</span> <span class="token punctuation">{.</span>packed<span class="token punctuation">.}</span> <span class="token operator">=</span> <span class="token keyword">object</span></span>
121<span class="line">    limit<span class="token operator">*:</span> uint16</span>
122<span class="line">    base<span class="token operator">*:</span> pointer</span>
123<span class="line"></span>
124<span class="line"><span class="token keyword">let</span></span>
125<span class="line">  gdtDescriptor <span class="token operator">=</span> <span class="token function">GdtDescriptor</span><span class="token punctuation">(</span></span>
126<span class="line">    limit<span class="token operator">:</span> <span class="token function">sizeof</span><span class="token punctuation">(</span>gdtEntries<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">,</span></span>
127<span class="line">    base<span class="token operator">:</span> gdtEntries<span class="token operator">.</span><span class="token keyword">addr</span></span>
128<span class="line">  <span class="token punctuation">)</span></span>
129<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="loading-the-gdt" tabindex="-1"><a class="header-anchor" href="#loading-the-gdt"><span>Loading the GDT</span></a></h2><p>Finally, we can now define an <code>gdtInit</code> proc that loads the GDT descriptor into the GDTR register using the <code>lgdt</code> instruction. We&#39;ll also load the segment selectors for the kernel code and data segments into the segment registers.</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/gdt.nim</span></span>
130<span class="line"></span>
131<span class="line"><span class="token keyword">proc</span> <span class="token function">gdtInit<span class="token operator">*</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{.</span>asmNoStackFrame<span class="token punctuation">.}</span> <span class="token operator">=</span></span>
132<span class="line">  <span class="token comment"># Ideally we would use a far jump here to reload the CS register, but support</span></span>
133<span class="line">  <span class="token comment"># for 64-bit far jumps (\`JMP m16:64\`) is not supported by the LLVM integrated</span></span>
134<span class="line">  <span class="token comment"># assembler. It&#39;s also only supported by Intel processors, not AMD. So we use</span></span>
135<span class="line">  <span class="token comment"># a far return instead.</span></span>
136<span class="line">  <span class="token keyword">asm</span> <span class="token string">&quot;&quot;&quot;</span>
137<span class="line">    lgdt %0</span>
138<span class="line"></span>
139<span class="line">    # reload CS using a far return</span>
140<span class="line">    lea rax, [rip + 1f]</span>
141<span class="line">    push %1    # cs</span>
142<span class="line">    push rax   # rip</span>
143<span class="line">    retfq</span>
144<span class="line"></span>
145<span class="line">  1:</span>
146<span class="line">    # reload data segment registers</span>
147<span class="line">    mov rax, %2</span>
148<span class="line">    mov ds, rax</span>
149<span class="line">    mov es, rax</span>
150<span class="line">    mov fs, rax</span>
151<span class="line">    mov gs, rax</span>
152<span class="line"></span>
153<span class="line">    # set SS to NULL</span>
154<span class="line">    xor rax, rax</span>
155<span class="line">    mov ss, rax</span>
156<span class="line">    :</span>
157<span class="line">    : &quot;m&quot;(\`gdtDescriptor\`),</span>
158<span class="line">      &quot;i&quot;(\`KernelCodeSegmentSelector\`),</span>
159<span class="line">      &quot;i&quot;(\`DataSegmentSelector\`)</span>
160<span class="line">    : &quot;rax&quot;</span>
161<span class="line">  &quot;&quot;&quot;</span></span>
162<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The comment explains why we&#39;re using a far return instead of a far jump. The <code>retfq</code> instruction is a far return, which pops the instruction pointer and the code segment selector from the stack and jumps to the <code>1:</code> label. It&#39;s as if the CPU continued execution right after the <code>retfq</code> instruction, but with the new code segment selector. The rest of the code reloads the other segment registers with the data segment selector. (The last <code>:</code> constraint tell the compiler that the <code>asm</code> block clobbers the <code>rax</code> register.)</p><p>Now we&#39;re ready to call <code>gdtInit</code> from <code>src/kernel/main.nim</code>:</p><div class="language-nim line-numbers-mode" data-highlighter="prismjs" data-ext="nim" data-title="nim"><pre><code><span class="line"><span class="token comment"># src/kernel/main.nim</span></span>
163<span class="line"></span>
164<span class="line highlighted"><span class="token keyword">
164import</span> gdt</span>
165<span class="line"><span class="token operator">...</span></span>
166<span class="line"></span>
167<span class="line"><span class="token keyword">proc</span> <span class="token function">KernelMainInner</span><span class="token punctuation">(</span>bootInfo<span class="token operator">:</span> <span class="token keyword">ptr</span> BootInfo<span class="token punctuation">)</span> <span class="token operator">=</span></span>
168<span class="line">  debugln <span class="token string">&quot;&quot;</span></span>
169<span class="line">  debugln <span class="token string">&quot;kernel: Fusion Kernel&quot;</span></span>
170<span class="line"></span>
171<span class="line">  <span class="token operator">...</span></span>
172<span class="line"></span>
173<span class="line">  debug <span class="token string">&quot;kernel: Initializing GDT &quot;</span></span>
174<span class="line">  <span class="token function">gdtInit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
175<span class="line">  debugln <span class="token string">&quot;[success]&quot;</span></span>
176<span class="line"></span>
177<span class="line">  <span class="token function">quit</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
178<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Let&#39;s compile and run.</p><div class="language-text line-numbers-mode" data-highlighter="prismjs" data-ext="text" data-title="text"><pre><code><span class="line">boot: Preparing BootInfo</span>
179<span class="line">boot: Creating new page tables</span>
180<span class="line">boot:   Identity-mapping bootloader:   base=0x06237000, pages=290</span>
181<span class="line">boot:   Identity-mapping BootInfo:     base=0x0636d000, pages=1</span>
182<span class="line">boot:   Mapping kernel to higher half: base=0xffff800000100000, pages=288</span>
183<span class="line">boot:   Mapping kernel stack:          base=0xffff800100000000, pages=4</span>
184<span class="line">boot:   Mapping physical memory:       base=0xffff800200000000, pages=32500</span>
185<span class="line">boot: Jumping to kernel at 0xffff800000100000</span>
186<span class="line"></span>
187<span class="line">kernel: Fusion Kernel</span>
188<span class="line">kernel: Initializing physical memory manager [success]</span>
189<span class="line">kernel: Physical memory free regions</span>
190<span class="line">              Start     Start (KB)     Size (KB)      #Pages</span>
191<span class="line">                0x0              0           640         160</span>
192<span class="line">           0x220000           2176          6016        1504</span>
193<span class="line">           0x808000           8224            12           3</span>
194<span class="line">           0x80c000           8240            16           4</span>
195<span class="line">           0x900000           9216         92596       23149</span>
196<span class="line">          0x6372000         101832         17900        4475</span>
197<span class="line">          0x77ff000         122876          7124        1781</span>
198<span class="line">kernel: Total free: 124304 KiB (121 MiB)</span>
199<span class="line">kernel: Virtual memory regions</span>
200<span class="line">                  Start   Type           VM Size (KB)      #Pages</span>
201<span class="line">     0xffff800000100000   KernelCode             1152         288</span>
202<span class="line">     0xffff800100000000   KernelStack              16           4</span>
203<span class="line">     0xffff800100004000   KernelData                4           1</span>
204<span class="line">     0xffff800200000000   KernelData           130000       32500</span>
205<span class="line">kernel: Initializing GDT [success]</span>
206<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Phew! We have a working GDT. Let&#39;s double-check the CPU registers using the QEMU monitor command <code>info registers</code> (I temporarily replaced the <code>-debugcon stdio</code> flag with the <code>-monitor stdio</code> flag in the <code>justfile</code> to make it easier to access the QEMU monitor through the terminal):</p><div class="language-sh-session line-numbers-mode" data-highlighter="prismjs" data-ext="sh-session" data-title="sh-session"><pre><code><span class="line"><span class="token output">QEMU 8.2.0 monitor - type &#39;help&#39; for more information</span>
207<span class="line">(qemu) info registers</span>
208<span class="line"></span>
209<span class="line">CPU#0</span>
210<span class="line">RAX=ffff800000114d80 RBX=0000000000000000 RCX=ffff800100003f10 RDX=ffff800100003f58</span>
211<span class="line">RSI=000000000000000a RDI=0000000000000000 RBP=ffff800100003f48 RSP=ffff8
21100100003f00</span>
212<span class="line">R8 =ffff800100003c10 R9 =0000000007ea5e48 R10=000000000636d001 R11=0000000000000004</span>
213<span class="line">R12=0000000000000000 R13=0000000006bb1588 R14=0000000000000000 R15=0000000007ebf1e0</span>
214<span class="line">RIP=ffff800000114d82 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=1</span>
215<span class="line highlighted">ES =0013 0000000000000000 000fffff 000ff300 DPL=3 DS   [-WA]</span>
216<span class="line highlighted">CS =0008 0000000000000000 000fffff 002f9a00 DPL=0 CS64 [-R-]</span>
217<span class="line highlighted">SS =0000 0000000000000000 00000000 00000000</span>
218<span class="line highlighted">DS =0013 0000000000000000 000fffff 000ff300 DPL=3 DS   [-WA]</span>
219<span class="line highlighted">FS =0013 0000000000000000 000fffff 000ff300 DPL=3 DS   [-WA]</span>
220<span class="line highlighted">GS =0013 0000000000000000 000fffff 000ff300 DPL=3 DS   [-WA]</span>
221<span class="line">LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT</span>
222<span class="line">TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy</span>
223<span class="line highlighted">GDT=     ffff80000021ebe0 0000001f</span>
224<span class="line">IDT=     ffff80000021ec00 00000fff</span>
225<span class="line">CR0=80010033 CR2=0000000000000000 CR3=000000000625b000 CR4=00000668</span>
226<span class="line">DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000</span>
227<span class="line">DR6=00000000ffff0ff0 DR7=0000000000000400</span>
228<span class="line">EFER=0000000000000d00</span>
229<span class="line">
229FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80</span>
230<span class="line">FPR0=0000000000000000 0000 FPR1=0000000000000000 0000</span>
231<span class="line">FPR2=0000000000000000 0000 FPR3=0000000000000000 0000</span>
232<span class="line">FPR4=0000000000000000 0000 FPR5=0000000000000000 0000</span>
233<span class="line">FPR6=0000000000000000 0000 FPR7=0000000000000000 0000</span>
234<span class="line">XMM00=00000000062552f8 0000000000000018 XMM01=0000000000000000 0000000000000000</span>
235<span class="line">XMM02=0000000000000000 0000000000000000 XMM03=0000000000000000 0000000000000000</span>
236<span class="line">XMM04=0000000000000000 0000000000000000 XMM05=0000000000000000 0000000000000000</span>
237<span class="line">XMM06=0000000000000000 0000000000000000 XMM07=0000000000000000 0000000000000000</span>
238<span class="line">XMM08=0000000000000000 0000000000000000 XMM09=0000000000000000 0000000000000000</span>
239<span class="line">XMM10=0000000000000000 0000000000000000 XMM11=0000000000000000 0000000000000000</span>
240<span class="line">XMM12=0000000000000000 0000000000000000 XMM13=0000000000000000 0000000000000000</span>
241<span class="line">XMM14=0000000000000000 0000000000000000 XMM15=0000000000000000 0000000000000000</span>
242<span class="line">(qemu)</span>
243<span class="line"></span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This looks good. The <code>CS</code> register contains the kernel code segment selector <code>0x08</code>, and its DPL=0.The other segment registers contain the data segment selector <code>0x13</code> (i.e. offset <code>0x10</code> | RPL <code>0x3</code>), and their DPL=3. The <code>SS</code> is set to NULL as expected. The <code>GDT</code> register seems to contain the address of the GDT descriptor (the address seems legit), and the limit is <code>0x1f</code>, which is the size of the GDT in bytes minus 1 (4 entries * 8 bytes per entry - 1).</p><p>For now, we&#39;ll be using only the kernel code and data segments. We&#39;ll come back to the user code segments when we implement user mode. We&#39;ll also come back to the GDT when we implement multitasking, because we&#39;ll need to add a new segment descriptor for the task state segment (TSS), which is required by the CPU when switching from user mode to kernel mode (e.g. when making a system call or when an interrupt occurs).</p><p>We&#39;ll now move to implementing the interrupt descriptor table (IDT) to handle CPU exceptions (and later hardware and software interrupts).</p>`,55)]))}const r=e(i,[["render",l],["__file","14-memory-segments.html.vue"]]),c=JSON.parse(`{"path":"/osdev/14-memory-segments.html","title":"Memory Segments","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Segment Descriptors","slug":"segment-descriptors","link":"#segment-descriptors","children":[{"level":3,"title":"Segment Selectors","slug":"segment-selectors","link":"#segment-selectors","children":[]}]},{"level":2,"title":"Global Descriptor Table","slug":"global-descriptor-table","link":"#global-descriptor-table","children":[]},{"level":2,"title":"Loading the GDT","slug":"loading-the-gdt","link":"#loading-the-gdt","children":[]}
243],"git":{"updatedTime":1744638230000},"filePathRelative":"osdev/14-memory-segments.md","excerpt":"\\n<p>In the x86 architecture (including x86_64), all memory access is subject to segmentation.\\nEven though in 64-bit mode segment boundaries are ignored (they're all set to the full\\n64-bit address space), we still need a number of them to differentiate between code and\\ndata access, and between kernel mode and user mode privileges. This is done through the\\n<strong>Global Descriptor Table</strong> (GDT), which is a table of segment descriptors that the CPU\\nuses to determine the access rights of memory accesses.</p>"}`);export{r as comp,c as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.