长模式下 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 的基数。
此代码存根提取自 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 的基数。