os framework 1 1 free

27
Version 1.0 1/27

Upload: dongsoo-choi

Post on 02-Oct-2014

31 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Os Framework 1 1 Free

Version 1.0 1/27

Page 2: Os Framework 1 1 Free

kkamagui 의 기부 북 시리즈란 ?

kkamagui의 기부 북(Donation Book) 시리즈는 여러분의 기부로 출간되는 핸드북 형태의 전자책

(e-book) 입니다. 한 권의 책으로 내기에는 양이 부족한 프로그래밍 팁이나 강좌를 묶어서 출간한

것으로, 제가 그동안 진행해왔던 프로젝트에 대한 내용들이 담겨있습니다.

만일 kkamagui의 기부 북 시리즈가 여러분에게 도움이 되었으며, 다음 기부 북 시리즈가 나오기를

바라신다면 작은 기부를 부탁 드립니다. 여러분이 모아주신 기부는 운영하는 사이트를 유지하고

기부 북 시리즈를 출간 하는데 많은 도움이 됩니다.

기부는 아래의 방법으로 가능합니다.

• 기부 북 안드로이드 어플을 구매하는 방법

◦ market://details?id=jscompany.book.osframework1 (마켓에서 직접 구매)

◦ https://market.android.com/details?id=jscompany.book.osframework1 (웹을 통해서 구

매)

• 은행 송금을 이용하는 방법

◦ 국민은행 399102-04-064166 김준영

• 기타 다른 기부 방법

◦ 아래 주소로 이동하시면 더 많은 기부 방법을 보실 수 있습니다.▪ http://kkamagui.tistory.com/783

무료로 배포되는 기부 북 시리즈는 원활한 기부를 위해 본문에 간헐적으로 기부 방법을 알리는 배

너가 들어있습니다. 위의 방법으로 기부를 하시고 저에게 메일(kkamagui at gmail.com)로 알려주

시면, 편하게 보실 수 있도록 기부 배너가 제외된 문서를 보내드리겠습니다.

기부 북이 여러분에게 많은 도움이 되길 기대하면서...

2011년 겨울 어느 추운 겨울 밤...

kkamagui 드림

Version 1.0 2/27

Page 3: Os Framework 1 1 Free

질문이나 피드백 방법

책 내용에 대한 궁금증이나 부족한 부분에 관한 피드백은 아래의 이메일이나 블로그로 연락 주시

기 바랍니다.

• 이메일 주소

◦ kkamagui at gmail.com

• 사이트와 블로그 주소

◦ http://www.mint64os.pe.kr

◦ http://kkamagui.tistory.com

기부 북의 저작권

기부 북의 저작권(copyright)은 kkamagui에게 있으며, 상업적으로 활용하는 것을 금합니다. 만일,

내용의 일부 또는 전체를 상업적으로 이용할 경우, 먼저 저자(kkamagui at gmail.com)에게 연락하

셔야 하며 무단으로 사용하시는 경우 법적 제재가 가해질 수 있습니다.

Version 1.0 3/27

Page 4: Os Framework 1 1 Free

기부 북 1 권 : OS Framework 에 대하여 ...

OS 프레임워크(Framework)는 필자가 2002년부터 2007년까지 여러 플랫폼에서 OS를 만들면 생

각해왔던 것을 틈틈이 정리한 것입니다. 매번 다른 플랫폼에서 OS를 만드는 동안 간단한 커널을

동작시킬 때까지 드는 시간이 너무 길다고 판단하여 이를 획기적으로 줄일 수 있는 방법을 고민했

는데, 이때 떠오른 것이 바로 프레임워크였습니다.

이 자료는 2008년에 처음 작성되었기 때문에 OS 프레임워크는 32비트 OS에 초점을 맞추어 구현

되었습니다. 비록 OS 프레임워크가 64비트까지 다루고 있지는 못하지만, 프레임워크를 사용해서

OS를 만드는 관점에서 보면 32비트와 64비트의 차이가 거의 없습니다. 따라서 현재 OS 프레임워

크로도 OS를 배우는데 부족함이 없을 거라 생각합니다.

32비트와 64비트의 차이가 궁금하다면 아래 두 책을 통해 자세한 정보를 얻을 수 있습니다.

• INTEL Architecture Manual, Volume 3

• 64 비트 멀티코어 OS 원리와 구조 (한빛 미디어)

기부 북 1권(OS Framework)은 여러 부로 나누어져 있으며, 최소 4부 이상으로 구성할 계획입니

다. 앞으로 많은 관심과 기대를 부탁 드립니다.

Version 1.0 4/27

Page 5: Os Framework 1 1 Free

목차

kkamagui의 기부 북 시리즈란?.....................................................................................................2

질문이나 피드백 방법...................................................................................................................3

기부 북의 저작권...........................................................................................................................3

기부 북 1권: OS Framework에 대하여..........................................................................................4

1.OS개발과 프레임워크의 만남....................................................................................................6

2.프레임워크와 OS 개발................................................................................................................93.Bottom-up vs Top-down...............................................................................................................10

4.OS 프레임워크...........................................................................................................................12

5.알아두면 도움이 되는 OS 개발 정보들..................................................................................145-1.BIOS(Basic Input Output System).......................................................................................15

5-2.IA-32(INTEL 32bit Architecture) CPU 아키텍처..................................................................15

5-3.어셈블리어.........................................................................................................................19

5-4.호출 규약(Calling Convention)...........................................................................................22

6.참고 자료...................................................................................................................................26

Version 1.0 5/27

Page 6: Os Framework 1 1 Free

1.OS 개발과 프레임워크의 만남

프로그래머라면 누구나 한 번쯤은 자신이 개발한 OS에서 직접 제작한 프로그램을 실행하고 싶다

는 생각을 했을 겁니다. 필자도 이런 꿈을 가진 한 사람으로서 자신만의 OS를 만들고 싶다는 욕망

은 프로그래머라면 당연한 것이라 생각합니다.

그럼, OS를 개발하려면 어떤 것이 필요할까요? OS에 관한 이론은 물론이고 CPU의 동작 원리, 어

셈블리어 및 하드웨어에 관련된 지식, 일정 수준 이상의 C 언어 레벨 등등 필요한 것은 셀 수 없이

