Welcome to My World (www.dgmayor.com)

소프트웨어/C & 자료구조 & 커널 & DB

14. 인터럽트 - 키보드 드라이버 1

dgmayor 2022. 6. 14. 11:22
728x90
 

14 ~ 15 강 소스코드입니다.
 

--------------------------------------------------------------------------------
 
자! 오늘은 키보드 드라이버를 구현해봅시다!
 
저번 강의를 통해 우리는 키보드 인터럽트를 받을 수 있게 되었습니다. 그렇다면 이제 어떤 키를 눌렀는지를 알아봐야겠죠?
 
interrupt.c 에 들어가서 버퍼용 전역변수를 하나 선언합시다. 여기에 어떤 문자를 입력했는지 저장할 겁니다.
 
 
 
unsigned char keybuf;
 
 

그리고, init_intdesc() 함수 끝에 다음과 같은 어셈블리 코드를 추가합시다. 이는 키보드 입력을 받겠다는 일종의 선언입니다.
 
 
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 = (unsigned short*)(0x0 + 8 * 0x21);
        *isr = inttable[2].offsetl;
        *(isr + 1= inttable[2].selector;
        *(isr + 2= inttable[2].type;
        *(isr + 3= inttable[2].offseth;
    
    }
 
    // 키보드 작동
    __asm__ __volatile__
    (
        "mov al, 0xAE;"
        "out 0x64, al;"
    );
    //  인터럽트 작동 시작
 
    __asm__ __volatile__("mov eax, %0"::"r"(&idtr));
    __asm__ __volatile__("lidt [eax]");
    __asm__ __volatile__("mov al,0xFC");
    __asm__ __volatile__("out 0x21,al");
    __asm__ __volatile__("sti");
 
    return;
cs
 
 

주의할 점은 " // 인터럽트 작동 시작 "전에 작성해야 한다는 점입니다. 키보드 입력 받는다고 선언도 안 했는데 인터럽트를 시작하면 안되겠죠? " // 키보드 작동 " 에 해당하는 2 줄을 적어주면 됩니다.
 
이제 셋팅이 끝났으니 본격적으로 idt_keyboard() 함수를 수정해서 키보드를 눌렀을 때 어떤 키를 눌렀는지 파악해보도록 하겠습니다.
 
 
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void idt_keyboard()
{
 
    __asm__ __volatile__
    (
        "push gs;"
        "push fs;"
        "push es;"
        "push ds;"
        "pushad;"
        "pushfd;"
        "xor al,al;"
        "in al, 0x60;"
    );
 
    __asm__ __volatile__("mov %0, al;" :"=r"(keybuf) );
    
    kprintf(&keybuf, 840);
 
    __asm__ __volatile__
    (
        "mov al, 0x20;"
        "out 0x20, al;"
    );
 
    __asm__ __volatile__
    (
        "popfd;"
        "popad;"
        "pop ds;"
        "pop es;"
        "pop fs;"
        "pop gs;"
        "leave;"
        "nop;"
        "iretd;"
    );
 
}
 
cs
 

복잡해보이지만 지난 강의때 작성한 코드와 별 차이가 없습니다.
 
__asm__ __volatile__("mov %0, al;" :"=r"(keybuf) ); 을 통해 실제로 어떤 값이 al에 저장되어있는지 keybuf로 옮기는 것 밖에 없습니다. 그리고 kprintf 로 어떤 값인지 확인하는 과정입니다.
 
좋습니다! 이제 다 끝났습니다. 어떤 값이 출력되는지 확인해볼까요? 컴파일 후 가상머신에 돌리고 abcd를 차례대로 입력해봅시다. 결과는?
 
 
 
 
 

뭔가... 출력이 되기는 하는데 우리가 예상했던 a,b,c,d 하고는 차원이 다르군요. 도대체 왜 그런거죠?
 
답은 Scan Code에 있습니다. 즉, a를 입력했을 때 키보드는 이를 ascii 형태로 CPU에 전달하지 않습니다. 대신 Scan code 형식으로 전달합니다.
 
 
 
 
 

보시다시피 a를 입력하게 되면 아스키 값인 0x61이 아닌 스캔코드 값인 0x1E를 받게 되는 겁니다. 그리고 골치 아픈 것은 키보드 인터럽트는 눌렀을 때도 발생하지만, 띨 때도 (!!!) 발생한다는 것입니다.
 
결국 요약하자면 키보드에 입력된 값을 알기 위해서는 스캔코드를 적절히 아스키코드로 번역하는 코드를 따로 만들어야 한다는 겁니다.
 
이는 다음 강의에서 본격적으로 구현해보겠습니다.
 
 
728x90

'소프트웨어 > C & 자료구조 & 커널 & DB' 카테고리의 다른 글

16. 기초적인 쉘  (0) 2022.06.14
15. 인터럽트 - 키보드 드라이버 2  (0) 2022.06.14
13. 인터럽트 - ISR 구현  (0) 2022.06.14
12. 인터럽트 IDT 구현  (0) 2022.06.14
11. 인터럽트 - IDT 선언  (0) 2022.06.14