반응형

→ 디스크립터 파일 추가

 

디스크립터 파일현재 가장 핵심적인 역할을 하는 파일로, GDT와 IDT에 관련된 모든 함수와 매크로가 정의되어 있습니다.

 

디스크립터 파일02.Kernel64/Source 디렉터리에 있으며 파일 내용은 아래와 같습니다.

 

GDT의 시작 주소 같이 상수로 사용된 부분은 유지보수를 위해 매크로로 치환했습니다.

 

 

디스크립터 소스 파일(02.Kernel64/Source/Descriptor.c) 1

 

디스크립터 소스 파일(02.Kernel64/Source/Descriptor.c) 2

 

디스크립터 소스 파일(02.Kernel64/Source/Descriptor.c) 3

 

디스크립터 소스 파일(02.Kernel64/Source/Descriptor.c) 4

 


 

디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 1

 

디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 2

 

디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 3

 

디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 4
디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 5

 

디스크립터 헤더 파일(02.Kernel64/Source/Descriptor.h) 6

 


 

→ 어셈블리어 유틸리티 파일 수정

 

어셈블리어 함수 kLoadGDTR(), kLoadTR(), kLoadIDTR()를 추가했으므로 이를 어셈블리어 유틸리티 파일에 반영합니다.

 

아래의 코드는 어셈블리어 유틸리티 파일의 내용 중에서 수전된 부분을 위주로 나타낸 것입니다.

 

어셈블리어 유틸리티 소스 파일(02.Kernel64/Source/AssemblyUtility.asm) 1

 

어셈블리어 유틸리티 소스 파일(02.Kernel64/Source/AssemblyUtility.asm) 2

 

 

어셈블리어 유틸리티 헤더 파일(02.Kernel64/Source/AssemblyUtility.h)

 


 

→ 유틸리티 파일 추가

 

유틸리티 파일앞으로 커널에서 사용할 유틸리티 함수를 정의한 파일kMemSet() 함수가 여기에 속합니다.

 

아래의 코드는 유틸리티 파일의 내용이고, kMemSet(), kMemCpy(), kMemCmp() 함수가 포함되어 있습니다.

 

 

유틸리티 소스 파일(02.Kernel64/Source/Utility.c) 1

 

유틸리티 소스 파일(02.Kernel64/Source/Utility.c) 2

 

유틸리티 헤더 파일(02.Kernel64/Source/Utility.h)


 

→ C언어 커널 엔트리 포인트 파일 수정

 

마지막으로 C언어 엔트리 포인트를 수정하여 이번 장에서 작성한 함수들을 호출합니다.

 

엔트리 포인트의 뒷부분에 GDT, IDT, TSS와 관련된 함수를 호출하는 코드를 추가하면 됩니다.

 

아래는 수정된 엔트리 포인트 코드를 나타낸 것으로 작성한 함수를 호출하는 것 외에 또 다른 기능이 추가되어 있는데, 바로 예외를 발생시켜 핸들러가 정상적으로 동작하는지 확인하는 기능입니다.

 

 

x86 프로세서에서 예외를 발생시키는 가장 편리한 방법은 정수를 0으로 나누는 것입니다.

 

정수를 0으로 나누면 Divide Error 예외(벡터 0번)가 발생하고, 바로 벡터 0번 핸들러가 호출됩니다.

 

이러한 특징을 이용하여 키를 입력받는 while() 루프 안에 숫자 0 키가 입력되면 임시 변수를 0으로 나누어 예외가 발생하도록 하였으며, 만약 IDT 테이블이 정상적으로 생성되고 프로세서에 로드 되었다면, 임시 핸들러(kDummyHandler() 함수)가 호출되고 커널이 정지할 것입니다.

 

C 언어 커널 엔트리 포인트는 이전의 코드와 대부분이 같으므로 수정된 부분 위주로 나타냈습니다.

 

IA-32e 모드 커널의 C언어 엔트리 포인트 소스 코드(02.Kernel64/Source/Main.c) 1

 

IA-32e 모드 커널의 C언어 엔트리 포인트 소스 코드(02.Kernel64/Source/Main.c) 2

 

IA-32e 모드 커널의 C언어 엔트리 포인트 소스 코드(02.Kernel64/Source/Main.c) 3

 


 

→ 빌드와 실행

 

이제 FS64 OSGDT, IDT, TSS에 대한 모든 내용이 적용되었으므로 빌드한 후 실행합니다.

 

FS64 OS의 루트 디렉터리에서 make를 입력하면 대부분 별다른 오류 없이 빌드되어 Disk.img 파일이 생성되고, 이 Disk.img 이미지 파일을 가상머신(QEMU)로 실행하면 아래와 같이 화면이 표시될 것입니다.

 

이제 키보드 입력 테스트를 수행하고 숫자 0번 키를 눌러봅니다.

 

모든 과정이 정상적으로 처리되었다면 Divide Error 예외가 발생하고 임시 핸들러가 수행되어 아래의 두 번째 사진과 같이 표시됩니다.

 

정상적으로 부팅된 화면

 

정상적으로 부팅된 화면

 

이렇게 인터럽트와 예외를 처리하기 위한 첫 번째 단계가 끝났습니다.

 

예외와 인터럽트 처리에 관련된 레지스터 및 자료구조와 프로세서가 중심이 되는 예외처리를 위주로 살펴봤으니, 이후에는 인터럽트를 위주로 살펴보고 키보드 인터럽트를 이용하여 키보드 디바이스 드라이버를 업그레이드하는 방법에 대해 알아봅니다.

 

이번에 작성한 핸들러 함수가 무한 루프인 이유는 디버깅을 위한 것도 있지만, 사실은 임시 핸들러 함수는 이전 코드로 복귀할 능력이 없기 때문입니다.

 

프로세서는 인터럽트나 예외가 발생했을 경우, 자신의 상태 중 일부만 스택에 저장하기 때문에 프로세서가 저장하지 않는 나머지 레지스터들은 OS가 처리해야 하는데 임시 핸들러는 그러한 코드가 없기 때문에 복귀할 수 없는 것입니다.

 

프로세서의 전체 상태를 저장하는 것은 원리만 알면 스택을 사용해서 쉽게 처리할 수 있습니다.

반응형

+ Recent posts