简体   繁体   中英

Far jump in gdt in bootloader

flush_gdt:
    lgdt [gdtr]
    jmp 0x08:complete_flush

complete_flush:
    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    ret

I am unable to understand what this code does . flush_gdt is a label okay , then lgdt [gdtr] loads the 48-bit pointer in gdtr register and after that from jmp 0x08:complet_flush .

What does jmp instruction do ? and then why are we moving 0x10 to ax and then subsequently to other registers

x86 supports two virtual memory schemes ( read about it here ):

  • segmentation, must, managed using the segment table, GDT.
  • paging, optional, managed using the page table, PDT.

Most operating systems want to to use paging and don't want the segmentation, but its must and can't just be disabled.

So the trick is to disable its effect as it wasn't there. This can usually be done by creating 4 large overlapped segments descriptors (beside the null segment):

  • segment index 0 : null segment descriptor
  • segment index 1 : code segment descriptor for the privileged (kernel) mode
  • segment index 2 : data segment descriptor for the privileged (kernel) mode
  • segment index 3 : code segment descriptor for the non-privileged (user) mode
  • segment index 4 : data segment descriptor for the non-privileged (user) mode

all these segments starts from 0x00000000 up to 0xffffffff , so you end up with overlapped large segments that is privileged code and data, and non-privileged code and data in the same time. This should open up the virtual memory and disable the segmentation effect.

The processor uses the segment selectors (segment registers cs , ds , ss ...) to find out the right segment (once again, the segmentation is must).

Every segment selector is 16 bit size and has the following layout ( source ):

在此输入图像描述

  • The first two bits indicates that privilege level, x86 supports 4 levels, but only two of them actually used ( 00 highest, and 11 lowest).

  • The third bit indicates the table should be used, mostly 0 , the GDT.

  • The rest 13 bits indicates the segment index.

If you interpreted the 0x08 that is loaded in cs , it will be in binary:

0000000000001     0         00
index 1 (code)   GDT    privileged

and the 0x10 that is loaded in ds , ss , ... :

0000000000010     0         00
index 2 (data)   GDT    privileged

If you read the segment selectors of any user mode program you should see that the cs value is 27 ( 0x1b ) which means:

0000000000011     0         11
index 3 (code)   GDT   non-privileged

and the data selectors ds , ss , ..., should store 35 ( 0x23 ):

0000000000100     0         11
index 4 (data)   GDT   non-privileged

The data segments selectors (registers), can be easily modified using simple mov instruction, but the cs can't be used with mov , so you use jmp 0x08:OFFSET to load the segment configurations into the the code segment selector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM