1

我目前正在开发内核,在实现系统调用时遇到了一个神秘的问题。我这样编写第 0x80 个中断处理程序:

sys_call_s:
    pushad
    call sys_call
    popad
    iret

“sys_call”是做实际工作的 C 函数的名称。问题是:执行“int 0x80”的下一条指令时出现三重错误。例如,我在执行下面程序的第三行时出错,最后 bochs 将自行重置。

abc: mov eax,0              ; 0 means system call get_pid()
     int 0x80
     mov [pid_father],eax   ; this is the instruction caused bochs to triple fault
     mov eax,1              ; 1: fork()
     int 0x80
     jmp $

pid_father:  dd 0

更奇怪的是,当我用“ret”代替“iret”指令时,程序运行良好,并在“jmp $”处自行旋转。

有谁知道我为什么会遇到这个问题?

[编辑] 现在我认为这个问题是由堆栈指针的错误地址引起的。我为这个进程映射了一个页面,这个页面的物理地址是0x401000,线性地址是0x800000(8M)。我已将此进程的堆栈指针设置为 0x800ff0,但每次我在 bochs 中使用“print-stack”命令时,输出都是:“物理地址不适用于线性 0x00801000”。我该如何解决?

[编辑] 现在我发现在这个过程中我无法访问数据。例如,当我将“mov [pid_father],eax”放在“int 0x80”之前时,bochs 会自行重置。为什么会这样?

4

1 回答 1

1

我认为您需要显示 GDT 和 DS 寄存器和分页表的内容。如果您在没有任何其余代码的情况下看到该行上的三重错误,那么这意味着对 [pid_father] 的访问是问题所在。数据段无效,或页面无效或标记为只读,导致 GPF 或页面错误异常。GPF 或页面错误异常正在失败(可能出于相同或不同的原因),这会导致双重错误异常,该异常再次失败会导致 CPU 发生三重错误并重置。

Bochs 通常非常擅长(从记忆中)打印出故障的原因。您可能想要稍微向上滚动历史并查找引发的第一个异常。

于 2013-05-05T06:39:14.367 回答