5. 예외(Exception)

예외는 프로그램이 프로그램 혹은 시스템에 문제를 일으킬만한 명령을 실행시킬 , CPU 문제 해결을 하기 위해 인터럽트를 일으키는 것입니다.

Protected mode에서 예외는 하드웨어, 인터럽트, 소프트웨어 인터럽트와 같은 IDT 사용합니다.

전체 예외의 종류는 다음과 같습니다.

# Exception Exception handler Signal

0 Divide error divide_error( ) SIGFPE

1 Debug debug( ) SIGTRAP

2 NMI nmi( ) None

3 Breakpoint int3( ) SIGTRAP

4 Overflow overflow( ) SIGSEGV

5 Bounds check bounds( ) SIGSEGV

6 Invalid opcode invalid_op( ) SIGILL

7 Device not available device_not_available( ) None

8 Double fault doublefault_fn( ) None

9 Coprocessor segment overrun coprocessor_segment_overrun( ) SIGFPE

10 Invalid TSS invalid_TSS( ) SIGSEGV

11 Segment not present segment_not_present( ) SIGBUS

12 Stack segment fault stack_segment( ) SIGBUS

13 General protection general_protection( ) SIGSEGV

14 Page Fault page_fault( ) SIGSEGV

15 Intel-reserved None None

16 Floating-point error coprocessor_error( ) SIGFPE

17 Alignment check alignment_check( ) SIGBUS

18 Machine check machine_check( ) None

19 SIMD floating point simd_coprocessor_error( ) SIGFPE

 

다음 코드는 첫번째 인터럽트 디스크립터에 divide error 처리하는 인터럽트 루틴에 관련된 디스크립터를 등록하는 것입니다.

mov edi, 0

lea esi, [idt_zero_divide]

mov cx, 8

rep movsb

 

다음 코드는 인터럽트 디스크립터를 작성한 코드입니다. Isr_zero_divide 인터럽트 서비스 루틴으로 설정하였습니다.

Idt_zero_divide:

dw isr_zero_divide

dw 0x08

db 0

db 0x8E

dw 0x0001

 

isr_zero_divide:

push gs

push fs

push es

push ds

pusad

pushfd

 

mov al, 0x20

out 0x20, al

 

mov ax, VideoSelector

move s, ax

move di, (80*6*2)

lea esi, [msg_isr_zero+divide]

call printf

 

jmp $

 

popfd

popad

pop ds

pop es

pop fs

pop gs

 

3. 타이머 인터럽트 핸들러

타이머는 PIC의 IRQ 0번입니다. 그러나 PIC을 사용하기 위해서 그 전의 포스트에서 초기화 하는 과정에서 시작 번호를 0x20으로 주었으므로, 타이머 인터럽트가 발생하였을 경우 PIC은 CPU에게 0x20을 알릴 것입니다. 따라서 IRQ 0번에 연결된 타이머의 인터럽트를 처리하는 인터럽트 디스크립터는 0x20 번째 디스크립터에 기술 되어야 합니다.

Protected Mode로 넘어갈 때, 모든 인터럽트를 막는 것이 작업에 효율적이었습니다. 따라서 모든 인터럽트를 막았고, 타이머 인터럽트를 받아 들이기 위해서 0x20째 인터럽트를 다시 허용 해야 합니다.

 

lidt[idtr]

 

mov al, 0xFA

out 0x21, al

sti

jmp $

 

Idt를 등록한 뒤에, 타이머에 해당하는 IRQ 0번, 0번 비트를 0으로 클리어 한 뒤, 이것을 0x21 번 포트에 out 명령어로 내주면 해당 인터럽트가 유효하게 됩니다. 마스터 PIC의 데이터 부분의 주소인 0x21에 써줍니다.

7

6

5

4

3

2

1

0

1

리얼타임 클록

1

플로피디스크

컨트롤러

1

프린터

포트1

1

COM1

1

COM2

