인터럽트 핸들러에서 돌아 오기 전에 특정 예외로 눌린 오류 코드를 팝업해야합니까?

StackOverflow https://stackoverflow.com/questions/491613

문제

256 개의 항목이있는 IDT 테이블을로드했으며 모두 비슷한 핸들러를 가리 킵니다.

  • 예외 8 및 10-14의 경우 예외 번호를 눌렀습니다 (이 예외는 오류 코드를 자동으로 푸시합니다).
  • 다른 사람들의 경우 "더미"오류 코드와 예외 번호를 푸시하십시오.
  • 그런 다음 공통 핸들러로 이동하십시오

따라서 공통 핸들러가 들어 오면 스택이 올바르게 정렬되고 예외/인터럽트 번호, 오류 코드 (더미 일 수 있음), EFLAGS, CS 및 EIP가 포함됩니다.

내 질문은 인터럽트 핸들러에서 돌아 오는 것에 간주됩니다. 나는 사용한다 iret 스택에서 예외 번호와 오류 코드를 취한 후 돌아 오지만 예외 NR 8에는 작동하지 않습니다. 스택에 오류 코드를 남겨두면 괜찮습니다!

질문:

  • 오류 코드를 배치하는 예외를 위해 스택에 오류 코드를 남겨 두어야합니까? 그렇다면 어떻게해야합니다 iret 오류 코드를 팝업 해야하는지 여부를 결정하십시오.
  • 인터럽트를 활성화하자마자 항상 예외 8 (이중 결함)을 얻지 만 모든 것이 잘 실행됩니다 (취미 OS를 개발하고 있습니다). 이것은 정상적인 행동입니까, 아니면 어딘가에 버그가 있습니까?
도움이 되었습니까?

해결책

CPU가 오류 코드를 자동으로 푸시하면 핸들러가 ~ 해야 하다 전에 팝업하십시오 iret. 그만큼 iret 지시는 결함, 함정 또는 외부 인터럽트라면 어디에서 왔는지 알지 못합니다. 항상 동일하게 수행되며 스택에 오류 코드가 없다고 가정합니다.

SDM (Software Developer 's Manual), Volume 3, 5 장, 5.13 섹션에서 인용 한 오류 코드 :

오류 코드는 스택에서 더블 워드 또는 단어로 푸시됩니다 (기본 인터럽트, 트랩 또는 작업 게이트 크기에 따라 다름). 스택을 더블 워드 푸시에 맞게 유지하려면 오류 코드의 상단 절반이 예약됩니다. IRET 명령이 예외 핸들러에서 반환하기 위해 실행되면 오류 코드가 팝업되지 않으므로 핸들러는 반품을 실행하기 전에 오류 코드를 제거해야합니다.

당신은 찾을 수 있습니다 IA-32 소프트웨어 개발자 매뉴얼 여기: http://www.intel.com/products/processor/manuals/

제 3 권, 5 장 5 장에서는 예외 및 인터럽트 처리를 설명합니다. 제 2 권 1 부에는 사양이 있습니다 iret 지침.

다른 팁

나는 a 작은 x86 OS 얼마 전. 파일을 살펴보십시오 ISR.ASM CVS 저장소에서.

핸들러를 설정하는 방법에 주목하십시오. 대부분 오류 코드를 푸시하는 몇 개의 처리기를 설명하기 위해 더미 DWORD를 스택에 밀어 넣습니다. 그런 다음 IRET를 통해 돌아 오면 인터럽트에 관계없이 항상 스택에 2 개의 DWORDS를 가정하고 8 장 전에 추가 ESP를 수행하여 물건을 잘 정리할 수 있습니다.

그것은 당신의 첫 번째 질문에 대답해야합니다.

두 번째 질문에 관해서는 : 인터럽트를 활성화 할 때의 이중 결함은 ... hmmm은 제대로 설정하지 않으면 페이징에 문제가 될 수 있습니다. 백만 명의 다른 일이 될 수 있습니다 :)

인터럽트를 활성화하자마자 "이중 결함"과 비슷한 문제가있었습니다. 글쎄, 그들은 보였다 이중 결함처럼, 그들은 실제로 타이머 인터럽트였습니다!

이중 결함은 인터럽트 번호입니다 8.

불행히도, 기본 그림 구성은 타이머가 인터럽트 번호로 인터럽합니다. (DEFAULT_PIC_BASE + TIMER_OFFSET) = (8 + 0) = 8.

내 모든 사진 인터럽트를 마스킹하면 (그림을 올바르게 구성 할 준비가 될 때까지)이 더블 오류처럼 보이는 타이머 인터럽트를 침묵 시켰습니다.

(사진은 CPU가 다음을 생산하기 전에 인터럽트를 인정해야합니다. 코드는 초기 타이머 인터럽트를 인정하지 않았기 때문에 그림은 더 이상 당신에게 더 이상주지 않았습니다! .))

오류 코드를 배치하는 예외를 위해 스택에 오류 코드를 남겨 두어야합니까?

다른 사람들이 언급했듯이, 당신은 다음 중 하나를해야합니다.

pop %eax
/* Do something with %eax */
iret

또는 오류 코드를 무시하려면 :

add $4, %esp
iret

그렇지 않다면 iret 오류 코드를 새로운 CS로 해석하고 다음과 같이 언급했듯이 일반 보호 결함을 얻을 수 있습니다. 페이지 결함 핸들러에서 IRET이 인터럽트 13 (일반 보호 오류) 및 오류 코드 0x18을 생성하는 이유는 무엇입니까?

이 페이지 핸들러 작업을 최소화합니다 내가 이것을 설명하기 위해 만든 것. 댓글을 달아보십시오 pop 그리고 그것이 날아가는 것을 본다.

위를 a와 비교하십시오 부서 오류 예외 스택을 터뜨리지 않습니다.

당신이 간단하게하는 경우에 주목하십시오 int $14, 여분의 바이트는 밀리지 않습니다 : 이것은 실제 예외에서만 발생합니다.

Intel Manual Volume 3 시스템 프로그래밍 안내서 -325384-056US 2015 년 9 월 표 6-1. "보호 모드 예외 및 인터럽트"열 "오류 코드"에는 오류 코드를 푸시하는 인터럽트 목록이 포함되어 있습니다.

38.9.2.2 "페이지 오류 오류 코드"는 오류의 의미를 설명합니다.

이것을 다루는 깔끔한 방법은 더미 오류 코드를 푸시하는 것입니다. 0 일을 균일하게 만들기 위해이 작업을 수행하지 않는 인터럽트를위한 스택에서. 제임스 몰로이의 튜토리얼 정확히 그렇게합니다.

Linux 커널 4.2는 비슷한 일을하는 것 같습니다. 아래에 아치/x86/Entry/Entry64.S IT 모델은 인터럽트합니다 has_error_code:

trace_idtentry page_fault do_page_fault has_error_code=1

그런 다음 같은 파일에서 다음과 같은 파일을 사용합니다.

.ifeq \has_error_code
pushq $-1 /* ORIG_RAX: no syscall to restart */
.endif

언제 푸시 할 때 has_error_code=0.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top