繁体   English   中英

在bootloader中远程跳转gdt

[英]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

我无法理解这段代码的作用。 flush_gdt是一个标签okay,然后lgdt [gdtr]加载gdtr寄存器中的48-bit指针, gdtrjmp 0x08:complet_flush

jmp指令有什么作用? 然后我们为什么要将0x10移动到ax,然后移动到其他寄存器

x86支持两种虚拟内存方案( 在此处阅读 ):

  • 必须使用分段表GDT管理分段。
  • 分页,可选,使用页表管理,PDT。

大多数操作系统都希望使用分页而不希望分段,但必须禁用它。

所以诀窍是禁用它的效果,因为它不在那里。 这通常可以通过创建4个大的重叠段描述符(在空段旁边)来完成:

  • 段索引0:空段描述符
  • 段索引1:特权(内核)模式的代码段描述符
  • segment index 2:特权(内核)模式的数据段描述符
  • 段索引3:非特权(用户)模式的代码段描述符
  • 段索引4:非特权(用户)模式的数据段描述符

所有这些段从0x00000000开始到0xffffffff ,因此您最终会得到重叠的大段,即特权代码和数据,以及同时非特权的代码和数据。 这应该打开虚拟内存并禁用分段效果。

处理器使用段选择器(段寄存器csdsss ...)来找出正确的段(再一次,必须进行分段)。

每个段选择器都是16位大小,并具有以下布局( ):

在此输入图像描述

  • 前两位表示权限级别,x86支持4个级别,但实际使用的只有两个级别( 00最高, 11最低)。

  • 第三位表示应该使用表格,大部分是0 ,GDT。

  • 其余13位表示段索引。

如果您解释了在cs加载的0x08 ,它将是二进制的:

0000000000001     0         00
index 1 (code)   GDT    privileged

以及dsss ,...中加载的0x10

0000000000010     0         00
index 2 (data)   GDT    privileged

如果您读取任何用户模式程序的段选择器,您应该看到cs值为270x1b ),这意味着:

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

数据选择器dsss ,...应存储35( 0x23 ):

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

数据段选择器(寄存器)可以使用简单的mov指令轻松修改,但cs不能与mov一起使用,因此使用jmp 0x08:OFFSET将段配置加载到代码段选择器中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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