많습니다. 특히 CPU와 어셈블리어에 대한 지식은 필수이므로 CPU 아키텍처 매뉴얼을 끌어 안고

살아야 합니다. 사실, 초급 프로그래머에게 이러한 지식을 요구하는 것 자체가 무리이기 때문에,

초급 프로그래머에게 OS 개발은 난공불락의 요새와 같습니다. 그리고 중급 이상의 프로그래머라

하더라도 OS란 벽이 그리 낮지는 않을 것입니다.

그래서 필자는 한 때 OS개발이 시스템 프로그래밍의 마지막 단계이며, 프로그래밍을 시작하는 입

장에서는 꿈에서나 가능한 경지라고 생각했습니다. 그런데 지금은 생각이 좀 바뀌었습니다. 이러

한 과정을 모두 거쳐간 선배님들이 후배들을 위해 자신만의 노하우를 웹사이트나 책으로 정리했

기 때문입니다. 웹에서 OS개발 관련 사이트를 쉽게 찾아볼 수 있고, 서점에서도 OS개발 관련 서

적을 심심치 않게 볼 수 있습니다. 물론 여기에는 필자의 책, “64 비트 멀티코어 OS 원리와 구조

”(한빛 미디어)도 포함됩니다. 지금 여러분들이 보고 있는 기부 북 1권과 함께 보면 도움이 되는 사

이트와 책을 소개할테니 여유가 되면 같이 참고하기 바랍니다.

▶OS를 만드는데 도움이 되는 책과 사이트◄

책 목록

• 64 비트 멀티코어 OS 원리와 구조 : 64비트 멀티코어 프로세서를 지원하는 OS를 만드는 책,

Step by Step 방식으로 진행하여 마지막 장에 이르면 완성된 OS가 나오는 방식

• Operating System Concepts : OS 이론에 관한 최고의 책

• Understanding the Linux Kernel : Linux Kernel에 대해 자세한 설명이 포함된 책

• The Design of the UNIX Operating System : Unix 시스템 전반에 대한 설명이 포함된 책

• MMURTL V1.0 : 32비트 멀티 태스킹 OS를 만드는 코드 위주의 책

• The Indispensable PC Hardware Book : PC Hardware의 모든 정보를 망라한 책

• The Undocumented PC : 위 책과 같이 PC의 모든 정보를 망라한 책

사이트 목록

