我读了xen的代码并找到下面的代码。但我不知道它的含义。它是初始化idt
和gdt
的代码吗?它是从实模式跳转到保护模式的代码吗?如果是,gdt
和idt
的实际地址在哪里?
Hvmloader.c:
asm (
" .text \n"
" .globl _start \n"
"_start: \n"
/* C runtime kickoff. */
" cld \n"
" cli \n"
" lgdt gdt_desr \n"
" mov $"STR(SEL_DATA32)",%ax \n"
" mov %ax,%ds \n"
" mov %ax,%es \n"
" mov %ax,%fs \n"
" mov %ax,%gs \n"
" mov %ax,%ss \n"
" ljmp $"STR(SEL_CODE32)",$1f \n"
"1: movl $stack_top,%esp \n"
" movl %esp,%ebp \n"
" call main \n"
/* Relocate real-mode trampoline to 0x0. */
" mov $trampoline_start,%esi \n"
" xor %edi,%edi \n"
" mov $trampoline_end,%ecx \n"
" sub %esi,%ecx \n"
" rep movsb \n"
/* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */
" mov $"STR(SEL_DATA16)",%ax \n"
" mov %ax,%ds \n"
" mov %ax,%es \n"
" mov %ax,%fs \n"
" mov %ax,%gs \n"
" mov %ax,%ss \n"
/* Initialise all 32-bit GPRs to zero. */
" xor %eax,%eax \n"
" xor %ebx,%ebx \n"
" xor %ecx,%ecx \n"
" xor %edx,%edx \n"
" xor %esp,%esp \n"
" xor %ebp,%ebp \n"
" xor %esi,%esi \n"
" xor %edi,%edi \n"
/* Enter real mode, reload all segment registers and IDT. */
" ljmp $"STR(SEL_CODE16)",$0x0\n"
"trampoline_start: .code16 \n"
" mov %eax,%cr0 \n"
" ljmp $0,$1f-trampoline_start\n"
"1: mov %ax,%ds \n"
" mov %ax,%es \n"
" mov %ax,%fs \n"
" mov %ax,%gs \n"
" mov %ax,%ss \n"
" lidt 1f-trampoline_start \n"
" ljmp $0xf000,$0xfff0 \n"
"1: .word 0x3ff,0,0 \n"
"trampoline_end: .code32 \n"
" \n"
"gdt_desr: \n"
" .word gdt_end - gdt - 1 \n"
" .long gdt \n"
" \n"
" .align 8 \n"
"gdt: \n"
" .quad 0x0000000000000000 \n"
" .quad 0x008f9a000000ffff \n" /* Ring 0 16b code, base 0 limit 4G */
" .quad 0x008f92000000ffff \n" /* Ring 0 16b data, base 0 limit 4G */
" .quad 0x00cf9a000000ffff \n" /* Ring 0 32b code, base 0 limit 4G */
" .quad 0x00cf92000000ffff \n" /* Ring 0 32b data, base 0 limit 4G */
" .quad 0x00af9a000000ffff \n" /* Ring 0 64b code */
"gdt_end: \n"
" \n"
" .bss \n"
" .align 8 \n"
"stack: \n"
" .skip 0x4000 \n"
"stack_top: \n"
" .text \n"
);
感谢。
答案 0 :(得分:1)
从代码的开头:
cld
- 明确指示标志。
cli
- 清除中断标志以屏蔽中断。
lgdt gdt_desr
- 将gdt_desr
的值加载到gdt
。在源代码中查找gdt_desr
,找出加载到gdt
的值。
" mov $"STR(SEL_DATA32)",%ax \n"
" mov %ax,%ds \n"
" mov %ax,%es \n"
" mov %ax,%fs \n"
" mov %ax,%gs \n"
" mov %ax,%ss \n"
将值STR(SEL_DATA32)
存储到ax
,然后从ax
存储到ds
,es
,fs
,gs
和ss
(除了cs
之外的所有段寄存器)。
" ljmp $"STR(SEL_CODE32)",$1f \n"
跳远/跳远到STR(SEL_CODE32):0x1f
,实际上将cs
设置为STR(SEL_CODE32)
,将eip
设置为0x1f
。
如果这是一个32位代码段,则处理器进入32位保护模式。见Stackoverflow question: bootloader - switching processor to protected mode。但是,我在这里没有看到用于设置PE
寄存器的cr0
位的代码,如上例和Wikipedia article on protected mode中所示。
在代码行cs:eip
移动到这段代码中未显示的地址(STR(SEL_CODE32):0x1f
)后,我不能说当时会发生什么。如果cs:eip
指向那里(如果那是跳转地址),它也可以在下一行继续。无论如何,其余代码和注释看起来就像用于从保护模式切换回实模式的代码。
Intruction lidt 1f-trampoline_start
会将1f-trampoline_start
的值加载到idt
,因此要了解所使用的实际值,请搜索if-trampoline_start
的来源。