mov edi, 8*0x20
lea esi, [idt_timer]
mov cx, 8
rep movsb
- 타이머는 IRQ 0번입니다. 그러나 부트스트랩 프로그램에서 PIC를 리매핑했기 때문에 타이머 인터럽트가 발생했을 때 PIC는 CPU에게 0x20번의 인터럽트가 발생했다고 알려줄 것입니다. 그래서 IDT에 있는 디스크립터 중 0x20번째에 만들어 놓은 디스크립터를 복사해서 설정해 놓습니다.
- idt_timer 디스크립터
lidt[idtr]
mov al, 0xFE ; 막아두었던 인터럽트 중
out 0x21,al ; 타이머만 다시 유효하게 합니다.
sti
jmp $
- sti 명령어를 꼭 해줘야, CPU가 PIC로부터 인터럽트를 받아들이고, /INTA 신호를 되돌려줄 수 있습니다. cli 명령으로 인터럽트 플래그가 0으로 세팅되어 있으면 CPU 측에서 /INTA 신호를 되돌려 주지 않습니다.
- 이후로는 타이머 인터럽트 핸들러가 계속 호출되어 문장이 나오게 됩니다.
idt_timer:
dw isr_32_timer
dw 0x08
db 0
db 0x8E
dw 0x0001
- 핸들러의 물리주소로서 0x010000 + isr_32_timer를 지정하고 있습니다.
- 인터럽트 핸들러인 isr_32_timer 루틴입니다.
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 명령어를 통해 중단되었던 루틴으로 돌아가더라도 인터럽트가 다시 걸릴 수 있도록 합니다.