Assembly 这个hvmloader.c引导加载程序代码是做什么的?

Assembly 这个hvmloader.c引导加载程序代码是做什么的?,assembly,x86,bootloader,real-mode,Assembly,X86,Bootloader,Real Mode,我阅读了xen的代码,找到了下面的代码。但我不知道这是什么意思。是该代码初始化了idt和gdt?是从实际模式跳到保护模式的代码吗?如果是,则gdt和idt的物理地址在哪里? Hvmloader.c: asm ( " .text \n" " .globl _start \n" "_start: \n" /* C runtime kick

我阅读了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"
    );

谢谢。

从代码开始:

cld
-清除方向标志

cli
-清除中断标志以屏蔽中断

lgdt gdt_desr
-将
gdt_desr
的值加载到
gdt
中。在源代码中查找
gdt\u 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
以外的所有段寄存器)

跳远/跳远到
STR(SEL\u CODE32):0x1f
,实际上将
cs
设置为
STR(SEL\u CODE32)
,并将
eip
设置为
0x1f

如果这是32位代码段,处理器将进入32位保护模式。看见但是,我在这里没有看到用于设置
cr0
寄存器的
PE
位的代码,如上述示例和中所示

在那行代码之后,
cs:eip
移动到该地址(
STR(SEL_CODE32):0x1f
),这段代码中没有显示,所以我不能说接下来会发生什么。如果
cs:eip
指向下一行(如果这是跳转地址),则它也可能在下一行继续。无论如何,其余的代码和注释看起来像是用于从保护模式切换回真实模式的代码


指令
lidt 1f-trampoline\u start
1f-trampoline\u start
的值加载到
idt
中,以便了解实际使用的值,搜索源代码以查找
if-trampoline\u start

在我看来,大多数工作都是将CPU设置回实模式以跳转到BIOS重启地址(实模式内存结束前16个字节=0xFFFF0)。实际工作在main中完成,大约三分之一的时间调用main。至于其余细节,我将把它留给了解此类内容的人。对于感兴趣的人,这里是Xen的源文件,其中包含以下代码:
"    ljmp $"STR(SEL_CODE32)",$1f \n"