0

슬레이브

PC

1

키보드

0

타이머

 

Cpu가 PIC으로부터 인터럽트를 받아들이고 /INTA 신호를 돌려주기 위해 sti를 실행 시켜 줍니다.

 

idt_timer:

dw isr_32_timer ;

dw 0x08

db 0

db 0x8E

dw 0x0001

 

     

15

  

  

  

  

  

  

  

  

  

  

  

  

  

  

0

(1)핸들러의 오프셋 15 – 0 (isr_32_timer)

(2)핸들러의 코드 세그먼트 셀렉터 (0x08)

(3)P(1)

(4) DPL(00)

(5) 0

(6)D

(7)1

(8) 1

(9)0

사용안함 ( 0 )

(10) 핸들러의 오프셋 31 – 16(0x0001)

63

  

  

  

  

  

  

  

  

  

  

  

  

  

  

48

 

인터럽트 디스크립터를 보면 0x10000+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

 

핸들러로 들어오면 먼저 모든 레지스터와 EFLAGS를 스택에 저장해 놨다가, 인터럽트 루틴이 종료될 때, 다시 복귀시킵니다.

PIC을 리셋하고 iret 명령어를 실행시켜, 다시 인터럽트가 걸릴 수 있도록 합니다.

 

4. 키보드 인터럽트 핸들러

isr_33_keyboard:

pushad

push gs

push fs

push es

push ds

pushfd

 

in al, 0x60

 

mov al, 0x20

out 0x20, al

 

mov ax, videoSelector

mov es, ax

mov edi, (80*4*2)

lea esi, [msg_isr_33_keyboard]

call printf

inc byte [msg_isr_33_keyboard]

 

popfd

pop ds

pop es

pop fs

pop gs

popad

iret

 

키보드에서 어느 키가 눌렸는지 확인 하기 위해, in al, 0x60 명령어로, 키보드 버퍼에 있는 문자 스캔코드를 가져온 후, PIC을 리셋합니다.

 

'Operating Systems > OS 커널 제작' 카테고리의 다른 글

5. Task Switching (1) - TSS  (0) 2015.01.22
4. Interrupt 와 Exception (4) - 예외  (0) 2015.01.20
4. Interrupt 와 Exception (2) - PIC  (0) 2015.01.18
3. Protected Mode (3)  (0) 2015.01.17
3. Protected Mode (2)  (0) 2015.01.15

1. PIC ( Programmable Interrupt Controller )

PC의 모든 외부로부터의 하드웨어 인터럽트는 8259A라는 칩을 통해서 입력을 받습니다. PIC를 제어 하기 위해, OS에는 PIC을 초기화하고 연결, 인터럽트를 받아들이는 방법, 받아 들인 인터럽트를 CPU에 전달하는 방법이 정의되어 있어야 합니다.

 

   

PIC master –slave 구조로 구성되고, 마스터 PIC IRQ 8 (0 – 7) 슬래이브 PIC IRQ 8 (8 – 15) 핀에 연결된 하드 웨어 장치의 인터럽트를 받아, CPU에게 알리고, CPU 인터럽트의 정보를 PIC으로부터 받아 해당 인터럽트 루틴을 실행합니다.

 

마스터 PIC 동작은 다음과 같습니다.

연결된 장치 , 인터럽트가 발생하면,

(1) INT 핀에 신호를 실어 CPU INT 핀에 신호를

 - CPU Eflags IE 비트를 1 세트하고, 인터럽트를 받을수 있는 상황이면 /INTA 핀으로 신호를 보냄

(2) CPU로부터 /INTA핀으로 신호가 오면, 번째 IRQ 연결된 장치에서 인터럽트가 발생했는지 데이터 버스를 통에 CPU 전달

- CPU PIC 보내온 데이터를 참조하여, Protected Mode 실행 중이면 번호에 맞는 디스크립터를 찾아 인터럽트 핸들러를 실행

