【发布时间】:2016-01-06 21:10:39
【问题描述】:
操作系统中断处理程序应该如何处理与编码错误相关的中断?
例如,我尝试除以 0 来测试我的中断,然后我的中断处理程序被调用。但是,由于 div 指令没有成功执行,EIP 并没有更新到它之后的下一条指令,并且在以iret 从中断处理程序返回后,它又回到了错误的div 指令。
mov ax, 3
mov dl, 0
div dl ; go back here again and again
处理此中断的正确方法是什么?我想到的几个方法:
将
dl更改为0以外的其他值。但是,我不确定dl是否可以在发生某些事情时保留,并且中断例程应该在退出后恢复寄存器,我不知道通过提供错误的计算来默默地纠正错误是好的。检索
div之后的下一条指令。但是,我还没有想到任何简单可靠的方法来获取下一条指令。将当前包含返回地址的栈顶修改为其他代码的地址。因此,我们不再返回
div指令。
【问题讨论】:
-
在除法前检查除数是否为0,并在执行前将其标记为错误?但是,如果您真的想要这样做,您可以通过零中断处理程序在您的 Div 中解码指令(在返回地址),然后计算当前指令的长度(出错的指令)和然后通过添加指令的长度来更新返回地址。这将产生在下一条指令处重新启动的效果(说起来容易做起来难)。您的最后一个想法经常被使用,并且更合理(返回到通用错误处理程序)。
-
@Michael Petch 我正在编写操作系统级别的中断处理程序,所以我不能假设用户空间程序会这样做。我想我会解决将执行流程重定向到其他代码,因为我们不能尝试“纠正”计算或继续使用垃圾值执行下一条指令并使一切都出错。可能这就是为什么在 C 程序中尝试除以 0 时,它会给出
floating point exception(使用gcc编译)并停止程序。 -
如果你正在编写一个操作系统,那么在 DIV 上为零我会在堆栈上放置一个操作系统错误处理程序作为返回地址并返回到该地址以终止用户程序并通知他们原因(被零除)。如果用户空间程序想要覆盖它,那么您的操作系统可以为用户程序提供某种类型的系统调用来注册错误处理程序。如果用户空间程序注册了一个处理程序,则该处理程序在执行 IRET 之前被放置在堆栈上。具体情况取决于您开发操作系统的方式。
-
如果您正在编写 POSIX 操作系统,那么正确的做法是将 SIGFPE 传递给进程(这将终止该进程,除非它们安装了信号处理程序)。
-
@MichaelPetch 感谢您的回答。你能把它作为一个答案,所以我可以接受吗?
标签: assembly x86 operating-system nasm