中断会导致 CPU 将 EFLAGS、CS 和 IP 寄存器保存到“堆栈”中,然后 iret 指令将它们从堆栈中弹出。这个堆栈在哪里?CPU如何知道它(我假设某个地方有一些寄存器)?我想要肮脏的细节。我正在研究基于 Unix 的系统。说Linux。
3 回答
首先,查看英特尔手册了解所有细节: http: //www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html
至于你的问题:
堆栈位于何处?
在中断时,x86 内核从任务状态段 (TSS) 加载堆栈指针。IDT 通过任务选择器字段指定要使用的 TSS。在 32 位模式下,TSS 提供 4 个堆栈指针,每个保护级别一个。由于保护级别通常只有 0 或 3,因此只有两个堆栈相关。在 64 位模式下,中断描述符条目可以选择指定索引 0-7,在给定的 64 位 TSS 中使用哪个堆栈指针。但是,由于重入问题,这种 64 位堆栈选择机制大部分都被破坏了,并且操作系统求助于软件切换。查看 x86 程序员参考卷 3,图 7-2。
如果中断将内核移动到更高的特权级别(数值上较低的 CPL),那么内核会将中断堆栈帧推送到这个新堆栈上,而不是被中断进程的当前堆栈。如果特权级别保持不变,那么内核只是将中断堆栈帧推送到当前堆栈上。
CPU是怎么知道的?
中断描述符表 (IDT) 为每个中断向量提供一个描述符,0-255。描述符条目告诉内核使用哪个 TSS(即堆栈),用户模式是否可以通过向量调用,是否在 ISR 条目上禁用中断等。参见 PRM 第 3 卷第 6 章。所以,所有的中断处理都是真的由 IDT 中的信息锚定。
中断不会导致操作系统保存 EFLAGS、CS 和 IP。CPU 自己执行此操作,无需操作系统。
第一个堆栈是由复位后在 CPU 上执行的第一个代码建立的。通常它是首先执行此操作的 ROM BIOS 代码。它设置 SS 和 SP 寄存器以指示堆栈位置。然后堆栈可以并且通常是由引导加载程序更改/移动,然后它可能会被内核再次移动。
只要有足够大小的可读可写内存,上述代码段想要定位堆栈的任何位置都可以。
SS:(E)SP - SS(堆栈段) SS 是 CPU 内部可用的 16 位寄存器,(E)SP 是 16(实模式)、32、64 位大小的保护模式。
- 在初始 BIOS POST 时,有效的 SS:(E)SP 由 BIOS 设置。
- BIOS 将控制权交给 MBR,然后在您的 MBR 引导加载程序代码中,您可以重置并设置有效的 SS:(E)SP 值。
- 在保护模式下,我们需要为添加段CS,DS,SS设置有效的GDT值,然后将适当的值加载到段中是CPU的责任,因为这个OS应该协调。