长模式下 amd64 中的零堆栈段

Zero stack segment in amd64 in long mode

此代码存根提取自 linux 内核 3.18.3,arch/x86/boot/compressed/head_64.S。虽然添加了额外的评论。

所有这些代码都在长模式(64 位)下执行,代码段选择器:0x10 和数据段选择器:0x18

xorl    %eax, %eax /* Setting up all data segments selectors to zero */
movl    %eax, %ds  /* Including stack segment */
movl    %eax, %es
movl    %eax, %ss
movl    %eax, %fs
movl    %eax, %gs

leaq    z_extract_offset(%rbp), %rbx

/* Set up the stack */
leaq    boot_stack_end(%rbx), %rsp

/* Zero EFLAGS */
pushq   [=10=] /* This instruction should fail since stack segment selector */
popfq      /* is zero (pointing to null descriptor) /*

据我所知,这段代码应该无法执行,因为在执行堆栈指令 pushq 时,%ss = 0x0 指向 gdt 中的空描述符。

尽管如此,这似乎可行,所以我想我遗漏了一些信息。 为什么这样做有效?

在 64 位模式下大部分禁用分段,仅使用 CS 的属性以及 FS 和 GS 的基数。