我正在编写一个简单的自制 64 位操作系统,通过 UEFI 启动它。这意味着当我的代码开始执行时,它已经处于长模式,并启用了分页。
现在,在退出 UEFI 引导服务后,我想用我自己的替换 UEFI 构建的所有控制结构。
成功更改 CR3(分页结构)的内容后,我使用lgdt
.
问题是现在,为了正确使用这个新的 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
正确的方法吗?或者我应该使用哪个其他指令?
提前致谢。