Music for reading(spotify)

DNS over HTTPS logo

OS개발을 시작하게 된 계기

대학 3학년에 컴퓨터 구조 수업과 OS수업을 들었더니, 실제로 OS를 만들어 보고 싶다는 생각이 들었다. 수업 때 얻은 지식으로 충분히 만들 수 있을 것이라 보았고, 무턱대고 부딛혀서 만들기를 시도해 보았으나 많이 어려웠다. 그래서 책을 하나 구했고, 이 책을 기반으로 초반 길을 닦으면 내 이론을 실제로 써먹을 수 있지 않을까 싶어 도전하기로 했다.

이 시리즈는

이걸 기록으로 남기는 이유는, 몇 가지 이유가 있다.

  1. 삽질한 걸 까먹을까봐
  2. 기록으로 남기면 나중에 뿌듯하니까
  3. 뿌듯하면 계속 지속할 원동력이 되니까

다음과 같은 이유로 시리즈로 기록을 해보고자 한다.

시작하기

이 글은 IT EXPERT 64비트 멀티코어 OS 원리와 구조, 한승훈 저1를 기반으로 작성되었다. 글쓴이에게 무한한 감사를 드리며 이 글을 시작하겠다.

본 시리즈는 다음과 같은 환경에서 작업했다.

AMD Ryzen 1700
Manjaro Linux 18.0 
Linux Kernel 4.19.23-1

사용 툴은 다음과 같다.

neovim
visual studio code

앞서 설치하기

base-devel, NASM 그리고 QEMU가 필요하다.

sudo pacman -Syyu
sudo pacman -S base-devel binutils nasm qemu

설치가 완료되었으면 binutils(GNU binary utilities)의 링커와 gcc가 제대로 설치되어있는지 확인하자. 크로스-컴파일도 지원하는지 꼭 확인해야 한다.

ld --help | grep "supported"

다음과 같이 출력이 되어야 한다.

ld: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little
elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex
ld: supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu elf_l1om elf_k1om i386pep i386pe

x86-64i386 등이 존재하는지를 잘 봐야 한다. 32비트와 64비트 크로스 컴파일링이 가능해야 하기 때문이다.

gcc도 크로스 컴파일링이 가능한지 확인하자

gcc -dumpspecs | grep -A1 multilib_options

다음과 같이 출력이 되어야 한다.

*multilib_options:
m64/m32

다음과 같이 되어있으면 당신의 머신은 크로스 컴파일링에 대해 준비가 된 것! 윈도우에 대해서는 WSL을 사용하면 될 것이라고 생각한다.

운영 모드

우리가 주변에서 흔히 사용하는 CPU는 대체로 64비트 호환 프로세서 이며, x86-64 프로세서, x64 프로세서, 또는 AMD64 프로세서라고 불리운다. 엄밀히 따지면 이는 CPU 명령어 셋 아키텍처들을 구분할 때 사용하는 말이며, 공정 등과는 관련이 없음을 일러둔다. 이 프로세서들은 여러 운영 모드를 가지고 있는데, 운영 모드들은 다음과 같다.

구분 운영 모드 설명
레거시 모드 리얼 모드 - 프로세서의 초기 상태, 16비트 모드로 동작하며 8086 프로세서와 호환됨.
- 최대 1MB(2^20)의 주소공간을 지원함.
  보호 모드 - 32비트 모드로 동작하며, 세그먼트, 페이징, 보호, 멀티태스킹 등의 기능 제공.
- 4GB(2^32)의 주소공간을 지원함.
  가상 8086 모드 - 보호 모드 내부에서 가상의 환경을 설정하여 리얼 모드처럼 동작하는 모드.
롱 모드 64비트 모드 - 64비트 단독 모드로써, 기본 주소 크기가 64비트이다.
- 32비트로 작성된 응용 프로그램을 작동시키기 위해서는 리빌딩이 필요하다.
  호환 모드 - 32-64비트 모드 전부를 지원하는 모드로써, 기본 주소 크기가 32비트이다.
- 32비트로 컴파일된 응용 프로그램은 리빌드 없이 구동 가능하다.

Operating Modes of the AMD64 Architecture 2

이 여러 운영 모드 중, 64비트 OS는 리얼 모드, 보호 모드, 그리고 롱 모드 세 가지를 반드시 지원하여야 한다. 롱 모드는 하위 모드인 호환 모드64비트 모드 두 가지를 전부 지원해야 한다.

각각의 모드를 자세히 알아보기 전에 간단하게 정리하고 들어가도록 하자.

리얼 모드

프로세서가 어떤 상태나 모드에 있던, 전원이 켜지거나 리셋이 되면 프로세서는 리얼 모드로 진입한다. 리얼 모드는 기본적으로 16비트 프로세서와 동일하게 동작하며, BIOS의 기능들을 사용 가능하다. 리얼 모드에서는 디바이스 드라이버를 BIOS가 지원하므로 따로 제작하지 않아도 된다는 장점이 있다. 리얼 모드에서는 제작한 OS 이미지를 디스크로부터 메모리로 복사하여 보호 모드로 전환하는 작업을 한다.

보호 모드

리얼 모드로부터 롱 모드로 전환하기 위해서는 보호 모드를 거쳐야 한다. 보호 모드는 기본적으로 32비트 OS들이 동작하는 모드이다. 최대 4GB의 주소 공간을 제공하고, OS의 필수 기능인 보호, 멀티태스킹, 세그먼테이션, 페이징 등의 기능을 하드웨어 단위에서 제공한다. 그만큼 더 복잡하고, 레지스터와 자료구조가 다양하다는 특징을 가지고 있다. 여기서 사용하는 레지스터는 대부분 롱 모드에서도 같이 사용할 수 있으므로 이 부분을 잘 알아두는 것이 중요하다.

롱 모드

롱 모드는 AMD64 / x86-64 아키텍처에서의 프로세서 모드로써, AMD에서 만든 32비트-64비트 호환 아키텍처이다. 이를 인텔에서 크로스-라이선싱으로 만든 것이 IA-32e아키텍처이며. 따라서 두 아키텍처 모두 롱 모드 라는 모드가 존재한다. 이 모드는 최대 16E(2^64)의 주소 공간을 제공하며, 레지스터 수도 보호 모드보다 많으나, 기본적으로 AMD64는 32비트를 확장한 아키텍처이므로 보호 모드와 비슷하거나 크게 다르지 않다. 롱 모드에는 64비트 모드호환 모드 두 가지가 존재하는데, 호환 모드는 롱 모드에서 동작하나 마치 보호 모드에서 동작하는 것처럼 코드를 실행할 수 있다는 장점이 있다. 이는 서브 모드만 전환하는 것으로 보호 모드의 32비트 코드를 실행할 수 있다는 뜻이며, 이를 이용하여 별다른 처리 없이 64비트 OS에서 32비트 보호 모드 프로그램을 실행시킬 수 있다.

마치며

오늘은 64비트 운영체제를 만들기 위한 기본 지식에 대해 일부 알아보았다. 다음은 x86-64 프로세서 아키텍처의 레지스터와 메모리 모델에 대해 알아 볼 예정이다.