본문 바로가기
IT 공부/운영체제

[2024.11.21] - IRETQ 명령어 새롭게 알게 된 내용 정리

by exdus3156 2024. 11. 21.

IRTG 명령어는 인터럽트 수행이 끝난 후에 핸들러 함수의 끝부분의 마지막 명령어다. 이것은 IST 스택에 프로세서가 직접 쌓아준 여러 레지스터 데이터들(Flags, CS, SS, RIP, RSP)를 한 꺼번에 복구시키는 명령어다. 

IDT 인터럽트 게이트 디스크립터 테이블에 우리는 인터럽트 핸들러 함수의 포인터를 저장하고, CS(코드 세그먼트 설렉터)와 IST, DPL, 타입을 저장한다. 이때 타입에는 인터럽트/트랩 두 종류 중 하나를 선택할 수 있는데, 보통 인터럽트를 선택한다. 트랩은 인터럽트 핸들러 수행 도중에 다른 인터럽트를 또 받을 수 있게 설정하는 것이다. 인터럽트는 핸들러 수행 도중에 다른 인터럽트 신호 발생 시 무시하는 역할을 수행한다. 

인터럽트 타입은 해당 인터럽트 신호가 발생하면 프로세서가 자동으로 RFLAGS 레지스터의 인터럽트 관련 레지스터(IF)를 비활성화해준다. 즉, 인터럽트 게이트 디스크립터의 타입이 인터럽트이면 그 인터럽트를 프로세서가 수행해줌과 동시에 IF를 비활성화해서 다른 인터럽트를 막아버리는 것이다.

그러면 이걸 개발자가 일일이 풀어줘야 할까? 그렇지 않다. 왜냐하면 IRETQ 명령어는 암묵적으로 비활성화된 인터럽트를 다시 활성화시켜주기 때문이다.

이게 참 중요한데, 보통 인터럽트 핸들러 함수의 내부에는 끝부분에 EOI(End Of Interrupt)를 APIC 혹은 PIC 컨트롤러에 전달하기 때문이다. 이걸 컨트롤러에 전달하면 컨트롤러는 자기 내부의 InService 레지스터에서 해당 인터럽트 항목의 비트를 비활성화해서 핸들러가 다 완료되었다고 가정한다. 그러면 나머지 인터럽트 신호가 있는 경우 그것을 다시 프로세서에게 INT 하는데, 프로세서는 IRETQ가 수행되기 전까지는 인터럽트를 비활성화했으므로 그것을 무시한다.

이렇게 무시해야한다. 왜냐하면 IRETQ 명령어 수행 전에도 나름 중요한 명령어들을 수행하고 있기 때문에 여전히 완전히 완료된 것은 아니기 때문이다.