abk*_*kds 8 x86 assembly bootloader gdt
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
Run Code Online (Sandbox Code Playgroud)
我无法理解这段代码的作用.flush_gdt是一个标签好,然后lgdt [gdtr]将48-bit指针加载到gdtr寄存器中,然后从中加载jmp 0x08:complet_flush.
jmp指令有什么作用?然后我们为什么要将0x10移动到ax,然后移动到其他寄存器
小智 17
x86支持两种虚拟内存方案(在此处阅读):
大多数操作系统都希望使用分页而不希望分段,但必须禁用它.
所以诀窍是禁用它的效果,因为它不在那里.这通常可以通过创建4个大的重叠段描述符(在空段旁边)来完成:
所有这些段从开始0x00000000达到0xffffffff,所以你最终重叠大段是在同一时间特权代码和数据,非特权代码和数据.这应该打开虚拟内存并禁用分段效果.
处理器使用段选择(段寄存器cs,ds,ss...),找出正确的段(再次分割是必须).
每个段选择器都是16位大小,并具有以下布局(源):

前两位表示权限级别,x86支持4个级别,但实际使用的只有两个级别(00最高和11最低).
第三位表示应该使用表格,主要0是GDT.
如果你解释了0x08加载的那个cs,它将是二进制的:
0000000000001 0 00
index 1 (code) GDT privileged
Run Code Online (Sandbox Code Playgroud)
而0x10被加载在ds,ss...:
0000000000010 0 00
index 2 (data) GDT privileged
Run Code Online (Sandbox Code Playgroud)
如果您阅读任何用户模式程序的段选择器,您应该看到cs值为27(0x1b),这意味着:
0000000000011 0 11
index 3 (code) GDT non-privileged
Run Code Online (Sandbox Code Playgroud)
和数据选择器ds,, ss...应该存储35(0x23):
0000000000100 0 11
index 4 (data) GDT non-privileged
Run Code Online (Sandbox Code Playgroud)
数据段选择器(寄存器)可以使用简单的mov指令轻松修改,但cs不能与之一起使用mov,因此您可以使用jmp 0x08:OFFSET将段配置加载到代码段选择器中.