我正在编写一个小型操作系统,它将在用户模式下执行一些代码(权限级别3).从该用户级代码,我想将中断调回到打印消息的操作系统.现在我真的不关心我的中断处理程序如何接受参数或类似的东西,我真的只想要一个中断处理程序来通知我(用户)代码已执行.
我的问题是:如何在用户模式下运行代码?我有一个函数,它设置一个带有代码段和数据段的本地描述符表(都具有用户模式权限).我不明白是我应该如何这些段装入cs,ss和ds.我成功加载了我的LDT,但我不知道如何实际使用它.我听说我应该使用iret,但我不知道具体如何.
我的另一个问题是我的中断处理程序应该如何工作.假设我为向量号0x40安装了一个中断处理程序,我想打印"你好,用户模式!".我知道如何设置中断处理程序,但我不完全理解从用户模式进入内核中断处理程序时如何切换上下文.我知道cs寄存器必须更改,因为我的例程将从我的IDT条目中指定的代码段运行.我也明白堆栈选择器可能也会改变,但我无法确定.
有人可以向我解释当调用中断门时会发生什么情况变化吗?
ugh*_*fhw 23
可以使用环3来完成,iret因为它的工作方式已被记录.当您收到中断时,处理器会按下:
iret通过撤消步骤1-3(ISR负责在必要时撤消步骤4).我们可以通过将所需信息推送到堆栈并发出iret指令来使用此事实来获得响铃3 .确保代码和堆栈段中具有正确的CPL(应在每个段中设置低两位).但是,iret不会更改任何数据段,因此您需要手动更改它们.您可以使用该mov指令执行此操作,但在执行此操作和切换环之间,您将无法读取堆栈外的数据.
cli
mov ax, Ring3_DS
mov ds, eax
push dword Ring3_SS
push dword Ring3_ESP
pushfd
or dword [esp], 0x200 // Set IF in EFLAGS so that interrupts will be reenabled in user mode
push dword Ring3_CS
push dword Ring3_EIP
iret
Run Code Online (Sandbox Code Playgroud)
如果您需要一个完整的工作示例,请参阅本教程.
发出中断时,处理器会读取您的IDT以获取ISR的正确代码段和指令指针.然后它会查看您的TSS以找到新的堆栈段和指针.它改变ss和esp适当的,然后将旧值到新的堆栈.它并没有改变任何数据段寄存器.如果需要访问ISR中的内存,则必须手动执行此操作.