슬레이브 PIC 동작은 다음과 같습니다.

(1) 자신의 INT 핀에 신호를 실어 마스터 PIC IRQ 2 핀에 인터럽트 신호를 보냄

- 마스터 PIC 자신의 IRQ 핀에서 인터럽트가 발생하여, CPU에게 INT핀으로 신호 보냄

(2) CPU /INTA 신호를 주면 데이터버스에 숫자를 실어  번째 장치에서 인터럽트가 발생했는지 알려줌

 

마스터 PIC 슬레이브 PIC 사용하기 위해서는 초기화를 해주어야 하며, 동작 등을 프로그래밍 주어야 합니다.

 

PIC 제어 하기 위해 4개의 프로그램을 정의 하겠습니다.

ICW1, ICW2, ICW3, ICW4

 

PIC 사용하는 I/O port 다음과 같은 주소를 사용합니다.

 

Master PIC Command : 0x20

Master PIC Data : 0x21

Slave PIC Command : 0xA0

Slave PIC Data : 0xA1

 

PIC 초기화 – ICW1

7

6

5

4

3

2

1

0

0

0

0

1

L

T

I

M

0

S

N

G

L

I

C

4

 

LTIM – 엣지 트리거링(0), 레벨 트리거링(1)

SNGL – 마스터 슬레이브 구조(0), 마스터만 사용(1)

마스터 PIC 초기화 하기 위해서 다음과 같이 세트 줍니다.

7

6

5

4

3

2

1

0

0

0

0

1

0

0

0

1

16진수로 계산해 보면 0x11 입니다.

 

I/O 명령어인 out 이용하여, 마스터 PIC I/O 주소 0x20 프로그램 합니다.

 

mov al, 0x11

out 0x20, al

 

딜레이를 주기 위해 다음 명령어를 2  실행시킵니다.

jmp $+2

nop

nop

 

명령들은 헥사코드로 0x00eb입니다. 따라서 이렇게 표시합니다

 

dw 0x00eb, 0x00eb

 

슬레이어 PIC I/O주소 0xA0 마찬가지로 세트 하고, 마찬가지로 딜레이를 줍니다.

7

6

5

4

3

2

1

0

0

0

0

1

0

0

0

1

 

 

out 0xA0, al

dw 0x00eb 0x00eb

 

PIC IQR 시작점 설정(IRQ 리맵핑): ICW2                       

7

6

5

4

3

2

1

0

Off7

off6

Off5

Off4

Off3

0

0

0

 

PIC 인터럽트를 받았을 IRQ 번호에 얼마를 해서 CPU 알려줄지 정합니다. 0 – 2 비트가 0 것은 숫자를 8 단위로 기재해야 된다는 뜻입니다.

마스터 PIC 다음과 같이 세트합니다.

7

6

5

4

3

2

1

0

0

0

1

0

0

0

0

0

 

mov al, 0x20

out 0x21, al

dw 0x00eb, 0x00eb

 

슬레이브 PIC 다음과 같이 세트합니다. IRQ 8 부터 시작 함으로, 앞서 마스터 PIC 지정한 것에서 8 더해서 슬레이브 PIC 0x28 세트 합니다.

7

6

5

4

3

2

1

0

0

0

1

0

1

0

0

0

 

mov al, 0x28

out 0xA1, al

dw 0x00eb, 0x00eb

 

만약 IRQ0 연결된 하드웨어에서 인터럽트가 발생한다면, ICW2 명령어에서 0x20 설정했기 때문에 IRQ 번호는 0x20 됩니다.

슬레이브 PIC IRQ0 (전체적으로 보면 IRQ8) 연결된 하드웨어 에서 인터럽트가 발생한다면,  0x28 됩니다.

 

마스터 PIC 슬레이브 PIC 구분 – ICW3

IRQ2 번에 슬레이브 PIC 연결되어 있다는 것을 마스터 PIC에게 알려줍니다.

