加载GDT后

问题描述 投票:1回答:1
# Load the GDT.
mov $gdt_descriptor, %ecx
lgdt (%ecx)
mov $0x10, %cx
mov %cx, %ds
mov %cx, %es
mov %cx, %fs
mov %cx, %gs
mov %cx, %ss
ljmp $0x8, $1f
1:  mov $kernel_stack, %esp

我无法理解这段代码的作用。为什么在加载GDT后将mov $ 0x10转换为cx然后再转到其他寄存器? ljmp指令有什么作用?

assembly x86 operating-system att gdt
1个回答
3
投票

它从lgdt告诉CPU的新GDT加载段描述符缓存(在CPU内部)。

更改表条目或更改表指向的位置时,CPU内部的段描述不会自动更新。

您甚至可以切换回实模式,DS base = 0 limit = 4GiB(ES和SS相同),并在实模式下使用32位地址,直到下一个mov ds, r16pop ds指令覆盖缓存的段描述。 (这被称为big / huge unreal mode,如果你也为CS做的那么大,但这不太方便,因为实模式中的中断只保存IP,而不是EIP。)

ljmp是一个far jmp,它设置CS(在这种情况下使用与数据描述符不同的描述符)。 x86不允许movpop设置CS,只是跳远。据推测,CPU不会通过此跳转来改变模式,否则asm源需要使用.code32.code16指令。

目标是1:标签,在forward方向。所以mov%esp用GDT索引1中的任何代码段设置进行解码/运行。(段选择器的低3位是权限位,因此$8是GDT索引1,$0x10是GDT索引2。)

mov%ss从设置%esp的指令中分离出来有点奇怪,因为x86会自动推迟中断,直到mov之后的指令到SS。这允许您在不使用cli / sti的情况下以原子方式设置SS:SP,但可能此代码在已禁用中断的情况下运行。此代码可能仅在启动期间运行一次,因此只需在设置新GDT和IDT所需的时间内禁用中断即可。

© www.soinside.com 2019 - 2024. All rights reserved.