• OS Dev 사이트(http://wiki.osdev.org/) : OS 개발에 대한 많은 내용을 담고 있는 사이트

Version 1.0 6/27

Page 7: Os Framework 1 1 Free

• Bona Fide OS Developer 사이트(http://www.osdever.net/) : OS 개발에 관련된 많은 자료와

예제 코드를 담고 있는 사이트

• The Operating System Resource Center(http://nondot.org/sabre/os/articles) : OS 개발에

관련된 각종 하드웨어나 소프트웨어 정보를 얻을 수 있는 사이트

• MINT64 OS 사이트(http://www.mint64os.pe.kr) : “64비트 멀티코어 OS 원리와 구조” 책의

Q&A와 OS 개발에 관한 정보를 공유하는 사이트

그럼 OS 프레임워크를 소개하기 앞서, OS개발의 일반적인 과정을 살펴보겠습니다. 모든 프로그램

이 그렇듯, OS 개발 역시 개발에 관련된 기반 지식을 쌓는 것에서 시작합니다. 그리고 부트 로더를

거쳐 간단한 커널을 만든 뒤 그 커널에 살을 붙이는 방법으로 개발을 진행합니다. 흔히 사용하는

용어로 표현하면 Bottom-up 방식이라 할 수 있습니다.

<그림 1> 일반적인 OS 개발과정

모든 것에 기본이 중요하듯 OS 개발도 기본이 중요합니다. 하지만 <그림 1>에서 가장 아래에 있

는 항목 중, 간단한 커널이 완성된 이후에 지속적으로 활용되는 지식이 얼마나 될까요? 부트 로더

를 개발하여 커널을 로딩하는 과정을 예로 들어보겠습니다. 부트 로더를 작성하고 커널을 로딩하

기 위해서는 어셈블리어, BIOS, 플로피 디스크 또는 하드디스크 동작 방식 등등을 알아야 합니다.

하지만 이러한 지식 중에서 BIOS에 대한 지식과 플로피 디스크 또는 하드디스크 동작 방식에 대

한 지식은 거의 재활용 되지 않습니다. 이런 부분은 코드가 한번 작성된 다음 다시 수정할 필요가

적고, 보통 함수로 작성한 다음 이를 호출만하기 때문에 지식의 재활용성이 낮다고 할 수 있습니

다. 하지만 Bottom-up 방식으로 OS 개발을 진행하면 이러한 부분을 거쳐서 커널까지 올라가야 하

Version 1.0 7/27

디바이스 드라이버, 어플리케이션, GUI 추가

커널 기능 추가, 시스템 콜 및 쉘 기능 추가

부트 로더 및 커널 로더, 간단한 커널(Hello, world) 작성

CPU 아키텍처, 어셈블리어, 하드웨어 등 학습

Page 8: Os Framework 1 1 Free

므로 피해갈 수 없습니다.

필자는 이러한 과정을 여러번 거쳤습니다. 2002년에 처음 개발한 32비트 OS(INTEL 32bit

Architecture)를 시작으로 ARM7을 사용한 임베디드보드, 그리고 ARM9을 사용한 휴대용 기기, 그

리고 64비트에 멀티코어를 지원하는 OS에 이르기까지 이 과정을 반복해왔습니다. 비록 취미로 개

발하는 것이어서 간단한 기능만 가지고 있었지만, 반복해서 만드는 동안 뭔가 느낀 것이 있었습니

다.

전체 OS 개발 시간을 100으로 봤을 때 기반 지식을 쌓는 시간이 70 이상이었는데, 이 시간을 OS

본연의 기능에 투자한다면 더 좋을 것 같다는 생각이 든 것입니다. 결국 필자는 하위 레벨의 추상

화를 생각하게 되었고 이것이 바로 OS 프레임워크를 만들게 된 계기였습니다.

▶다양한 종류의 OS◄

이미 수많은 OS들이 개발되어 각자의 길을 걷고 있습니다. 그 중에는 상용으로 전환하여 사

용자를 확보하고 있는 OS(Sky OS 류)도 있고, 기존의 OS와 바이너리 레벨의 호환을 목적으

로 개발 중인 OS(React OS 류)도 있습니다. 아래는 완성도가 높은 몇 가지 OS를 선택하여

정리한 것입니다.

<화면 1> 윈도우즈와 호환되는 OS를 목표로 개발된 React OS, 높은 완성도를 보임, http://www.reactos.org

Version 1.0 8/27

Page 9: Os Framework 1 1 Free

<화면 2> 순수 어셈블리어로 작성된 Menuet OS, http://www.menuetos.net

<화면 3> 상용으로 판매되고있는 Sky OS, 상당히 높은 완성도를 보임, http://www.skyos.org

<화면 4> 필자가 만든 MINT64 OS, 64비트에 멀티코어 프로세서를 지원, http://www.mint64os.pe.kr

Version 1.0 9/27

Page 10: Os Framework 1 1 Free

2. 프레임워크와 OS 개발

프레임워크라는 단어는 이미 개발자 사이에서 친숙한 단어가 되었습니다. 웹 세상의 스프링 프레

임워크와 같은 성공한 프레임워크들 덕분에 프레임워크를 잘 모르는 필자같은(?) 사람도 이를 사

용하면 빠르고 편리하게 완성도 높은 프로그램을 개발할 수 있는 것을 알았습니다. 그렇다면 프레

임워크란 정확히 무엇일까요? 위키피디아(www.wikipedia.org)는 프레임워크를 아래와 같이 정의

했습니다.

소프트웨어 프레임워크는 소프트웨어 시스템 또는 서브 시스템을 위한 재사용 가능한 설계

이다. 설계는 추상 클래스와 인스턴스간의 협력 방법에 대한 집합이다. 소프트웨어 프레임워

크는 객체지향적으로 설계되고 일반적으로 객체지향언어로 구현되지만, 반드시 객체지향언

어일 필요는 없다. 소프트웨어 프레임워크는 개발 및 다른 컴포넌트를 연결할 수 있게 도와

주는 부분을 포함할 수 있다. 해당 파트로는 지원 프로그램, 코드 라이브러리, 스크립트 언어

또는 다른 소프트웨어등이 있으며, 프레임워크의 다양한 파트는 API를 외부로 노출할 수 있

다.

위의 정의만으로는 라이브러리와 비슷한 개념처럼 보입니다. 라이브러리와 프레임워크의 차이점

은 뭘까요? 라이브러리는 역사가 깊은 개념으로 유용한 유틸리티(함수, 클래스)들의 집합으로 볼

수 있습니다. 유저의 입장에서 라이브러리는 직접 호출하는 대상이며 주된 흐름은 유저의 코드가

제어합니다. 하지만 프레임워크는 기본적인 이벤트처리 로직을 프레임워크 내부에 포함하고 있으

며 라이브러리와 반대로 프레임워크가 유저의 코드를 직접 호출하는 방식으로 동작합니다. 이러한

특징은 프레임워크에서 일반적인 작업들을 처리하고, 유저는 필요한 경우만 코드를 추가해 프로그

램을 완성할 수 있다는 것을 뜻합니다.

이 책은 프레임워크에 대한 이해를 목적으로 하는 것이 아니므로 프레임워크에 대한 내용은 이 정

도로 정리하고, 프레임워크를 어떻게 OS개발에 접목할 수 있는지 살펴보겠습니다.

3.Bottom-up vs Top-down필자가 OS를 개발할 당시에 OS 개발 서적 또는 자료는 Bottom-Up 방식, 즉 CPU 스펙, BIOS, 어

셈블리어와 같은 하위레벨에서 상위레벨로 올라가면서 커널을 완성하는 방식이 대부분이었습니

다(유감스럽게도 후에 필자가 쓴 책도 이런 방식으로 구성되어 있습니다). 필자도 그렇게 배우기

Version 1.0 10/27

Page 11: Os Framework 1 1 Free

시작했고 많은 시간을 투자하여 결국 상위 레벨까지 구현하는데 성공했습니다. 그 당시 개발 방법

과 순서에 대해서는 크게 고민하지 않았습니다. 대부분의 자료가 Bottom-Up 방식을 따르고 있으니

당연하게 받아들였습니다.

하지만 OS를 Bottom-up 방식으로 여러 플랫폼에서 개발해보니 이 방법의 장단점을 알게 되었습

니다. <그림 2>는 Bottom-up 방식으로 개발할 때 개발 기간과 부하 사이의 그래프를 그려본 것입

니다(필자의 경험을 바탕으로 그린 것이라 여러분의 수준에 따라서는 다른 그래프가 나올 수 있습

니다). 여기서 부하는 해당 개발 단계에서 프로그래머가 가지고 있는 지식 대비 해당 단계를 넘기

위해 해야하는 노력을 뜻합니다. 즉, 부하가 높을수록 시간도 다음 단계로 넘어가기가 힘들다는 의

미입니다.

<그림 2> Bottom-up 개발 시, 단계 별 부하

Bottom-up 방식으로 OS를 개발할 때 장점은 기반이 탄탄히 다진 상태에서 OS개발을 시작하므로,

일정 단계가 지나면 개발 속도가 매우 빠르다는 것입니다. <그림 2>를 보면 부트 로더와 커널 로

더를 만드는 단계에서 부하가 최대이며 그 이후, 커널 확장과 디바이스 드라이버 등을 만드는 단계

로 넘어가면 오히려 부하가 그리 높지 않습니다. 하지만 이 방식은 실제 작동하는 OS를 만나기까

지 시간이 오래 걸린다는 문제가 있습니다. 기초 지식이 부족한 초급 프로그래머에게 커널 확장 이

전까지의 시간은 마치, 사람이 되기 위해 동굴에서 쑥과 마늘만 먹는 웅녀가 된 듯한 착각을 일으

킬 정도입니다(필자의 경험담입니다).

Bottom-Up 방식의 문제는 여기서 그치지 않습니다. 초급 프로그래머가 힘들게 기본기를 다져 벽을

오르는 동안 지쳐서 “Hello, world”를 끝으로 OS개발 의욕을 잃게 만드는 문제도 있습니다.

"Hello,world" 만 덩그러니 표시하는 OS가 무슨 OS란 말입니까? OS란 커널과 어플리케션을 위한

Version 1.0 11/27

개발단계

부하

개발 전지식습득

부트 로더,커널 로더

커널 확장,테스트

디바이스드라이버,

GUI,어플리케이션

Page 12: Os Framework 1 1 Free

서비스를 제공해야 진정한 OS라 할 수 있는데, Bottom-up 방식으로 진행하면 이러한 어려움 때문

에 “진짜 OS”를 개발하기 힘듭니다.

OS 개발을 Top-down 방식으로 진행한다면 어떻게 될까요? Top-Down 방식은 프레임워크를 통해

하위 레벨의 정보를 추상화하여 숨기고, 프레임워크 위에서 마치 어플리케이션 프로그래밍을 하듯

이 OS를 개발하는 것을 뜻합니다. 이 방식으로 개발을 진행하면 초급 프로그래머는 CPU, 하드웨

어, 어셈블리어와 같은 하위 레벨에 대한 학습 기간이 줄어들기 때문에, 초기 과부화가 획기적으로

줄어듭니다.

또한 프레임워크가 하드웨어 의존적(Hardware-dependant)부분에 대해 신뢰성있는 코드를 제공함

으로써, OS개발 초기 단계(커널 로딩까지의 단계)의 테스트 및 디버깅 시간을 줄여주는 장점도 있

습니다. 그리고 중급 또는 고급 프로그래머는 프레임워크를 분석하고 기능을 추가함으로써, 각자

가 추구하는 이상적인 OS를 쉽고 빠르게 개발할 수 있습니다. <그림 3>은 Top-down 방식으로 시

작했을 때 개발 단계 별 부하를 그래프로 나타낸 것입니다.

<그림 3> Top-down 개발 시, 단계 별 부하

앞으로 필자가 개발한 OS 프레임워크를 사용하여 Top-down 방식으로 직접 개발을 진행해볼 것이

기 때문에, <그림 3>의 그래프와 자신의 느낌을 직접 비교해보기 바랍니다.

4.OS 프레임워크

OS 계층 구조에서 OS 프레임워크가 담당하는 부분을 표시해보면 <그림 4>와 같습니다. OS 프레

Version 1.0 12/27

개발단계

부하

개발 전지식습득

디바이스 드라이버프레임워크 확장

커널어플리케이션

GUI

Page 13: Os Framework 1 1 Free

임워크는 하드웨어와 커널 사이에서 디바이스 드라이버를 제공하여 커널에서 하드웨어를 쉽게 제

어할 수 있도록 해주며, 시스템 서비스와 어플리케이션 사이에서 입출력 관련 API를 제공하여 간

단히 어플리케이션을 제작할 수 있도록 해줍니다. 비록 프레임워크가 시작 단계라서 많은 기능을

제공하지 못하지만, 부족한 부분은 추후에 추가할 예정입니다.

<그림 4> OS 계층 구조와 프레임워크

OS 프레임워크가 제공하는 기능은 아래에서 볼 수 있습니다.

• PC 부팅 이후 커널 실행 전까지 모든 단계 담당

◦ BIOS -> 부트 로더 -> 32비트 전환 -> 커널 로딩

• 키보드 처리 및 콘솔 모드 화면 입출력 함수 제공

• 태스크 스위칭 및 기타 유틸리티 함수 제공

• 기본적인 인터럽트 처리 및 인터럽트 콜백(Callback) 함수 제공

OS 개발에 뛰어들어서 초기 부하를 견디지 못해 그만둔 분이라면, 위의 기능 목록을 보고 다시

OS 개발의 의욕을 불태울지도 모르겠습니다. 위의 기능이 의미하는 바를 한마디로 하자면 OS 프

레임워크를 사용하면 어셈블리어나 하드웨어에 대한 지식이 거의 없어도 OS를 개발할 수 있다는

것입니다(물론, 이는 어디까지나 OS 프레임워크에 구현되어 있는 기능을 사용할 때입니다). 단, 프

레임워크 코드가 C 언어로 되어있으니 C 언어를 모른다면 세컨드 랭귀지로 C언어를 배우는 것을

강력히 추천합니다.

현재 OS 프레임워크는 IA-32 기반으로 작성되어있으며, 간단하기 때문에 다른 플랫폼으로 포팅

(Porting)도 그리 어렵지 않습니다. 기본 함수의 인터페이스 포팅만으로도 쉽게 OS소스 코드를 재

활용할 수 있습니다(Simple의 미학이랄까...). 1권의 마지막에는 휴대용 기기에 프레임워크를 포팅

하여 OS 코드를 재활용하는 예를 보일 것입니다(휴대용 기기의 홈브루(Homebrew) 프로그래밍에

대해 관심이 있다면 살짝 기대해도 좋습니다).

Version 1.0 13/27

하드웨어

어플리케이션(쉘, 계산기, GUI 등등…)

커널

시스템 서비스(API or System Call)

프레임워크

디바이스 드라이버

입출력 관련 API

Page 14: Os Framework 1 1 Free

연재를 통해 OS 프레임워크를 기반으로 제작할 OS는 아래와 같은 기능이 있습니다.

• 32비트 멀티 태스킹(Multi-tasking)

• 콘솔 모드 쉘(Console Mode Shell)

• 스케줄러(Scheduler)

• 동기화 객체(Synchronize Object)

• 동적 메모리 관리(Dynamic Memory Management)

• 간단한 파일 시스템(File System)

앞으로 과정은 OS 프레임워크를 활용하는 방법과 OS의 동작 원리에 초점을 맞추어 진행할 예정

입니다. OS에 부족한 부분은 여러분들이 보충할 수 있도록 충분한 설명을 덧붙일 것이니 기능을

확장하는데 큰 어려움이 없을 겁니다.

OS 프레임워크의 사용 환경과 실제 OS를 구현하는 부분은 2부부터 자세히 소개할 것이므로 1부

에서는 OS개발에 도움이 되는 내용들에 대해서 간단히 알아보겠습니다. 1부가 OS 프레임워크에

대한 이론적인 설명만 있어 아쉬워할 분들을 위해 프레임워크가 제공하는 기본 쉘의 실제 스크린

샷을 첨부했습니다(<화면 6>).

<화면 6> OS 프레임워크를 이용해서 만든 OS의 쉘 동작 화면

필자가 프레임워크를 만든 목적이 초기 과부화를 줄이는 것이라고 이야기 했습니다. 따라서

아래에서 다루게 될 하위 레벨의 내용은 프레임워크를 사용하는데 중요한 부분이 아닙니다.

Version 1.0 14/27

Page 15: Os Framework 1 1 Free

하지만 모르는 것 보다는 아는 것이 도움이 되기 때문에 간단하게 설명을 덧붙였으니 가벼운

마음으로 읽어보기 바랍니다. 복잡한 부분은 제외하고 기본적인 내용만 다룰 것이므로 처음

접하는 분도 이해하는데 큰 문제가 없을 겁니다.

혹시 이해가 잘 안되는 부분이 있더라도 걱정할 필요는 없습니다. 중요한 부분은 개발을 진

행하면서 다시 한번 자세히 설명할 예정이니 지금은 메모만 해두면 됩니다. 시스템 프로그래

밍에 익숙한 독자라면 아래의 내용들을 이미 알고 있을 것이니 다음으로 넘어가도 좋습니다.

5. 알아두면 도움이 되는 OS 개발 정보들

5-1.BIOS(Basic Input Output System)

BIOS는 메인보드(Mainboard)에 포함된 펌웨어(Firmware)의 일종으로써 메인보드에 연결된 CPU,

메모리 및 각종 주변기기들의 상태를 체크(POST, Power On Self Test)하고 시스템 전체를 초기화

하는 중요한 역할을 합니다.

BIOS는 하드웨어의 단순한 체크와 초기화만 하는 것이 아닙니다. BIOS는 예전 16비트 환경부터

디스크 입출력과 비디오 모드 전환 등 여러가지 기능을 제공했습니다. 소프트웨어 인터럽트(int 명

령어)를 통해서 BIOS의 여러 기능들을 사용할 수 있으며, 과거 MS-DOS의 경우 BIOS 서비스를

많이 이용했습니다. 또한 플로피/하드 디스크 또는 CD-ROM에서 부트 로더를 읽어 메모리에 올린

뒤 실행해주는 것 역시 BIOS가 하는 역할이니 지금도 우리는 BIOS 덕을 톡톡히 보고 있습니다.

BIOS는 메인보드의 펌웨어이므로 메인보드 제조사 별로 조금씩 차이를 보이지만, 16비트 시절부

터 사용되던 서비스들은 거의 모두 제공하고 있습니다. 그리고 최근의 BIOS는 32비트 모드에서

사용 가능한 서비스를 제공하는 것도 있습니다.

5-2.IA-32(INTEL 32bit Architecture) CPU 아키텍처

OS 프레임워크는 x86 호환 CPU를 기반으로 합니다. PC 환경의 32비트 CPU는 INTEL과 AMD에

서 생산하는 제품을 주로 사용하는데, 32비트 OS를 제작하는 것이 목표라면 두 회사의 CPU가 큰

차이가 없습니다. 따라서 앞으로 연재는 INTEL 아키텍처를 기준으로 설명하겠습니다. IA-32 CPU

의 특징 중 OS개발에 관련된 부분을 간단히 정리하면 아래와 같습니다.

Version 1.0 15/27

Page 16: Os Framework 1 1 Free

• 80386 호환 CPU 아키텍처

• 16비트, 32비트 모드 지원

• 4GB 메모리 주소 공간

• 페이징(Paing)과 세그먼테이션(Segmentation) 기능 제공

• 다중 권한 레벨(Multi-Privilege Level) 지원

IA-32 CPU는 굉장히 복잡한 구조를 하고 있는데, 자세히 설명하자면 책 한 권으로도 부족하니 꼭

필요한 부분만 살펴보겠습니다. 자세한 내용이 궁금한 분은 INTEL에서 제공하는 매뉴얼 중에

"Volume 1: Basic Architecture"를 참고하기 바랍니다(매뉴얼은 참고자료 1의 웹사이트에서 다운받

을 수 있습니다).

OS 개발과 밀접한 관련이 있는 부분을 하나 꼽으라면 당연히 레지스터입니다. 레지스터는 CPU를

위한 데이터 저장 공간으로 이후에 설명할 어셈블리어에서 중요한 역할을 합니다. IA-32 CPU에는

여러 종류의 레지스터가 있으며, 레지스터 종류에 따라 역할이 조금씩 다릅니다. <그림 5>는

INTEL 아키텍처 매뉴얼에 포함된 레지스터에 대한 정보입니다.

<그림 5> INTEL CPU 레지스터

IA-32 CPU의 레지스터는 8개의 범용 레지스터(General-Purpose Register, EAX~ESP)와 메모리의

Version 1.0 16/27

Page 17: Os Framework 1 1 Free

영역을 구분하는 6개의 세그먼트 레지스터(Segment Register, CS~GS), 현재 CPU의 상태를 나타

내는 플래그 레지스터(Program Status and Control Register, EFLAGS)와 실행 중인 코드의 위치를

나타내는 인스트럭션 레지스터(Instruction Register, EIP), 그리고 컨트롤 레지스터(Control

Register, CR)외의 특수 목적 레지스터들로 구성됩니다.

범용 레지스터는 32비트 크기인데 16비트와 8비트로 각각 나누어 사용할 수 있습니다. <그림 6>

은 범용 레지스터의 다양한 크기 별로 이름을 명명하는 방법을 나타냅니다.

<그림 6> 범용 레지스터의 크기와 이름

일반적으로 어셈블리어는 레지스터 명명법을 위와 같이 사용하고 있기 때문에, 이름을 기억해두면

후에 어셈블리어를 공부할 때 도움이 됩니다. 위의 범용 레지스터 중에 특수한 용도로 사용되는

두 레지스터가 있는데, 바로 ESP와 EBP 레지스터입니다. ESP 레지스터는 스택(Stack)의 Top을

가리키는 레지스터로써 C 언어의 함수 호출이나 지역 변수 등에 깊게 관여합니다. ESP 레지스터

의 용법에 대해서는 후에 호출 규약(Calling Convention)을 살펴보면서 다시 설명할 것이니 스택과

관련이 있다는 정도만 알고 넘어가겠습니다. EBP 레지스터는 함수를 호출할 때 스택의 Base를 지

정하는 용도로 사용되는데, 일반적으로 ESP 레지스터의 값을 임시로 저장하는 용도로 사용됩니

다. EBP 레지스터는 크게 중요하지 않으므로 ESP 처럼 스택과 관련이 있다는 정도만 알고 넘어가

겠습니다.

세그먼트 레지스터는 범용 레지스터와 함께 사용되는 레지스터로써 메모리 공간을 논리적인 블럭

단위로 나누는 역할을 합니다. 세그먼트 레지스터는 16비트 환경과 32비트 환경에서 역할이 다른

데, 16비트 환경에서는 메모리 공간의 시작 주소를 가리키는 역할을 합니다. 32비트 환경에서는

메모리 공간의 시작 주소와 크기, 속성, 권한 등의 정보가 들어있는 세그먼트 디스크립터(Segment

Version 1.0 17/27

Page 18: Os Framework 1 1 Free

Descriptor)의 위치를 가리키는 역할을 합니다. 그래서 32비트 환경에서 세그먼트 레지스터는 세그

먼트 셀럭터(Segment Selector)라는 이름으로 불립니다.

우리가 만들 OS가 32비트 OS이므로 16비트/32비트 모드에 따라 세그먼트 레지스터와 세그

먼트 셀렉터로 구분해서 사용해야 하지만, 여러분이 혼란스러울지 몰라서 세그먼트 레지스터

로 통일해서 사용했습니다. 2부부터는 구분해서 사용할 예정이니 참고하기 바랍니다.

세그먼트를 이용해서 구분할 수 있는 메모리 공간은 코드, 데이터, 스택 등의 영역으로 목적에 맞

게 설정할 수 있다. 세그먼트 레지스터는 코드를 실행할 때 또는 메모리에 접근할 때 암묵적으로

사용되는데, 세그먼트 레지스터 이름과 영향력은 아래와 같습니다.

• CS 세그먼트 레지스터

◦ 코드 실행 시에 사용

◦ EIP 레지스터와 관련됨

• DS 세그먼트 레지스터

◦ 메모리에 접근할 때 사용

◦ 메모리에 접근(읽기/쓰기)하는 레지스터와 관련됨

• SS 세그먼트 레지스터

◦ 스택에 접근할 때 사용

◦ ESP와 EBP 레지스터와 관련됨

세그먼트 레지스터와 범용 레지스터는 실질적으로 어떤 관련이 있을까요? 간단히 설명하면 어드

레스를 계산할 때 범용 레지스터의 값에 세그먼트 레지스터의 시작 주소 값이 더해집니다. 위의

CS 세그먼트 레지스터와 EIP 레지스터의 경우를 예로 들어보겠습니다. EIP 레지스터에 0x2000의

메모리 주소값이 들어있고 CS 세그먼트 레지스터가 가리키는 세그먼트가 0x10000에서 시작한다

고 가정해보겠습니다. 그렇다면 실제 실행되는 코드는 두 개의 값이 더해진 0x12000에 있으며

CPU는 이러한 방식으로 어드레스를 계산해서 코드를 실행합니다. <그림 7>은 범용 레지스터의

값에 세그먼트 레지스터가 어떻게 영향을 미치는지를 그림으로 나타낸 것입니다.

Version 1.0 18/27

Page 19: Os Framework 1 1 Free

<그림 7> 범용 레지스터와 세그먼트 레지스터의 사용

사실 세그먼트의 시작 주소를 더해서 계산된 어드레스는 선형 주소(Linear Address)라고 불리며,

이는 실제 접근하는 물리 주소(Physical Address)와 같을 수도 있고 다를 수도 있습니다. 선형 주소

는 다시 페이징 기법(Paging)에 의해 완전한 물리 주소로 변환되기 때문입니다. 페이징 기법에 대

해서 설명하는 것은 이 책의 목적을 벗어나므로, 더 자세한 내용이 궁금한 분은 INTEL 매뉴얼

"VOLUME 3: System Programming Guide"를 참고하거나 “64비트 멀티코어 OS 원리와 구조”를 참

고하기 바랍니다.

5-3.어셈블리어

OS 개발은 물론이고 시스템 프로그래밍하면 빼놓을 수 없는 것이 어셈블리어입니다. 편리하고 생

산적인 언어들이 대세인 요즘 어셈블리어의 필요성이 점점 약해지고 있지만, OS를 만들려면 한번

봐둘 필요는 있습니다.

어셈블리어는 기계어와 거의 1:1로 대응되는 구조이며, 초기의 어셈블리어는 단순히 기계어를 편

하게 작성하기 위한 수단이었습니다. 하지만 어셈블리어도 발전을 거듭하여 매크로 지원과 어셈블

리어 확장 명령, 그리고 고급 언어적인 요소들을 포함하였고, 고질적인 문제였던 낮은 생산성을 극

복하고 있습니다.

Version 1.0 19/27

Page 20: Os Framework 1 1 Free

어셈블리어 컴파일러로는 MASM, TASM, GAS, AS, NASM, FASM 등이 있고, 각 컴파일러마다 문

법과 지원하는 명령어에 차이가 있습니다. 어셈블리어 코드는 INTEL 스타일과 AT&T 스타일로 구

분하는데, 일반적으로 INTEL 스타일을 많이 사용합니다. INTEL 스타일과 AT&T 스타일의 가장 큰

차이점은 소스 레지스터와 타겟 레지스터의 위치가 서로 반대라는 점입니다. 대부분의 어셈블리어

가 INTEL 스타일의 명령어를 지원하므로 앞으로 표기할 어셈블리어 코드는 INTEL 스타일로 표기

하겠습니다. OS 프레임워크에서는 오픈소스 컴파일러인 NASM을 사용하니, 궁금한 독자들은

NASM 사이트(http://nasm.sourceforge.net)에서 다운받아 테스트를 해보는 것도 좋은 방법입니다.

어셈블리어 코드는 일반적으로 <코드 1>과 같은 형태를 하고 있습니다. <코드 1>의 코드는 실제

OS 프레임워크에서 사용되고 있는 부트 로더의 코드의 일부로써, 커널 로딩을 위한 초기화와 환영

메시지를 화면에 표시하는 역할을 합니다. 부트 로더 코드는 512Byte 미만으로 간단하며 몇 가지

어셈블리어 명령만으로 작성되어 있으므로 어셈블리어 실습에는 아주 그만입니다. 부팅 후에 결과

를 바로 확인할 수 있는 장점도 있으므로 기회가 되면 스스로 작성해보는 것도 좋습니다. 어셈블리

어는 기계어와 거의 1:1로 대응하기 때문에 많은 명령어가 있는데, 그 중에서 자주 쓰이는 명령어

몇 가지를 추려서 <리스트 1>에 정리해 놓았다.

<코드 1> 부트 로더 어셈블리어 코드[org 0x00]jmp 0x07c0:startstart :

mov ax, cs

mov ds, ax

mov es, ax

; 스택의 설정

; 함수 호출을 위해 필수

mov ax, 0xffff

mov ss, ax

mov ax, 0xffff

mov sp, ax

mov bp, ax

... 생략 ...

fill :

mov byte [gs:bx], 0x00

Version 1.0 20/27

Page 21: Os Framework 1 1 Free

sub bx, 2

cmp bx, 0

ja fill

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; OS 메시지를 화면에 출력한다.

mov ax, 0x03

push ax

mov ax, MSG0

push ax

mov ax, 1

push ax

mov ax, 1

push ax

call print

... 생략 ...

<리스트 1> 자주쓰는 어셈블리어 명령(NASM 기준)

• mov A, B : B에서 A로 값을 이동

• cmp A, B : 두 값을 비교하여 결과를 EFLAGS 레지스터에 업데이트

• rep instruction : 명령을 CX 레지스터의 값 만큼 반복 수행

• call X : 스택에 반환 주소를 삽입하고 X 위치의 코드를 실행, 함수를 호출하는 용도로 사용

• jmp X : 무조건 해당 주소로 이동하여 X 위치의 코드를 실행

• je, ja, jxx X : 조건 분기 명령, EFLAGS 레지스터의 플래그 값에 따라서 jmp 수행(보통 cmp

와 같은 명령어와 함께 사용), 다양한 종류의 명령이 있음

• push X: X의 값을 스택에 저장

• pusha, pushad : 스택에 레지스터 값을 저장. EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI을

차례대로 저장

• pop X : 스택에서 값을 꺼내 X에 저장

• popa, popad : 스택에서 값을 꺼내 레지스터에 저장. 위의 pushad 명령과 같은 순서의 레지

스터 사용

Version 1.0 21/27

Page 22: Os Framework 1 1 Free

• add A, B : A에 B의 값을 더한 후 A에 저장

• sub A, B : A에서 B의 값을 뺀 후 A에 저장

• mul A : EAX의 레지스터 값과 A의 값을 곱한 후 A에 저장

• inc A : A의 값을 1 증가

• ret, retn X: 스택에서 반환 주소를 꺼내 이동한 뒤 스택의 값을 X 만큼 줄임(보통 Call 명령

어과 짝으로 사용)

• iret, iretd : 인터럽트 처리 시에 사용하는 ret 명령, EFLAGS 레지스터의 값과 함께 반환 주

소로 이동

• or A, B : A에 B값을 OR한 뒤 A에 저장

• xor A, B : A에 B값을 XOR한 뒤 A에 저장

• not A : A의 값을 반전(0->1, 1->0)한 뒤 A에 저장

• int X : X번째의 소프트웨어 인터럽트(Software Interrupt)를 발생

• cli : 인터럽트 발생 불가 설정

• sti : 인터럽트 발생 가능 설정

• in X, Y : I/O 포트 Y에서 값을 읽어서 X에 저장, 주변 장치 제어 용도의 명령

• out Y, X : X의 값을 I/O 포트 Y에 출력, 주변 장치 제어 용도의 명령

<리스트 1>에서 정리한 어셈블리어 명령만 알아도 프레임워크의 코드를 이해하는데 큰 어려움이

없습니다. 세부적인 동작 방식이나 위에서 언급하지 않은 명령이 궁금한 독자들은 역시 INTEL 매

뉴얼 "VOLUME 2: Instruction Set Reference"를 참고하기 바랍니다.

개인적인 취향 때문에 NASM이 아닌 다른 어셈블리어 컴파일러를 사용하고 싶은 독자들이 있을

것이라 생각합니다. 프레임워크의 어셈블리어 코드는 NASM으로 작성되었지만, NASM에 의존적

인 명령어는 거의 사용하지 않았습니다. 따라서 다른 어셈블러를 사용하고 싶다면 쉽게 소스를 다

른 어셈블리어로 포팅할 수 있습니다. OS 프레임워크를 빌드하는 컴파일러와 세부 옵션들을 설정

하는 부분은 2부에서 다룰 예정이니, 선호하는 어셈블리어 컴파일러가 있다면 OS를 개발할 수 있

도록 미리 준비해두는 것도 좋은 방법입니다.

Version 1.0 22/27

Page 23: Os Framework 1 1 Free

5-4.호출 규약(Calling Convention)

호출 규약(Calling Convention)은 함수에 어떻게 파라메터를 전달하고 어떻게 결과 값을 얻을 것인

가에 대한 규약입니다. 호출 규약은 stdcall, cdecl, fastcall, syscall 등이 있는데, 일반적으로 많이 사

용하는 stdcall과 cdecl만 간단히 알아보겠습니다.

x86 호환 CPU에서 stdcall과 cdecl의 공통점은 EAX 레지스터를 통해서 결과 값을 받는 겁니다(결

과 값이 64비트일 경우, 상위 32비트는 EDX, 하위 32비트는 EAX를 사용합니다). 차이점은 스택을

정리하는 쪽이 호출자(Caller)인가 아니면 피호출자(Callee)인가 하는 부분인데, stdcall의 경우는

피호출자(Callee)가 스택을 정리하며 cdecl의 경우는 호출자(Caller)가 스택을 정리합니다. 스택은

LIFO(Last In First Out)의 자료구조로써 x86 호환 CPU에서는 하드웨어적인 명령어(push와 pop 명

령어)으로 스택을 지원합니다. x86의 스택은 높은 주소(4G 방향)에서 낮은 주소(0 방향)로 자라게

되어있으며 스택의 Top은 ESP 레지스터를 통해 지정합니다. 아래의 간단한 코드를 통해서 stdcall

과 cdecl의 차이점에 대해서 좀더 자세히 알아보겠습니다.

<코드 2> 함수 호출 예제

int A( int a, int b ){

int c;

c = a+b;

return c;}

int main(int argc, char* argv[]){

int iRet;

iRet = A( 1, 2 );}

<코드 2>는 A 함수를 호출해서 결과 값을 저장하는 아주 간단한 코드입니다. 위의 코드를 stdcall

과 cdecl로 각각 호출했을 때, 스택의 Top의 위치와 스택의 내용은 <그림 8>와 <그림 9>로 나타낼

수 있습니다.

Version 1.0 23/27

Page 24: Os Framework 1 1 Free

<그림 8> stdcall 방식의 스택

<그림 9> cdecl 방식의 스택

<그림 8>에서 보듯이 stdcall의 경우는 A 함수(Callee)에서 리턴할 때 A 함수가 스택 정리를 수행하

므로 main 함수(Caller)에서는 스택 정리에 관여하지 않습니다. 하지만 <그림 9>처럼 cdecl 방식의

경우는 A 함수(Callee)에서 리턴할 때 스택 정리를 수행하지 않으므로, main 함수(Caller)가 별도의

단계를 거쳐서 스택을 정리합니다. C언어에서 사용하는 호출 규약은 일반적으로 cdecl이며, cdecl

의 장점은 호출자(Caller)가 스택을 정리하므로 피호출자(Callee)에게 가변적 인자(Variable

Argument)를 넘겨줄 수 있다는 점입니다.

왜 cdecl은 가변적 인자를 넘기는 것이 가능할까요? 그 이유는 피호출자가 스택 정리에 관여하지

않기 때문입니다. 호출자는 피호출자에게 넘겨준 파라미터의 개수를 알고 있으므로 가변적인 파라

메터를 사용하는 경우에도 스택을 제대로 복원할 수 있습니다. 반대로 피호출자가 스택 정리를 수

행하는 stdcall의 경우, A 함수에서 스택 정리를 해야하기 때문에 A 함수는 파라미터의 개수를 정확

Version 1.0 24/27

2

1

Return Address

main에서 A 호출함수 A에서 return 수행

(스택 정리 수행)

함수 호출 전main의 스택

A 함수 호출 후main의 스택

Low Address(0)

High Address(4G)

: 스택의 Top (ESP 레지스터)

2

1

Return Address

2

1

main에서 A 호출 함수 A에서 return 수행

함수 호출 전main의 스택

A 함수 호출 후main의 스택

LowAddress(0)

HighAddress(4G)…

파라미터 정리 후main의 스택

main에서 파라미터 정리

: 스택의 Top (ESP 레지스터)

Page 25: Os Framework 1 1 Free

히 알고 있어야 합니다. 하지만 일반적인 함수 호출에서는 파라미터의 개수를 넘겨주지 않으므로

스택 정리를 정확히 할 수 없기 때문에 stdcall은 가변 인자 처리가 어렵습니다.

가변적 인자를 사용하는 대표적인 함수로는 printf, scanf 류의 함수가 있으며, 이 함수들을 생각해

보면 가변 인자의 장점이 무엇인지 확실히 알 수 있을 겁니다(printf가 고정적인 개수의 파라미터를

받는다고 상상해보세요, 다양한 파라미터를 받는 다양한 버전의 printf 함수를 만들어야 할지도 모

릅니다). 실제 호출 규약 별로 어셈블리어 코드를 보면 좀더 명확하게 알 수 있지만, 어셈블리어에

익숙치 못한 분들을 위해 그림으로 간단히 설명했습니다. 호출 규약에 대해 보다 자세한 내용이 궁

금한 분들은 위키피디아(http://en.wikipedia.org/wiki/Calling_convention) 를 참조하거나 “64비트 멀

티코어 OS 원리와 구조”를 참조하기 바랍니다.

Operating System Resource Center

앞으로 연재를 진행하면서 하드웨어와 관련된 하위 레벨에 대한 내용들은 거의 다루지 않을

생각입니다. OS 프레임워크를 사용하는 목적이 하위 레벨에 대한 지식 없이도 쉽게 OS를 개

발하는 것이기 때문에, 설명을 하더라도 꼭 필요한 부분만 살펴볼 겁니다. 연재에서 언급하지

않는 부족한 내용들은 <화면 7>의 사이트를 참고하면 보충할 수 있으니, 기회가 되면 한 번

쯤 방문하여 자료를 읽어보는 것도 좋습니다(OS 개발자라면 한 번쯤은 들러본 기억이 있을

겁니다).

<화면 7> Operating System Resouce Center, http://www.nondot.org/sabre/os/articles

Version 1.0 25/27

Page 26: Os Framework 1 1 Free

이상으로 OS 프레임워크와 OS 개발에 대한 기본적인 내용을 간단히 알아보았습니다. 2부에서는

OS 프레임워크를 사용하기 위한 환경을 구축하고 직접 구현한 OS를 테스트하는 방법에 대해서

살펴볼 것입니다.

Version 1.0 26/27

Page 27: Os Framework 1 1 Free

6. 참고 자료

• 64 비트 멀티코어 OS 원리와 구조 , 한빛 미디어◦ http://www.mint64os.pe.kr

• INTEL Architecture Manual◦ http://developer.intel.com/products/processor/manuals/index.htm

• 고급 개발자들만이 알고 있던 OS제작의 원리 그리고 CODES, 가남사◦ http://www.bellon2.com

• OS개발 관련 자료◦ http://www.nondot.org/sabre/os/articles

• 필자의 블로그◦ http:// kkamagui.tistory.com

Version 1.0 27/27