【问题标题】:Change GDT and update CS while in long mode在长模式下更改 GDT 并更新 CS
【发布时间】:2016-03-19 19:10:43
【问题描述】:

我正在编写一个简单的自制 64 位操作系统,通过 UEFI 启动它。这意味着当我的代码开始执行时,它已经处于长模式,并启用了分页。

现在,在退出 UEFI 引导服务后,我想将 UEFI 构建的所有控制结构替换为我自己的。

成功更改CR3(分页结构)的内容后,我使用lgdt成功加载了一个新的GDT。

问题是,现在,为了正确使用这个新的 GDT,我需要将一个新值移动到 CS 中。在网上我找到了很多关于如何从 32 位切换到 64 位的教程,但几乎没有关于长模式到长模式的教程。

我认为我应该使用远跳,但我没能用这段代码(AT&T 语法)做到这一点:

mov %rax, %cr3   # load paging structures (it works)
lgdt 6(%rcx)     # load gdt (it works)
mov $100, %rsp   # update stack pointer (it works)

# now what I tried unsuccessfully:
pushw $8         # new code segment selector
pushq fun        # function to execute next
retfq            # far return (pops address and code segment)

没有任何 IDT,此代码在 retfq 处出现三重错误。

编辑:我检查了我的分页结构,我很确定它们不是问题的原因。事实上,没有最后三个指令,代码运行良好。问题是我需要一种更新 CS 的方法,在我的代码中仍然指的是 UEFI 构建的旧段。 retfq 是这样做的正确方法吗?或者我应该使用哪个其他指令?

提前致谢。

【问题讨论】:

  • 信息不足。见minimal reproducible example。你怎么知道你声称的事情是有效的?旁注,您应该使用pushq $8,因为retfq 需要一个qword。另外我希望你知道rsp 仍然是指当前(缓存的)堆栈段,所以pushretf 将使用它。最后,使用未对齐的rsp 通常是不受欢迎的,即使 cpu 会接受它。
  • @Jester 我确信某些指令有效,因为我独立测试了它们并且代码运行良好。另外,旧的堆栈段也可以,因为它覆盖了所有的地址空间(实际上,在长模式下,所有段都覆盖了整个地址空间,并且仅用于访问权限;段限制总是被忽略;段基仅有效fsgs)。
  • 是的,但是分页可能会将地址100 映射到一些无法访问的内存中。
  • @Jester 你是对的。我应该指定我多次检查了我的分页结构,它们看起来没问题。
  • 嗯,你的意思是pushq $fun 可能吗?另请注意,立即推送仅对扩展的 32 位进行符号化。我使用的代码更像:sub $16, %rsp; movq $8, 8(%rsp); movabsq $fun, %rax; mov %rax, (%rsp); lretq.

标签: assembly 64-bit x86-64 osdev gdt


【解决方案1】:

看起来主要问题是一个简单的错字。在 at&t 语法中,pushq funpushq $fun 表示非常不同的东西,前者将内存中的 8 个字节推送到地址 fun,而后者推送fun 的地址(假设它适合 32 位符号扩展立即数) .

也就是说,lretq 还期望选择器是一个完整的 8 字节 qword,所以 pushw $8 应该真的是 pushq $8。只要额外的 6 个字节可读,字大小的推送仍然有效,但它会使堆栈不平衡。如果您重新加载堆栈指针,这可能无关紧要。

避免上述所有陷阱的替代代码如下所示:

sub $16, %rsp
movq $8, 8(%rsp)
movabsq $fun, %rax
mov %rax, (%rsp)
lretq

【讨论】:

  • 我是赞成票。我本来希望 OP 也有。
  • 如果已知 fun 小于 jmpq *fun_ptr; fun_ptr: .quad $fun; .word $8 或 32 位等效项。
  • 谢谢。直到现在我才弄清楚如何在长模式下进行远跳。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-13
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多