我正在开发内核并在实现系统调用时遇到一个神秘的问题。我像这样编写0x80th中断处理程序:
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 $”旋转。
有谁知道我为什么会遇到这个问题?
[edit]现在我认为这个问题是由堆栈指针的错误地址引起的。我为这个过程添加了一个页面,这个页面的物理地址是0x401000,线性地址是0x800000(8M)。我已将此进程的堆栈指针设置为0x800ff0,但每次在bochs中使用“print-stack”命令时,输出为:“物理地址不可用于线性0x00801000”。我该如何解决?
[edit]现在我发现在这个过程中我无法访问数据。例如,当我在“int 0x80”之前放置“mov [pid_father],eax”时,bochs重置自己。为什么会这样?
答案 0 :(得分:1)
我认为您需要显示GDT和DS寄存器和分页表的内容。如果您在没有任何其余代码的情况下看到该行上的三重错误,那么这意味着访问[pid_father]是个问题。数据段无效,或页面无效或标记为只读,这会导致GPF或页面错误异常。 GPF或页面错误异常失败(可能是出于同样的原因,或者是另一个原因),这会导致双重故障异常,再次失败导致CPU出现三重故障并重置。
Bochs通常很好(从记忆中)打印出它出现故障的原因。您可能需要稍微向上滚动历史记录并查找引发的第一个异常。