UnnamedOS
gdt_asm.S
1 .global gdt_flush
2 gdt_flush:
3 
4 // We need to load the CS register which can only be done by doing a far jump.
5 // 0x08 then is loaded into CS which has the 16-bit format
6 // fedcba9876543210
7 // a bc
8 // a being the index of the segment in the GDT, b whether we're in GDT (0) or IDT (1) and c the ring of the segment.
9 // So 0x08 means 0000000000001000, a is 1, b is 0 and c is 0; so 0x0008 describes the 2nd entry of the GDT (our code segment which is in ring 0).
10 
11 gdt_flush_code_segment:
12  ljmp $0x0008, $gdt_flush_data_segment
13  // We jump to the next label below with the side effect that CS is set to 0x08.
14  // The jump address ist calculated roughly as follows: gdt[index($0x08)].base + $gdt_flush_data_segment.
15  // index($0x08) is 1 (as explained above), so we look for the base of the 2nd GDT entry.
16  // This base is 0 (see gdt_init in gdt.c), so the jump address is 0 + $gdt_flush_data_segment = $gdt_flush_data_segment,
17  // which means we just jump to gdt_flush_data_segment normally (with flushing CS as side effect).
18 
19 gdt_flush_data_segment:
20  mov $0x0010, %ax // To flush the data (DS), stack (SS), extra (ES) and general purpose (FS/GS) segment registers, we can
21  mov %ax, %ds // just load our segment selector directly with mov. We use 0x10 because it means 0000000000010000,
22  mov %ax, %es // a is 2, b is 0 and c is 0; so 0x0010 describes the 3rd entry of the GDT (our data segment which is in ring 0).
23  mov %ax, %fs
24  mov %ax, %gs
25  mov %ax, %ss
26  ret // All the segment registers are set up now, we can return to the calling C code.