7

6

5

4

3

2

1

0

S7

S6

S5

S4

S3

S2

S2

S0

 

S0 – S7 IRQ 선에 해당됩니다. 0 들어가면, 하드웨어 장치에 연결이 되어 있다는 것을 나타내고, 1 연결하면 슬레이브 PIC 연결되어 있음을 의미합니다.

7

6

5

4

3

2

1

0

0

0

0

0

0

ID2

ID2

ID0

 

번째 IRQ 핀에 연결되어 있는지 마스터 PIC 해당 비트를 1

3~7비트는 0으로 하여, ID0 – ID2 3비트를 사용하여 슬레이브 PIC 마스터 PIC IRQ 핀에 연결되어 있는지 세트합니다.

 

마스터 PIC IRQ 2번에 슬레이브 PIC 연결합니다.

마스터 PIC 이렇게 세트 합니다.

7

6

5

4

3

2

1

0

0

0

0

0

0

1

0

0

 

슬레이브 PIC 다음과 같이 세트 합니다.

7

6

5

4

3

2

1

0

 

 

 

 

 

 

1

0

 

mov al, 0x04

out 0x21, al

dw 0x00eb, 0x00eb

mov al, 0x02

out 0xA1, al

dw 0x00eb, 0x00eb

 

추가 명령어 : ICW4

7

6

5

4

3

2

1

0

0

0

0

S

F

N

M

B

U

F

M

/

S

A

E

O

I

U

P

M

 

SFNM BUF, M/S 기능은 우리가 사용하는 PC에서 구현되어 있지 않기 때문에 항상 0으로 설정합니다.

AEOI – PIC Reset 자동으로 할지, 수동으로 할지 나타냄

리셋을 자동으로 수행하도록 한다면 CPU IRQ 번호를 알린 바로 리셋 하며, 수동으로 수행하도록 한다면 CPU에서 IRQ 번호를 받아들이고, 인터럽트 루틴을 처리 다음, PIC 명령을 주어 리셋해야 합니다.

uPM - MCS-80/85 모드(0) , 8086(1)

 

IRQ 자동으로 리셋하고, 8086 모드로 실행되게 합니다.

다음과 같이 마스터 PIC 설정합니다.

7

6

5

4

3

2

1

0

0

0

0

0

0

0

0

1

 

다음과 같이 슬레이브 PIC 설정합니다.

7

6

5

4

3

2

1

0

0

0

0

0

0

0

0

1

 

mov al, 0x01

out 0x21, al

dw 0x00eb, 0x00eb

out 0xA1, al

dw 0x00eb, 0x00eb

 

인터럽트 막기

 

Protected Mode 넘어가면서 IDT 설정, 하드웨어 인터럽트 작업을 하는 동안 모든 인터럽트를 불가능으로 전환합니다.

 

마스터 PIC IRQ핀에서 슬레이브 PIC 연결된 IRQ2 핀을 제외하고 인터럽트를 막고, 슬레이브 PIC 모든 인터럽트를 막습니다.

 

슬레이브 PIC 다음과 같이 설정합니다.

7

6

5

4

3

2

1

0

1

 

1

1

1

1

1

1

1

 

마스터 PIC 다음과 같이 설정합니다.

7

6

5

4

3

2

1

0

1

1

1

1

1

0

1

1

 

mov al, 0xFF

out 0xA1, al

dw 0x00eb, 0x00eb

mov al, 0xFB

out 0x21, al

 

 

'Operating Systems > OS 커널 제작' 카테고리의 다른 글

4. Interrupt 와 Exception (4) - 예외  (0) 2015.01.20
4. Interrupt 와 Exception (3) – 인터럽트 핸들러  (0) 2015.01.19
3. Protected Mode (3)  (0) 2015.01.17
3. Protected Mode (2)  (0) 2015.01.15
3. Protected Mode (1)  (0) 2015.01.14

+ Recent posts