현재 커널을 개발 중이며 시스템 호출을 구현할 때 신비한 문제가 발생합니다. 다음과 같이 0x80th 인터럽트 처리기를 작성합니다.인터럽트 처리기에서 이상한 동작이 발생했습니다.
sys_call_s:
pushad
call sys_call
popad
iret
"sys_call"은 실제 작업을 수행하는 C 함수의 이름입니다. 문제는 : "int 0x80"의 다음 명령을 실행할 때 트리플 오류가 발생했습니다. 예를 들어, 프로그램의 세 번째 행을 실행할 때 오류가 발생하고 마지막으로 boch가 스스로 재설정됩니다.
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에 사용할 수 없습니다"라는 출력이 표시됩니다. 어떻게 해결할 수 있습니까?
[편집] 이제이 프로세스에서 데이터에 액세스 할 수 없음을 알게되었습니다. 예를 들어 "mov [pid_father], eax"를 "int 0x80"앞에두면 bochs가 자체를 재설정합니다. 왜 이런 일이 일어난거야?
힌트를 보내 주셔서 감사합니다. 스튜어트. –
문제는 페이지 테이블에서 찾습니다. 해당 페이지 테이블 항목에 쓰기 가능 플래그를 설정하지 않았습니다. 따라서이 페이지에 글을 쓸 때마다 보호 오류가 발생합니다. "ret"명령어를 사용하여 인터럽트 핸들러에서 복귀하는 경우 코드 세그먼트의 선택자는 커널의 코드 선택기 인 0x10이며이 세그먼트의 코드는 모든 페이지에 대한 읽기/쓰기 권한이 있습니다. 이것은 바로 "iret"명령을 "ret"로 대체 한 직후의 첫 번째 프로세스 beheaviors를 설명합니다. –
정말요? 나는 페이지 보호가 선택 자 보호를 초과한다고 생각했기 때문에 페이지 테이블이 읽기 전용으로 표시된 경우 페이지는 현재 코드 세그먼트와 상관없이 읽혀진다. BTW - 페이징을 사용할 수 있음을 언급하지 않았습니다. 그것은 언급 할만한 유용한 것이었을 것입니다. – Stewart