Skip to content

day 10: PIC - 타이머 인터럽트 핸들러

  • kernel.asm
1
2
3
4
mov edi, 8*0x20
lea esi, [idt_timer]
mov cx, 8
rep movsb
  • 타이머는 IRQ 0번입니다. 그러나 부트스트랩 프로그램에서 PIC를 리매핑했기 때문에 타이머 인터럽트가 발생했을 때 PIC는 CPU에게 0x20번의 인터럽트가 발생했다고 알려줄 것입니다. 그래서 IDT에 있는 디스크립터 중 0x20번째에 만들어 놓은 디스크립터를 복사해서 설정해 놓습니다.

  • idt_timer 디스크립터

1
2
3
4
5
6
lidt[idtr]

mov al, 0xFE      ; 막아두었던 인터럽트 중
out 0x21,al           ; 타이머만 다시 유효하게 합니다.
sti
jmp $
  • sti 명령어를 꼭 해줘야, CPU가 PIC로부터 인터럽트를 받아들이고, /INTA 신호를 되돌려줄 수 있습니다. cli 명령으로 인터럽트 플래그가 0으로 세팅되어 있으면 CPU 측에서 /INTA 신호를 되돌려 주지 않습니다.

  • 이후로는 타이머 인터럽트 핸들러가 계속 호출되어 문장이 나오게 됩니다.

1
2
3
4
5
6
idt_timer:
  dw isr_32_timer
  dw 0x08
  db 0
  db 0x8E
  dw 0x0001
  • 핸들러의 물리주소로서 0x010000 + isr_32_timer를 지정하고 있습니다.

  • 인터럽트 핸들러인 isr_32_timer 루틴입니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
isr_32_timer:
  push gs
  push fs
  push es
  push ds
  pushad
  pushfd

  mov al, 0x20
  out 0x20, al

  mov ax, VideoSelector
  mov es, ax
  mov edi, (80*2*2)
  lea esi, [msg_isr_32_timer]
  call printf
  inc byte [msg_isr_32_timer]

  popfd
  popad
  pop ds
  pop es
  pop fs
  pop gs

  iret
  • 위의 코드에서 0x20(master PIC - 커맨드 버스) 주소로 0x20을 보내는 것의 의미는 EOI(End-Of-Interrupt command code)라고 합니다.

  • 이 명령어는 인터럽트의 끝을 알립니다. 이 커맨드는 IRQ기반 인터럽트 루틴이 끝났을 때 PIC칩에 발급됩니다. 마스터 PIC만 있으면, 이 커맨드가 필요 없지만, IRQ가 슬레이브 PIC로 간다면, 이 커맨드를 마스터 PIC와 슬레이브 PIC 각각에 발행해야 합니다.

  • 즉, EOI 명령어 out 0x20(master PIC), 0x20(EOI)은 PIC를 리셋하여 IRET 명령어를 통해 중단되었던 루틴으로 돌아가더라도 인터럽트가 다시 걸릴 수 있도록 합니다.