我目前正在开发一个内核,并在执行系统调用时遇到一个神秘的问题。我写这样的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
更strangly,当我以“RET”的“IRET”指令时,程序工作正常,在“JMP $”旋本身。
有没有人有任何想法,为什么我得到这个问题?
现在我认为这个问题是由堆栈指针的错误地址引起的。我为这个过程配了一个页面,这个页面的物理地址是0x401000,线性地址是0x800000(8M)。我已将此进程的堆栈指针设置为0x800ff0,但每次在bochs中使用“print-stack”命令时,输出为:“物理地址不可用于线性0x00801000”。我该如何解决它?
现在我发现我无法在这个过程中访问数据。例如,当我在“int 0x80”之前放置“mov [pid_father],eax”时,bochs会重置其自身。为什么会发生?
感谢您的提示,斯图尔特。 – 2013-05-05 07:04:13
问题位于页面表中。我没有在相应的页表项中设置可写标志。所以,每次我写这个页面时,我都会遇到保护错误。 当使用指令“ret”从中断处理程序返回时,代码段的选择器是0x10,它是内核的代码选择器,并且此段中的代码有权读/写任何页面的访问权。这解释了为什么第一个过程beheaviors用“ret”代替“iret”指令后。 – 2013-05-05 07:15:11
真的吗?我认为页面保护会覆盖选择器保护,所以如果页面表被标记为只读,那么不管当前代码段如何,页面都是只读的。顺便说一句 - 你没有提到你启用了分页功能。这将是一件有用的事情。 – Stewart 2013-05-05 19:20:03