几个月来,我一直在研究“自制”操作系统。目前,它启动并进入 32 位保护模式。我已经加载了中断表,但还没有设置分页(还)。
现在,在编写我的异常例程时,我注意到当一条指令引发异常时,异常例程会被执行,但随后 CPU 会跳回到引发异常的指令!这并不适用于所有异常(例如,除零异常将跳回到除法指令之后的指令),但让我们考虑以下一般保护异常:
MOV EAX, 0x8
MOV CS, EAX
我的例程很简单:它调用一个显示红色错误消息的函数。
结果:MOV CS,EAX 失败 -> 显示我的错误消息 -> CPU 跳回 MOV CS -> 无限循环发送错误消息。
我已经和一位操作系统和 unix 安全方面的老师讨论过这个问题。他告诉我他知道 Linux 有办法绕过它,但他不知道是哪一种。
天真的解决方案是从例程中解析抛出指令,以获得该指令的长度。该解决方案非常复杂,我觉得在每个受影响的异常例程中添加对相对繁重的函数的调用有点不舒服......
因此,我想知道这是否是解决问题的另一种方法。也许有一个“魔法”寄存器包含可以改变这种行为的位?
--
非常感谢您提前提供任何建议/信息。
--
编辑:似乎很多人想知道为什么我要跳过有问题的指令并恢复正常执行。
我有两个原因:
首先,杀死一个进程将是一种可能的解决方案,但不是一个干净的解决方案。这不是它在 Linux 中的做法,例如,(AFAIK)内核发送信号(我认为是 SIGSEGV)但不会立即中断执行。这是有道理的,因为应用程序可以阻止或忽略信号并恢复自己的执行。这是一种非常优雅的方式来告诉应用程序它做错了 IMO。
另一个原因:如果内核本身执行了非法操作怎么办?可能是由于错误,但也可能是由于内核扩展。正如我在评论中所说:在这种情况下我该怎么办?我应该杀死内核并显示一个带有笑脸的漂亮蓝屏吗?
这就是为什么我希望能够跳过指令。“猜测”指令大小显然不是一种选择,并且解析指令似乎相当复杂(我不介意实现这样的例程,但我需要确保没有更好的方法)。