几个月来,我一直在研究“自制”操作系统。 目前,它启动并进入32位保护模式。 我已经加载了中断表,但还没有设置分页(还)。操作系统开发:如何避免例外程序后的无限循环
现在在编写我的异常例程时,我注意到当一条指令抛出一个异常时,异常例程就会执行,但是CPU会跳回到引发异常的指令!这并不适用于每一个异常(例如,一个div零异常会跳回指令除法指令之后),但是让我们考虑下面的一般保护性异常:
MOV EAX, 0x8
MOV CS, EAX
我的例行很简单:调用显示红色错误消息的函数。
结果:MOV CS,EAX失败 - >我的错误消息显示 - > CPU跳回到MOV CS - >无限循环垃圾邮件错误消息。
我在操作系统和unix安全方面与老师讨论过这个问题。 他告诉我他知道Linux有办法绕过它,但他不知道哪一个。
幼稚的解决方案是从例程中解析抛出指令,以获得该指令的长度。 该解决方案非常复杂,我感到有点不舒服,在每个受影响的例外程序中增加一个相对较重的功能的呼叫...
因此,我想知道是否是解决问题的另一种方法。也许有一个“神奇”的寄存器,包含一点可以改变这种行为?
-
非常感谢您提前任何建议/信息。
-
编辑:好像很多人想知道为什么我想跳过有问题的指示,恢复正常运行。
我有两个方面的原因:
首先,杀的过程将是一个可能的解决方案,而不是一个干净的。这不是它在Linux中的做法,例如,内核发送信号(我认为是SIGSEGV),但不会立即中断执行。这很有意义,因为应用程序可以阻止或忽略信号并恢复自己的执行。这是一个非常优雅的方式来告诉应用程序它做了错误的国际海事组织。
另一个原因:如果内核本身执行非法操作会怎么样?可能是由于一个错误,但也可能是由于内核扩展。正如我在评论中所说:在这种情况下我应该怎么做?我只需要杀死内核并用笑脸显示一个漂亮的蓝屏?
这就是为什么我希望能够跳过指令。 “猜测”指令的大小显然不是一种选择,解析指令看起来相当复杂(不是我介意实现这样的例程,但我需要确保没有更好的方法)。
我明白你的观点。我知道继续执行产生段错误的进程是没有意义的,但我只是想*做到这一点,主要是出于好奇。 从我目前所了解的情况来看,不可能以简单的方式来完成(例如,没有定义中断行为的神奇寄存器)。 – 2012-02-08 15:05:35
如果你确实想要做到这一点,那么你必须实现一个解码器来确定RAM中原始字节的指令长度。对于80x86(可变长度指令,前缀等)这将是一大笔工作。一旦你得到了它的“工作”,它在某些情况下仍然不起作用。例如,想象一下由“页面不存在”导致的页面错误 - 您无法尝试解码不存在的字节。 – Brendan 2012-02-08 15:18:28
我知道这将是一个大量的工作。没有想到页面错误,但这不是一个很大的问题(至少在我的情况下,还没有)。 – 2012-02-08 15:47:03