首页 文章

保护模式初始化期间的堆栈结构

提问于
浏览
0

我'm working on a simple kernel that follows the multiboot specification. This is for a class project, so I can' t直接发布我的代码,但对于我的问题,它's sufficient to say that we'重新使用multiboot sample code的修改版本 .

我一直在关注OSDev维基的GDT Tutorial . 在本教程中,他们的平面保护模式示例代码只是从堆栈中加载两个值并将它们放入GDTR . 这让我感到困惑,因为我认为应该在堆栈初始化之前设置GDTR . 我还没有初始化它 . 我想's possible that GRUB sets it to something before jumping to any of the code in boot.S, but I haven'能够找到任何建议的文件 .

tl; dr - 为什么OSDev GDT Tutorial在加载全局描述符表的地址和大小时从相对于ESP的地址检索数据?

1 回答

  • 1

    如果没有正确设置GDT,你无法在保护模式下做很多事情,GRUB显然必须不仅为你而且为自己做 . 话说

    'CS'必须是32位读/执行代码段,偏移量为'0',限制为'0xFFFFFFFF' .

    暗示具有正确设置的代码段描述符的GDT和加载了选择该描述符的选择器的CS寄存器 .

    setGdt子例程接受堆栈上的参数 . 这使得从C代码调用它很方便(32位x86 C / C编译器,如gcc和Microsoft Visual C,其他几个支持这种调用约定;请参阅cdecl) .

    但是,在调用setGdt之前,甚至在将参数推送到堆栈之前,您需要设置堆栈,因为这种语言:

    'ESP'操作系统映像必须在需要时立即创建自己的堆栈 .

    请注意,该页面的boot.S文件中的示例代码执行此操作:

    /* The size of our stack (16KB). */
    #define STACK_SIZE                      0x4000
    ...
    multiboot_entry:
                /* Initialize the stack pointer. */
                movl    $(stack + STACK_SIZE), %esp
    ...
                /* Our stack area. */
                .comm   stack, STACK_SIZE
    

    应该是不言自明的 .

    现在,当您将选择器加载到段寄存器中时,段基址和段限制(以及段访问权限)将缓存在CPU中 . 因此,在下一次加载到段寄存器之前,在运行代码下更改GDT或GDTR将不起作用 .

相关问题