728x90
14 ~ 15 강 소스코드입니다.
--------------------------------------------------------------------------------
자 저번 강의에 이어서 ScanCode를 아스키코드로 바꾸는 작업을 진행해봅시다.
interrupt.h에 다음과 같은 함수를 하나 선언해줍시다.
( ScanCode가 담긴 char 형을 받아 아스키값을 리턴해줄겁니다. )
( ScanCode가 담긴 char 형을 받아 아스키값을 리턴해줄겁니다. )
unsigned char transScan(unsigned char);
그리고 이 함수를 interrupt.c 에 다음과 같이 구현해봅시다.
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
|
unsigned char transScan(unsigned char target)
{
unsigned char result;
switch (target)
{
case 0x1E: result = 'a'; break;
case 0x30: result = 'b'; break;
case 0x2E: result = 'c'; break;
case 0x20: result = 'd'; break;
case 0x12: result = 'e'; break;
case 0x21: result = 'f'; break;
case 0x22: result = 'g'; break;
case 0x23: result = 'h'; break;
case 0x17: result = 'i'; break;
case 0x24: result = 'j'; break;
case 0x25: result = 'k'; break;
case 0x26: result = 'l'; break;
case 0x32: result = 'm'; break;
case 0x31: result = 'n'; break;
case 0x18: result = 'o'; break;
case 0x19: result = 'p'; break;
case 0x10: result = 'q'; break;
case 0x13: result = 'r'; break;
case 0x1F: result = 's'; break;
case 0x14: result = 't'; break;
case 0x16: result = 'u'; break;
case 0x2F: result = 'v'; break;
case 0x11: result = 'w'; break;
case 0x2D: result = 'x'; break;
case 0x15: result = 'y'; break;
case 0x2C: result = 'z'; break;
case 0x39: result = ' '; break; // 스페이스
case 0x0E: result = 0x08; break; // 백스페이스 아스키코드 = 8
default: result = 0xFF; break;
// 구현안된 것은 무시한다. 구분자는 0xFF
}
return result;
}
|
cs |
철저한 노가다(...)의 산물입니다만... 어찌되었던 이제 스캔코드가 아스키코드로 변환되어 나올 겁니다!
0x08은 아스키로 백스페이스에 해당됩니다. 그리고 나머지 스캔코드 값들 ( 때는 것까지 포함해서! )은 0xFF로 돌려줍시다. 그리고 0xFF로 리턴한 경우 가볍게 무시(...)하면 됩니다.
무슨 말인지 모르겠다구요? int_keyboard()에 구현된 것을 보면 바로 이해할 수 있을 겁니다. 그 전에 특정 라인에 써진 문자들을 모두 지워주는 kprintf_line_clear() 함수를 function.h와 function.h에 각각 추가합시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// function.h 에 추가
void kprintf_line_clear(int);
// function.c에 추가
void kprintf_line_clear(int line)
{
char *video = (char*)(0xB8000 + 160 * line);
for (int i = 0; i < 160 ; i++)
{
*video++ = 0;
*video++ = 0x03;
}
}
|
cs |
--------------------------------------------------------------------------------
좋습니다! 이제 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
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// interrupt.c 맨 상단에 추가
static unsigned char keyboard[160] = { 0, };
static unsigned short index = 0;
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) );
keybuf = transScan(keybuf);
if (keybuf == 0x08 && index != 0 ) // 백스페이스 입력
keyboard[--index] = 0;
else if (keybuf != 0xFF && keybuf != 0x08)
keyboard[index++] = keybuf;
kprintf_line_clear(8);
kprintf(keyboard,8,0);
__asm__ __volatile__
(
"mov al, 0x20;"
"out 0x20, al;"
);
__asm__ __volatile__
(
"popfd;"
"popad;"
"pop ds;"
"pop es;"
"pop fs;"
"pop gs;"
"leave;"
"nop;"
"iretd;"
);
}
|
cs |
keyboard 버퍼에 index 값을 적절히 조절하면서 하나씩 쌓아가는 모습입니다. 이 때 백스페이스를 입력했을 때에는 index 값을 빼고 0을 저장함으로서 버퍼 값을 하나 날리는 것을 확인할 수가 있습니다.
이렇게 만들어진 버퍼를 8줄에 출력합니다. ( 그 전에 clear 함수를 불러 해당 열에 있는 모든 잔상을 지워버립니다. )
자! 이제 키보드로부터 입력받을 모든 준비가 끝났습니다! 컴파일하고 실행해봅시다!
감격의 도가니탕이 아닐 수 없군요. DOS나 Linux shell 과 똑같이 영문 입력이 가능하고 또 자유롭게 지울 수도 있습니다!!
이렇게해서 키보드 디바이스 드라이버를 구현해봤습니다. 사실상 영문 소문자만 입력가능하고 대문자나 숫자, 느낌표나 따옴표 등등 입력이 안되는 허접한 드라이버입니다. 하지만 운영체제 자체를 만드는 데 의의를 두고 계속 진행해보도록 하겠습니다.
( 원리를 알았으니 좀 더 디테일하게 만드는 것은 시간문제겠죠? 스스로 수정해서 더 나은 드라이버를 만들어보세요 )
( 원리를 알았으니 좀 더 디테일하게 만드는 것은 시간문제겠죠? 스스로 수정해서 더 나은 드라이버를 만들어보세요 )
다음 강의에서는 HoGoS 만의 Shell을 만들어보도록 하겠습니다. 처음에는 허접한 명령어만 소화할 겁니다. 하지만 파일시스템, 프로세스, 메모리 등등을 구현하면서 점점 더 많은 명령어를 지원하게 될 겁니다.
감사합니다.
728x90
'소프트웨어 (과거) > C & 자료구조 & 커널 & DB' 카테고리의 다른 글
17. 하드디스크 드라이버 (0) | 2022.06.14 |
---|---|
16. 기초적인 쉘 (0) | 2022.06.14 |
14. 인터럽트 - 키보드 드라이버 1 (0) | 2022.06.14 |
13. 인터럽트 - ISR 구현 (0) | 2022.06.14 |
12. 인터럽트 IDT 구현 (0) | 2022.06.14 |