【问题标题】:What to do in interrupt handler for divide by zero?在除以零的中断处理程序中做什么?
【发布时间】: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


【解决方案1】:

您是对的,在这种特殊中断的情况下,这些都不是特别好的事情。正如 cmets 中所提到的,由于您拥有指令的地址,因此您可以获取该地址处的任何内容,解码指令,然后将指针推进到下一个地址......但代码不会期待这一点!

在 POSIX 操作系统中,这种异常行为由 SIGFPE 信号覆盖。如果您正在编写一个操作系统并且想要遵循 POSIX,那么您的中断处理程序应该将该信号发送到该进程。如果进程有该信号的处理程序,则跳转到该信号并允许进程处理它(例如,这就是高级语言中的 try/catch 块的工作方式......现在你知道为什么异常很慢!)。如果没有信号处理程序,则应终止该进程(并重新进入您的调度程序以确定下一步该做什么......并希望它是 PID 1!)。

当然,这是您的操作系统,如果您不想遵循 POSIX,则没有理由!如果您有其他奇特的方式来处理用户程序中的错误,那么您可以实现它。

【讨论】:

  • 我想说:做任何 Linux 做的事,但 POSIX 当然更好 :-)
  • 哦,ANSI C也提到了(虽然我不认为它需要被零除),所以它肯定应该在操作系统中使用。
【解决方案2】:

一般来说,编码错误只有两种选择:

a) 终止进程。这可能包括也可能不包括做其他事情(记录错误、创建核心转储等)。

b) 允许进程(甚至不能正常执行)尝试自己的恢复(这比正常执行更难做和测试)。信号就是一个例子。

【讨论】:

    猜你喜欢
    • 2020-12-09
    • 2015-03-02
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 2021-07-30
    相关资源
    最近更新 更多