* Cygwin이 자주 업데이트 되는 바람에 가상머신을 사용해서 개발하실 수 있도록 준비했습니다. 계속해서 빌드에 오류가 생기신다면 http://jsandroidapp.cafe24.com/xe/8920 에 가셔서 가상머신을 사용하시기 바랍니다. ^^

* 2014년 4월 13일자 Cygwin을 기준으로 내용이 업데이트 되었습니다 ^^

* 빌드에 문제가 생기거나 정상적으로 동작하지 않는다면, MINT64 OS 개발용 가상머신을 이용하세요 ^^

** 가상머신 이미지 다운로드: http://jsandroidapp.cafe24.com/xe/8920**

* 관련 내용은 64비트 멀티코어 OS 원리와 구조 QnA 사이트(www.mint64os.pe.kr)에서 계속 업데이트 되고 있습니다. ^^


제 책 "64비트 멀티코어 OS 원리와 구조" 가 나온지도 벌써 3년이 지났습니다. ^^;;; 책이 출간됨과 동시에 가장 많이 질문을 받는 것이 OS 제작을 위한 환경 구축 방법인데요...

얼마전부터 환경 구축에 어려움을 겪는 분들이 많아지셔서 Cygwin 최신 버전을 다운 받아서 빌드를 해봤습니다. ^^;;; 실제로 빌드를 진행하다보니 몇 가지 변경점이 보이더군요. ㅠㅠ 그래서 그 내용을 여기다가 정리해놓습니다. ㅠㅠ

<출처 - yes24.com>

ps1) 혹시 아래대로 수행했는데 빌드에 문제가 생기거나 정상적으로 동작하지 않는다면, 곧 업로드될 MINT64 OS 개발용 가상머신을 이용하세요 ^^ ps2) 안타깝게도 Cygwin에 덮어쓰는 방법은 이제 더이상 동작하지 않습니다.


Cross Compiler를 만들려면 먼저 Cygwin 사이트(http://www.cygwin.com/install.html)로 이동해서 32비트 Cygwin Installer를 다운로드 받습니다. Setup.exe 파일을 다운하면 됩니다. ^^;;;

다운로드 후 파일을 실행하면 어떻게 설치할 것이고 패키지 소스는 어디에서 다운 받을 것인지 선택하는 부분이 나오는데, 책에 나와있는 카이스트 사이트(ftp://ftp.kaist.ac.kr)가 더이상 유효하지 않으니 다른 사이트를 선택해야합니다.

우리나라 근처에 있는게 아무래도... 속도도 빠르니 가까운 일본 주소인 ftp://ftp.jaist.ac.jp를 선택하면 됩니다. ^^;;; 패키지 소스를 다운 받을 주소를 선택하고 난 뒤에는 "Select Package" 화면이 나올 때까지 적당히 Next를 선택해주면 됩니다. ^^;;;

"Select Package" 화면이 나오면 아래의 항목들을 설치해줍니다. 책을 쓸 때는 C++ 관련 항목이 없어도 정상적으로 빌드가 되었지만, 지금은 C++ 컴파일러를 설치하지 않으니 configure 중에 오류가 발생하더군요. ㅠㅠ

+Devel
    + binutils - 2.24.51-2 버전, 소스 및 바이너리 모두 설치
    + bison - 2.7.1-1 버전, 바이너리만 설치
    + flex - 2.5.35-1 버전, 바이너리만 설치
    + gcc-core - 4.8.2-2 버전, 소스 및 바이너리 모두 설치
    + gcc-g++ - 4.8.2-2 버전, 바이너리만 설치
    + libiconv - 1.14-2 버전, 바이너리만 설치
    + libtool - 2.4.1 버전, 바이너리만 설치
    + make - 4.0-2 버전, 바이너리만 설치
    + patchutils - 0.3.2-1 버전, 바이너리만 설치
+Libs
    + libgmp-devel - 6.0.0a-1 버전, 바이너리만 설치
    + libmpfr-devel -3.1.2-1 버전, 바이너리만 설치
    + libmpc-devel - 1.0.2-1 버전, 바이너리만 설치
    + libncurses-devel - 5.7-18 버전, 바이너리만 설치

위의 항목이 설치되고 나면 binutils부터 차례대로 빌드를 시작하면 됩니다.

binutils를 빌드하려면 /usr/src 디렉터리 아래에 있는 binutils 디렉터리로 이동해서 다음과 같은 순서로 커맨드를 입력하면 빌드와 설치가 끝납니다.

// 디렉터리 이동 후 아래 작업 수행
$> cd /usr/src/binutils-2.24.51-2   <== 디렉터리 이름은 binutils 버전에 따라 다를 수 있음    
$> export TARGET=x86_64-pc-linux
$> export PREFIX=/usr/cross
$> ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared --disable-nls
$> make configure-host
$> make LDFLAGS="-static"
$> make install

아래는 테스트를 위한 부분입니다. 아래처럼 커맨드를 실행했을 때 x86_64 관련 항목이 보이면 제대로 된 것입니다. ^^;;;;

$> /usr/cross/bin/x86_64-pc-linux-ld --help | grep "supported "
/usr/cross/bin/x86_64-pc-linux-ld: supported targets: elf64-x86-64 elf32-i386 a.
out-i386-linux efi-app-ia32 efi-bsdrv-ia32 efi-rtdrv-ia32 efi-app-x86_64 efi-bsd
rv-x86_64 efi-rtdrv-x86_64 elf64-little elf64-big elf32-little elf32-big srec sy
mbolsrec tekhex binary ihex
/usr/cross/bin/x86_64-pc-linux-ld: supported emulations: elf_x86_64 elf_i386 i38
6linux

binutils 빌드 및 설치가 끝났다면 gcc를 cross compile할 차례입니다. gcc는 아래와 같은 순서로 입력하면 빌드와 설치가 완료됩니다. ^^;;;

압축 해제, 파일명은 cygwin에서 다운받은 GCC 버전에 따라서 다를 수 있으니 실제 디렉터리를 확인하여 입력해야 합니다. ^^;;; 아래 패치 파일도 모두 마찬가지 입니다.

$> cd /usr/src
$> tar -xvf gcc-4.8.2.tar.bz2
$> export TARGET=x86_64-pc-linux
$> export PREFIX=/usr/cross
$> export PATH=$PREFIX/bin:$PATH

압축 해제가 끝났으니 소스가 있는 디렉터리 이동 후 나머지 작업 수행합니다.

$> cd /usr/src/gcc-4.8.2    <== 디렉터리 이름은 GCC 버전에 따라 다를 수 있음
$> ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --without-headers --disable-shared --enable-multilib
$> make configure-host
$> make all-gcc
$> make install-gcc

빌드가 완료된 후 테스트용입니다. 아래와 같이 입력했을 때 m64가 보이면 정상적으로 설치된 것입니다.

$> /usr/cross/bin/x86_64-pc-linux-gcc -dumpspecs | grep -A1 multilib_options
*multilib_options:
m64/m32

빌드한 크로스 컴파일러는 MINT64 OS를 개발하는데 필요한 최소한의 환경만 구성되어 있습니다. 64비트 관련 gcc 라이브러리 등은 빌드되지 않은 상태이므로, 빌드된 컴파일러로 test.c 파일을 빌드했을 때 발생하는 오류는 무시하셔도 됩니다. ^^

자, 이제 64비트 바이너리를 생성할 수 있는 gcc가 생성되었으니, 즐거운 OS 프로그래밍하세요 ;)

64비트 멀티코어 원리와 구조가 나온지 약 3년이 지났습니다. 그동안 QnA 사이트를 운영하면서 가장 많이 받았던 질문이 개발환경 설정에 대한 글이었는데요, 아무래도 cygwin 버전이 올라가다보니 책에 있는 빌드방법으로는 제대로 빌드가 되지 않더라구요(지금도 개발환경에 대한 질문이 계속 올라온다는...). ㅠㅠ 그래도 많은 분들이 도와주셔서 어찌어찌 성공하신 분들도 있지만... 사실 책임은 저한테 있는지라 언젠가는 해결해야 겠다고 생각했습니다.

<64비트 멀티코어 원리와 구조 - 출처 yes24>

그래서~!!! 오늘 애기를 빡시게 놀게한다음 일찍 재우고 다시 개발환경을 만드는 중입니다. 그래서 내용도 업데이트하고 이번에는 가상머신으로 만들어서 다운받아 바로 쓸 수 있도록 만들 생각입니다. @0@)-b 이렇게 하면 빌드에 문제가 생겨도 가상머신을 다운받아 실행하면 되니 문제가 없을 것 같더군요. ^^;;;

크로스 컴파일러를 만드는게 시간이 많이 걸리는지라... 지금 시작하면 언제 끝날지 잘 모르겠네요. ㅠㅠ 그래도 이번에 확실히 해서 큰 포부를 가지고 OS 개발을 시작하셨다가... 개발 환경 설정 때문에 좌절하시는 일이 없도록 잘 해보겠습니다. @0@)/~

그럼 좋은 밤 되세요 >ㅁ<)-b

ps1) 아침에는 개발 환경 설정을 업데이트 할 수 있으면 좋겠네요 ㅠㅠ

ps2) Yes24 사이트에서는 책이 품절로 나오는군요. ' ')a... 교보문고에 가시면 아직 구할 수 있습니다. ^^

0. 들어가기 전에...

이 글은 64비트 멀티코어 OS 구조와 원리의 QnA 사이트(http://mint64os.pe.kr)에 등록된 RUMO님의 질문과 그에 대한 답변을 요약한 것입니다. 자세한 내용은 C언어로 커널을 개발중입니다를 참고하시기 바랍니다. ^^


1. 질문 내용

안녕하세요; 커널을 혼자 공부중인 학생입니다...

아주 기초부터 썩어빠진 놈이 커널짠답니다.

2개월째 낑낑 대는데 아주 기초적인 부분부터 막막합니다. 자비를 베풀어 도움을 주십사 합니다 ㅠ

먼저 boot.asm 을 만들었습니다....부트로더이지요. 책을 참고하여 만들었습니다.

또 어셈블리어로 kernel.bin을 만들었습니다. boot.asm이 kernel.bin으로 점프하지요. 맞습니다 여기까지 잘됩니다.

헌데 커널을 C언어로 작성한뒤 병합하니 이상하게도 boot.asm만 실행된다는 것입니다.

일단 개발환경부터 말씀드리자면 VM웨어에 우분투를 설치하여 작업중이며 테스트 또한 VM에 테스트중입니다.

원래 boot.asm과 kernel.asm은 아래와 같이 컴파일 하였습니다.

nasm -f bin -o boot.bin boot.asm nasm -f bin -o kernel.bin kernel.asm cat boot.bin kernel.bin > kernel.img

커널이 어셈으로 짜여졌을때는 매우 잘 동작 하였습니다.

헌데 C언어로 짠 커널 (ckernel.c라고 하겠습니다.)...

nasm -f bin -o boot.bin boot.asm gcc -c ckernel.c ld -e ckernel -Ttext 0x00 -e textout ckernel.c objcopy -R .comment -R .note -S -O binary ckernel.c ckerenl.bin cat boot.bin ckernel.bin > ckernel.img

이렇게 컴파일 하니 부트로더만 동작한다는 것입니다...

그러던중 알게된것이 엔트리 포인트입니다만 이것또한 저에겐 너무 와닿지 않는 개념인지라;;;

당췌 어찌 해야될지 모르겠습니다. 컴파일도 제대로 하고 있는게 맞는지; 엔트리 포인트를 제대로 찍은건지;

초보자라 설명도 중구난방입니다...첨부 파일을 보시면 바로 이해가 되실겁니다 -_-;;

몇주째 개고생중입니다. 제발 도와주십시오 ㅠ


2.답변 내용

안녕하세요, 커널을 만드시느라 고군분투하고 계시는군요. ^^

어셈블리어로 작성된 부트로더에서 C 언어로 작성된 32비트 커널로 점프하기 위해서는 크게 2가지가 필요합니다.

첫 번째는 스택입니다. 스택에 관련된 레지스터는 ESP와 EBP가 있는데, 1Mbyte 이하 영역중에서 마음에 드는 곳을 지정해주면 됩니다. 한가지 주의할 점은 스택은 아래로 자라기 때문에 레지스터에 설정하는 값이 스택 영역의 끝부분을 가리키고 있어야겠지요. boot.asm을 ESP는 초기화하여 스택은 만들어 놓으셨더군요. 그런데 EBP는 초기화 되어있지 않던데 EBP 레지스터도 ESP와 같은 값으로 초기화하면 좋을 것 같습니다. ^^;;;

두 번째는 엔트리 포인트입니다. 엔트리 포인트는 C 코드가 제어를 넘겨받았을 때 제일 처음 코드 수행을 시작해야 하는 부분을 나타냅니다. 만일 빌드 결과물이 리눅스의 ELF 파일 포맷이나 윈도우의 PE 파일 포맷 형식이라면 링커(LD)에 -e 옵션을 주어 엔트리 포인트를 지정해주는 것이 의미가 있습니다. 하지만, 지금은 커널을 만들고 있고 실제로 C 코드의 출력 결과물은 메타 정보 없이 코드/데이터만 들어있는 바이너리(Binary) 형식을 사용하고 있으니, 링커에서 지정해준 엔트리 포인트는 의미가 없습니다.

따라서 강제로 엔트리 포인트인 kernel_main() 함수를 부트로더가 점프하는 어드레스인 0x10000로 지정해줘야 합니다(kernel.c 파일을 보고 엔트리 포인트 함수가 저게 아닐까 생각했는데, 원하시는 함수가 있으시면 그걸로 선택하시면 됩니다 ^^). 저도 예전에 이 문제로 고민을 많이 했는데요, 해결방법은 아주 간단합니다. 컴파일러가 코드를 컴파일할 때 실제로 C 파일에 나열된 함수의 순서를 그대로 따릅니다. 그러니 엔트리 포인트로 사용할 함수를 C 파일에 가장 위쪽으로 옮겨주면 되겠지요. ^^

두 부분을 제외한 나머지는 제가 봤을 때 충분한 것 같네요. ^^ 부트로더에서 C 언어 커널로 점프하는 부분에 대한 더 자세한 내용이 궁금하시다면, 64비트 멀티코어 OS 원리와 구조 에서 7장을 참고하시면 됩니다. 엔트리 포인트에 대해서도 자세히 설명해 놓았으니 도움이 되실겁니다. ^^

그럼 파이팅입니다. ^^

ps) OS를 빌드하실 때 배치 파일이나 makefile을 이용하시면 좀더 편리하게 작업하실 수 있습니다. ;)

64비트 멀티코어 OS 원리와 구조 세트가 출간된지 3년이 다 되어갑니다. 책에 대한 QnA 사이트가 필요해서 책 출간과 동시에 mint64os.pe.kr 사이트도 운영 중인데요, 지금까지 약 300개의 QnA가 달렸습니다. @0@)/~ (그중에 오탈자에 대한 문의도 다수 있다는 건 함정... 쿨럭..;;;)

<출처 - yes24.com>

질문에 대해서 답변을 달다보면 가끔 통찰력이 느껴지는 질문도 있는데요, 이런 질문들은 혼자보기가 아깝더라구요. ^^;;; 그래서 정리해서 공유하는게 어떨까하는 생각을 했습니다. 시간이 나는대로 틈틈이 정리해서 올려볼 예정이니 기대해주세요 >ㅁ<)/~

그럼 좋은 하루 되세요 ^^

지난번에 Workspace님께서 MINT64 OS를 Mac OS X에서 개발하는 방법(http://osdevlog.tistory.com/1)을 올려주셨는데요, 

이번에 Jungsub K님께서도 내용을 조금 보강해서 올려주셨습니다. 감사합니다. Jungsub K님 ^^


해당 내용은 여기(http://nayuta.net/64비트_멀티코어_OS_원리와_구조/OS_X에서_개발환경_구축하기)에서 보실 수 있습니다.


각 OS에서 빌드하는 방법을 올려주시니... 왠지 MINT64 OS가 관심받고 있는 것 같아 마음이 훈훈하네요. ㅠㅠ


나중에 활동 많이 해주시는 분들을 모아서 식사라도 한 끼 대접해야할 듯 싶습니다. ㅠㅠ


다들 감사드리고, 앞으로도 많은 관심 부탁드립니다. (_ _)



"64비트 멀티코어 OS 원리와 구조"가 출간된지 벌써 1년이 다되었습니다. ^^)-b 그동안 MINT64 OS 개발과 관련해서 많은 질답이 오고 갔는데요, 그중에서 빼 놓을 수 없는 것이 바로 "개발 환경 설정"과 관련된 내용입니다. ㅠㅠ 실제로 개발 환경 설정때문에 많은 분들이 고생을 하고 계신데요, 이 문제로 고민하시던 Ethobis님께서 해결책을 내놓으셨습니다(Ethobis님 감사합니다. ㅠㅠ).


Ethobis님께서 사용하신 방법은 Cygwin을 기본으로 설치하고 난 뒤 부록 CD에 있는 개발환경을 그대로 복사하는 방법인데요, Cross Compiler를 만드는 복잡한 단계를 거치지 않아도 되기 때문에 괜찮은 것 같습니다. ^^


부록 CD를 다운 받는 곳과 Ethobis님의 글은 아래에서 보실 수 있습니다. ;)


    부록 CD : http://jsandroidapp.cafe24.com/xe/220

    Ethobis님의 글 : http://ethobis.tistory.com/63


그럼 즐거운 OS 프로그래밍하세요 :)


ps) 좋은 팁을 알려주신 Ethobis님께 감사의 말씀을 전합니다. ^^

"64비트 멀티코어 OS 원리와 구조"가 2012년 대한민국 우수학술도서로 선정된지 얼마되지 않아서 또 기쁜소식이 들려왔습니다. Workspace님께서 MINT64 OS를 Mac OS X 10.7.4에서 빌드하는 방법을 올려주셨거든요 ;)


아래 글 링크 나갑니다.


    OS X 10.7.4에서 개발 환경 구축하기: http://osdevlog.tistory.com/1

    Chapter 7 C Kernel 실행까지~: http://osdevlog.tistory.com/2


Workspace님 감사합니다. :)

즐거운 OS 개발 하시길 바래요 ^^)-b

근 한달동안 모든 코딩을 어셈블리어로만 하고 있다보니 호출 규약(Calling Convention)을 다시 살펴보고 있습니다. C로 프로그래밍하던 시절에는 호출 규약은 별로 신경쓰지 않았는데, 어셈블리어로 함수를 호출하려니 안 볼수가 없더군요. ㅠㅠ


MINT64 OS를 만들 때 어셈블리어로 코딩했으면서 왠 엄살이냐고 생각하실텐데... 리눅스에서 사용하는 호출 규약(Calling Convention)과 윈도우에서 사용하는 호출 규약은 상당한 차이가 있더라구요. ㅠㅠ 그래서 적응하는데 살짝 힘들었습니다. 사실 적응한다기 보다는 차이를 아는데 시간이 좀 걸렸지요. ㅠㅠ

64비트 리눅스의 호출 규약

리눅스는 64비트 모드에서 파라미터를 전달할 때 윈도우보다 레지스터를 더 많이 사용합니다. 정수 타입의 파라미터를 전달할 때는 순서대로 RDI, RSI, RDX, RCX, R8, R9까지 6개의 레지스터를 사용하고 7개 이상이면 스택을 통해 전달합니다. 실수 타입의 파라미터의 경우는 XMM0 ~ XMM7까지 8개를 순서대로 사용하고 그 이상이면 스택으로 전달하지요. ;)


반환값은 정수일 때 RAX(하위 64비트), RDX(상위 64비트)를 사용하고, 실수일때는 XMM0(하위 128비트), XMM1(상위 128비트)를 사용합니다. 아래는 64비트 멀티코어 OS 원리와 구조의 11.2.2 장에서 추출한 호출 규약 그림입니다. ;)




64비트 윈도우의 호출 규약

반면, 윈도우는 64비트 모드에서 파라미터를 전달할 때 레지스터 4개만 사용합니다. 정수 타입의 경우는 순서대로 RCX, RDX, R8, R9를 사용하고 나머지는 스택으로 전달합니다. 실수의 경우는 XMM0 ~ XMM3까지 4개를 순서대로 사용하며 나머지는 스택으로 전달합니다. 여기까지 보면 파라미터로 사용하는 레지스터의 종류와 개수만 차이가 나는 것 같습니다만.... 실제로 보면 스택을 사용하는 방법도 차이가 있습니다.


리눅스의 경우 파라미터를 전달할 때 스택을 꽉꽉 채워서 사용하는 반면, 윈도우의 경우는 4개의 레지스터가 들어갈 공간만큼을 띄워서 사용합니다. 즉, 파라미터 4개가 RCX, RDX, R8, R9를 통해 전달되지만, 스택에 이 4개를 위한 공간을 할당해놓는 것이죠. 아래 그림을 보시면 좀 더 이해하시기 편할 겁니다. ^^;;;





이 차이 때문에 한참을 헤맸네요. ㅠㅠ 스택에 저 공간을 안 할당해놓으면 파라미터가 잘못 전될되서 보기좋게 함수 호출이 실패를... 쿨럭..;;; 그리고 주의할 점은 비록 파라미터가 4개 미만이더라도 함수 호출 시 저 영역은 무조건 할당해야 한다는 겁니다. 에궁... 진짜 알고나면 별 것 아닌데... 코드를 몇 번이나 갈아 엎었는지 모르겠네요. ㅠㅠ


C로 코딩을 했으면 아예 신경을 안써도 되는 부분인데... 어셈블리어로 코딩하다보니 삽질을 하고 말았군요. ㅎㅎ 윈도우 호출 규약에 대한 보다 자세한 내용이 궁금하시다면 MSDN 사이트를 참고하시기 바랍니다. ^^


그나저나 PE32 파일 포멧을 읽어 메모리에 로딩하여 실행하는 가볍게 어셈블리어로 작성하는 괴수(?)를 어떻게해야 따라잡을 수 있을까요? 아우... 따라가려니 죽을 것만 같네요. ㅠㅠ


그럼 좋은 밤 되세요 ;)

<64비트 멀티코어 OS 원리와 구조>


제가 오랜시간을 걸쳐 정리한 책, 64비트 멀티코어 OS 원리와 구조가 "2012년 대한민국학술원 우수학술도서"에 선정되었습니다. 이런 영광이... 제게도 이런 날이 오는군요. ㅠㅠ)-b 우수 학술 도서 목록은 http://www.nas.go.kr/info/notice/view.jsp?NP_Code=10000043&NP_DataCode=20000014&NGB_Code=10001430에서 살펴보실 수 있습니다. ^^


그동안 64비트 멀티코어 OS 원리와 구조를 구매해주신 많은 분들께 감사드리며, 우수학술도서로 선정될 수 있도록 힘써주신 한빛미디어의 한동훈님께 감사드립니다. 그리고 책이 나올 수 있도록 도와주시고 응원해주신 많은 분들께도 감사의 말씀을 드립니다. 앞으로 책이 많이 나가서 얼른 2쇄 찍고 부끄러운 오탈자를 정리할 수 있으면 좋겠네요. ㅠㅠ)-b


앞으로 더욱 열심히 하는 kkamagui가 되겠습니다. ^^)-b

그럼 좋은 밤(?) 되세요 ;)


굵게 표시된 부분이 오타가 수정된 부분입니다.


==== 1권의 오탈자 내용 ====

*. 79 Page, 아래에서 5 번째 줄

보호 모드는 IA-32e 모드로 전환하려면 공식적으로 거쳐야 하는 모드로, 32비트 윈도우나 리눅스 OS가 동작하는 기본 모드입니다.


*. 80 Page, 위에서 6 번째 IA-3e 모드를 IA-32e 모드로 수정

IA-32e 모드


*. 80 Page, 아래에서 5 번째줄

리얼 모드에서 전환할 수 있는 모드는 공식적으로 보호 모드뿐 이며, 보호 모드에서는 가상 8086 모드나 IA-32e 모드, 다시 리얼 모드로 전환할 수 있습니다. 시스템 관리 모드는 모든 모드에서 진입할 수 있고, 처리가 끝나 이전의 운영 모드로 복귀하거나 리셋을 통해 리얼 모드로 진입할 수 있습니다.


*. 80 Page, 아래에서 3 번째 줄

화살표가 연결되지 않은 리얼 모드에서 IA-32e 모드로 전환하는 것은 불가능하며, 무리하게 시도하면 리셋이나 예외가 발생할 수있습니다(실제 편법을 사용하면 가능하긴 하지만 여기서는 다루지 않습니다).


*. 83 Page, [그림 3-3]에서 128비트 XMM 레지스터(16개), 64비트 RIP, 64비트 RFLAGS, CR8 레지스터 부분 수정됨

[그림 3-3].PNG


*. 85 Page의 "여기서 잠깐"의 시작에서 6번째 줄

곱셈 명령은 AX와 오퍼랜드를 곱한 후, 그 결과를 DX:AX나 혹은 AX에 저장하도록 설계되었습니다.


*. 87 Page 아래에서 5번째 줄부터...

그렇다면 어떻게 해야 할까요? 프로세서 제조사에서는 이런 경우를 대비하여 무조건 분기 명령어(jmp)에 예외를 두었습니다.

즉, 무조건 분기 명령어의 오퍼랜드의 크기는 기본 64비트로 하여 전체 어드레스 범위에서 이동이 가능하도록 한 것입니다.

[그림 3-5]는 RIP 상대 어드레스를 사용하여 표현 가능한 어드레스 영역과 무조건 분기 명령어를 사용해서 접근할 수 있는 영역에 대해

나타낸 것입니다.


*. 88 Page [그림 3-5]

           [그림 3-5].png


*. 113 Page 아래에서 8번째 줄

그 위쪽에서 두 파일은 a.c와 b.c로부터 생성되는 것을 알 수 있습니다.


*. 141 Page 위에서 6번째 줄, 154 Page 아래서 5번째 줄, 2861 Page 위에서 7번째 줄, 2872 Page 맨 밑줄

xor byte [ HEADNUMBER ], 0x01 ; 헤드 번호를 0x01과 XOR 하여 토글(0->1, 1->0)


*. 142 Page, 아래서 3번째줄

x86 프로세서의 스택은 [그림 5-3]과 같이 데이터가 삽입될 때마다 스택의 상위(Top)를 나타내는 스택 포인터 레지스터(SP)가 낮은 어드레스(0x00에 가까운 어드레스)로 이동합니다.


*. 143 Page, 밑에서 10째줄

또한 스택은 넉넉한 것이 좋으므로 스택 포인터 레지스터(SP)와 베이스 포인터 레지스터(BP)를 0xFFFF로 설정하여, 스택 영역의 크기를 세그먼트의 최대 크기로 지정하겠습니다.


*.149 Page, 아래에서 13번째 줄

        ret 12                   ; 호출한 함수로 복귀한 후, 스택에 삽입된 파라미터 3개를 제거(3*4) "ret" "add esp, 12"와 같은 역할

        ^^^^^^

            ret 수행 후 스택 포인터(SP)를 12만큼 더함. 보호모드 코드이므로

            레지스터의 기본 크기 및 스택의 기본 크기가 32비트(4바이트)이기 때문에 4*3 = 12만큼 더함


*.151 Page, 위에서 15번째 줄

        ret 4                     ; 호출한 함수로 복위한 후, 스택에 삽입된 파라미터 1개를 제거(1*4) "ret" "add esp, 4"와 같은 역할

        ^^^^^^^

             ret 수행 후 스택 포인터(SP)를 4만큼 더함. 보호 모드 코드이므로

             레지스터의 기본 크기와 스택의 기본 크기가 32비트(4바이트)이기 때문에 4*1 = 4만큼 더함


*. 161 Page, 아래서 5번째줄 Code

; 512 - ( $ - $$ ) % 512 : 현재부터 어드레스 512까지


*. 213 Page, 가장 아래번째 줄

보호 모드 엔트리 포인트(EntryPoint.s) 코드에서 최초로 실행되는 C 코드입니다.


*. 251 Page, [그림 9-2] 페이지 디렉터리 엔트리 부분에서 PS1을 PS로 수정

[그림 9-2].PNG


*. 261 Page, 위에서 4번째 줄

kSetPageEntryData( &( pstPML4TEntry[ 0 ] ), 0x00, 0x101000, PAGE_FLAGS_DEFAULT, 0 );


*. 263 Page, [그림 9-5]의 XMSE를 SMXE로 수정


[그림 9-5].PNG


*. 266 Page, 소스 코드에서 위에서 10째줄

// 1 비트 P, RW, US, PWT, PCD, A, D, PS, G, 3 비트 Avail, 1 비트 PAT, 8 비트 Reserved,


*. 283 Page, [표 10-2] IA32_EFER 레지스터의 비트 구성에서 7번째 줄 LMA 항목

LMA 읽기 전용 -1로 설정되면 프로세서 모드가 IA-32e 모드(호환 모드 또는 64비트 모드)임을 나타내며, 0으로 설정되면 프로세서 모드가 기타 모드임을 나타냄


*.283 Page, 밑에서 10째줄

[표 10-2]에서 보는 것과 같이 IA-32e 모드 활성화 여부는 비트 8에 위치하는 LME 비트와 관계가 있고 이 비트를 1로 설정하면 IA-32e 모드를 활성화할 수 있습니다.


*.288 Page [예제 10-2] 위에서 1째줄

#ifndef __MODESWITCH_H__

#define __MODESWITCH_H__


*. 333 Page 아래쪽과 351 Page 가운데 부분, 482 Page 윗부분

BOOL kChangeKeyboardLED( BOOL bCapsLockOn, BOOL bNumLockOn, BOOL bScrollLockOn )

{

    int i, j;


    // 키보드에 LED 변경 커맨드 전송하고 커맨드가 처리될 때까지 대기

    for( i = 0 ; i < 0xFFFF ; i++ )

    {

        // 입력 버퍼(포트 0x60)가 비었으면 커맨드 전송 가능

        if( kIsInputBufferFull() == FALSE )

        {

            break;

        }

    }

...   생략 ...


*. 334 Page 위에서 3번째 줄

// 입력 버퍼(포트 0x60)로 LED 상태 편경 커맨드(0xED) 전송

kOutPortByte( 0x60, 0xED );

... 생략 ...


*. 341 Page 위에서 15번째 줄, 357 Page 아래에서 5번째 줄

BOOL kIsUseCombinedCode( BYTE bScanCode )


*. 341 Page, 위에서 18번째 줄, 357 Page, 아래에서 2번째 줄

BOOL bUseCombinedKey = FALSE;


*. 343 Page 아래쪽359 Page 가운데 부분

void UpdateCombinationKeyStatusAndLED( BYTE bScanCode )

{

    BOOL bDown;

    BYTE bDownScanCode;

    BOOL bLEDStatusChanged = FALSE;


    // 눌림 또는 떨어짐 상태처리, 최상위 비트(비트 7)가 1이면 키가 떨어졌음을 의미하고

    // 0이면 눌림을 의미함

    if( bScanCode & 0x80 )

    {

        bDown = FALSE;

        bDownScanCode = bScanCode & 0x7F;

    }

    else

    {

        bDown = TRUE;

        bDownScanCode = bScanCode;

    }


*. p.363 페이지 (02.Kernel64/Source/Keyboard.h)의 Down을 On으로 변경
// 키보드의 상태를 관리하는 자료구조
typedef struct kKeyboardManagerStruct
{
    // 조합 키 정보
    BOOL bShiftDown;
    BOOL bCapsLockOn;
    BOOL bNumLockOn;
    BOOL bScrollLockOn;
    
    // 확장 키를 처리하기 위한 정보
    BOOL bExtendedCodeIn;
    int iSkipCountForPause;
} KEYBOARDMANAGER;


*. 365 Page, 아래에서 12번째 줄

BOOL kIsUseCombinedCode( BYTE bScanCode );


*. 365 Page, 아래에서 17번째줄 변수 선언 부분 굵게 처리

void Main( void )

{

    char vcTemp[ 2 ] = {0, };

    BYTE bFlags;

    BYTE bTemp;

    int i = 0;


    ... 생략 ...



*. 383 Page의 [그림 12-7]에서 16~31 비트의 값(크기를 기준 주소로 수정)

그림 12-7.PNG


*. 386 Page, 위에서 21번째 줄 30번째 줄

#define GDT_FLAGS_LOWER_TSS ( GDT_FLAGS_LOWER_DPL0 | GDT_FLAGS_LOWER_P

#define GDT_FLAGS_UPPER_TSS ( GDT_FLAGS_UPPER_G )


*. 428 Page 아래에서 18번째 줄, 436 Page 아래에서 3번째 줄, 600 Page 아래에서 9번째 줄, 606 Page 위에서 7번째 줄

%macro KLOADCONTEXT 0      ; 파라미터를 전달받지 않는 KLOADCONTEXT 매크로 정의


*. 483 Page, 위에서 10번째 줄, 굵게 표시

// 키를 저장하는 큐와 버퍼 정의

static QUEUE gs_stKeyQueue;

static KEYDATA gs_vsKeyQueueBuffer[ KEY_MAXQUEUECOUNT ];


*. 492 Page의 위쪽

사실 14장은 앞 장과 비교해서 변한 것이 거의 없습니다.


*. 498 Page의 "GCC 헤더 파일에 정의된 가변 인자 매크로와 리스트"의 위쪽 문단

각 매크로와 데이터 타입이 어떻게 정의되어 있는지 코드를 직접 확인해 보겠습니다.


*. 609 Page, 첫 번째 줄  굵게 표시

{ "createtask", "Create Task", kCreateTestTask },


*. 620 Page의 [그림 18-3]

그림 18-3.png


*. 627 Page, "TCB 할당 및 해제 함수의 코드"에서 위로 2번째 줄

다음은 앞서 설명한 내용에 따라 구현한 TCB 할당 및 해제 함수의 코드입니다. ID를 처리하는 부분을 제외하고는 평이한 코드이므로

이해하는데 큰 어려움이 없을 것입니다. TCB 자료구조에 추가된 stLink 필드는 18.2.4절에서 살펴보겠습니다.


*. 660 Page의 위에서 4째줄

콘솔 화면의 주변을 돌면서 문자를 출력하는 태스크와 자신의 ID에 해당하는 위치에 바람개비를 출력하는 태스크를 작성했습니다.


*. 741 Page 위에서 7 번째 줄

태스크의 수를 제한하려면 임계 영역 진입 여부를 나타내는 플래그와 잠금 횟수를 나타내는 카운터, 그리고 임계 영역에 진입한 태스크의 ID만 있으면 처리할 수 있습니다.


*. 742 Page 아래에서 8번째 라인

만약 잠근 태스크가 해제를 요청하는 것이고 잠긴 횟수가 2 이상이면 중복으로 잠긴 것이므로 횟수만 1 감소시키고 실제로 해제하는 작업은 수행하지 않습니다.


*. 751 Page 그림 [20-4]

[그림 20-4].PNG


*. 769 Page 맨 윗 라인

콘솔 셸 파일에는 태스크를 생성하고 종료하는 태스트 때문에 killtask 커맨드의 기능이 수정되고 동기화 기능을 테스트하는 testmutex 커맨드가 추가되었습니다.


*. 791 Page의 밑에서 셋째줄

하지만 멀티코어 프로세서 환경일 경우 자식 스레드는 다른 코어에서 실행될 수 있으며, 이런 경우 태스크를 즉시 대기 리스트로 옮길 수 없습니다.


*. 815 Page의 밑에서 8째줄

[그림 21-4]의 위를 보면 콘솔 셸(태스크 ID: 0x100000000)과 유휴 태스크(태스크 ID: 0x200000001)의 태스크 플래그를 보면 최상위 바이트가 각기 0x60과 0x58로 시작하는 것을 볼 수 있습니다.


*. 825 Page [그림 22-2]

[그림 22-2].PNG


* 843 Page, 밑에서 10 째줄

또 FPU 예외 처리가 끝나면 다시 0으로 설정해서 같은 태스크가 FPU를 사용할 때 예외가 발생하지 않도록 해야 합니다.


* 876 Page, 밑에서 두번째 줄

1KB 블록 2개를 생성한 후 1KB 블록 하나를 할당해주면 남은 블록은 [그림 23-3]과 같이 1KB 블록 1개, 2KB 블록 1개, 4KB 블록 1개가 됩니다.


* 879 Page, 위에서 3번째 줄 그림 제목

[그림 23-6] 블록 크기에 맞지 않는 메모리를 할당받았을 때 할당된 메모리의 구조(4.3MB 할당)


* 933 Page 위에서 7 째줄

하지만, LBA 어드레스 모드일 때는 레지스터가 LBA 어드레스로 통합되어 섹터 번호 레지스터는 LBA 어드레스의 0비트~7비트, 실린더 LSB 레지스터는 8비트~15비트, 실린더 MSB 레지스터는 16비트~23비트, 드라이브/헤드 레지스터의 헤드 필드는 24비트~27비트를 저장합니다.


* 1049 Page, 위에서 6번째 줄 자료구조에서 아래의 굵게된 부분 추가

typedef struct kFileHandleStruct
{
    // 파일이 존재하는 디렉터리 엔트리의 오프셋
    int iDirectoryEntryOffset;
    // 파일 크기
    DWORD dwFileSize;
    // 파일의 시작 클러스터 인덱스
    DWORD dwStartClusterIndex;
    // 현재 I/O가 수행중인 클러스터의 인덱스
    DWORD dwCurrentClusterIndex;
    // 현재 클러스터의 바로 이전 클러스터의 인덱스
    DWORD dwPreviousClusterIndex;
    // 파일 포인터의 현재 위치
    DWORD dwCurrentOffset;
} FILEHANDLE;


* 1120 Page 위에서 6 째줄

// 파일 이름 삽입

kMemCpy( vcBuffer, pstentry->d_name, kStrLen( pstEntry->d_name ) );


* 1161 Page, [그림 27-5]의 가장 마지막 부분

[그림 27-5].PNG


*. 1174 Page, 위에서 11 번째 줄

iRealReadCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1174 Page, 밑에서 9 번째 줄

iRealWriteCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1186 Page, 밑에서 16 번째 줄

iRealReadCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );

*. 1186 Page, 밑에서 2 번째 줄

iRealWriteCount = MIN( gs_stRDDManager.dwTotalSectorCount -

dwLBA, iSectorCount );


*. 1239 Page, 위에서 10째줄과 13째줄

// LSB 제수 래치 레지스터(포트 0x3F8)에 제수의 하위 8비트를 전송

// MSB 제수 래치 레지스터(포트 0x3F9)에 제수의 상위 8비트를 전송


*. 1246 Page, 위에서 2째줄과 5째줄

// LSB 제수 래치 레지스터(포트 0x3F8)에 제수의 하위 8비트를 전송

// MSB 제수 래치 레지스터(포트 0x3F9)에 제수의 상위 8비트를 전송


*. 1251 Page, [예제 28-3]의 소스 부분
#include "FileSystem.h" <-- Normal 글씨체로 수정
#include "SerialPort.h" <-- Bold 글씨체로 수정

*. 1280 Page, 위에서 5번째줄, 맨 앞의 "-"를 "*"로 대체하고 위의 *와 같은 레벨로 들여쓰기 수정
* BIOS의 롬 영역 중에서 0x0F0000~ 0x0FFFFF 범위 내에 존재

* 1291 Page, [그림 29-13]에서 전달할 로컬 APIC INTIN을 전달할 로컬 APIC LINTIN으로 수정, 0x000x04로 수정
[그림 29-13].PNG  
* 1399 Page, [그림 31-1]에서 오른쪽 아래에 있는 "ㅁ: 비활성화 된 부분"의 사각형을 회색으로 변경
[그림 31-1].PNG

==== 2권의 오탈자 내용 ====

*. 1528 Page, 아래에서 11번째 줄

태스크 풀을 관리하는 함수를 수정하는 방법은 33.2.2절에서 살펴보므로, 이번 절에서는 수정된 태스크 풀 자료구조만 살펴보고 넘어가겠습니다.


*. 1539 Page, 위에서 7번째 줄, 1580 Page, 아래에서 12번째 줄

// 나머지 코어에서 현재 태스크와 같은 레벨을 검사


*. 1612 Page, 아래에서 2째줄

하지만, 7부가 지나면 곧 다시 돌아오니 너무 아쉬워 할 필요는 없습니다.


*. 1655 Page, 위에서 5번째 줄

브레슨햄 직선 알고리즘을 사용한 선 그리기 함수의 코드 - 최적화 후


*. 1672 Page, 35.2.1절에서 아래로 8번째줄

하지만, 문자 정보가 비트맵으로 들어 있으므로 확대하거나 축소했을 때 문자가 깨끗하게 표시되지 않고, 굵게하거나 기울일려면 해당 스타일의 비트맵을 모두 생성해야하는 단점이 있습니다.


*.1764 Page, 아래에서 10번째줄, kDrawMouse -> kDrawCursor로 수정

kDrawCursor( &stScreenArea, pstVideoMemory, iX, iY );


*. 1882 Page, 위에서 7번째 줄

이 절에서 작성할 윈도우 매니저는 더 이상 테스트 코드가 아닌 실제 코드로서, 키보드와 마우스 데이터를 이용해 윈도우로 이벤트를 전달하는 기능과 업데이트를 수행하는 기능을 구현합니다.


*. 1946 Page, 위에서 4번째 줄

//----------------------------------------------------------------------------------------------

// 제목 표시줄 그리기

//----------------------------------------------------------------------------------------------

// 제목 표시줄을 채움

        if( bSelectedTitle == TRUE )
        {
            stTitleBarColor = WINDOW_COLOR_TITLEBARACTIVEBACKGROUND;
        }
        else
        {
                stTitleBarColor = WINDOW_COLOR_TITLEBARINACTIVEBACKGROUND;

        }


kInternalDrawRect( &stArea, ... 생략 ...)


*. 1951 Page, 위에서 6번째 줄

39장의 내용을 MINT64 OS에 추가한 뒤 make를 입력하면 Disk.img 파일이 생성됩니다.


*. 1994 Page, 위에서 6번째 줄 제목

41.1.1 Z 순서의 가장 아래에서 위로 그리는 알고리즘의 문제점


*. 1998 Page, 위에서 3번째 줄

윈도우 1은 자신의 영역에 포함된 픽셀 오프셋 5~7 부분을 비디오 메모리로 전송한 뒤 해당 영역의 비트맵을 모두 0으로 표시합니다.


*. 2027 Page, 아래에서 3번째 줄

특히 마우스 데이터를 처리하는 부분과 화면 업데이트 요청을 처리하는 부분은 조금만 수정하면 화면 업데이트 횟수를 많이 줄일 수 있기 때문에 속도에 목마른 우리에겐 아주 중요한 포인트입니다.


*. 2150 Page, 위에서 첫번째 줄

43장에서는 프로세서의 정보와 메모리 정보를 표시하는 시스템 모니터 태스크를 구현해 봤습니다. 


*. 2150 Page, 위에서 6번째 줄

44장에서는 다시 고전으로 돌아가 역사의 뒤안길로 사라졌던 콘솔 셸을 GUI 버전으로 부활시킬 것입니다.


*. 2169 Page, 위에서 7번째 줄 도움말

while( kGetKeyFromGUIKeyQueue( &stData) == FALSE)

        |---------- 그래픽 모드용 키 큐에서 데이터를 꺼내는 함수


*. 2182 Page, "44.3.2 콘솔 파일 수정"에서 아래 첫번째 줄

콘솔 파일은 그래픽 모드 지원을 위해 입출력 함수의 코드를 일부 수정하고, 그래픽 모드용 화면 버퍼와 키 큐를 추가했습니다.


*. 2309 Page 전체를 아래 내용으로 교체2309 페이지의 내용.PNG


*. 2400 Page, 아래에서 4번째 줄

MINT64 OS에는 아직까지 MSR에 읽고 쓰는 함수가 없으므로 MSR에 관련된 어셈블리어 함수부터 만들겠습니다.


*. 2546 Page, "[표 50-2] e_entry 필드의 세부 구성과 의미"를 "[표 50-2] e_ident[16] 필드의 세부 구성과 의미"로 변경


*. 2546 Page, 아래에서 7번째 줄

가장 먼저 할 일은 e_ident 필드의 상위 4바이트가 매직 넘버이므로, 파일의 첫 4바이트가 매직 넘버와 일치하는지를 검사하여 올바른 ELF64 파일인지 확인하는 것입니다.


*. 2548 Page, 아래에서 5번째 줄

현재 섹션의 타입에 따라 필드의 의미가 달라지며 자세한 내용은 [표50-6]을 참조


*. 2616 Page, 위에서 첫번째 줄

[그림 51-2]는 이러한 처리 과정을 나타낸 그림입니다.


*. 2625 Page 위에서 14번째 줄,  2641 Page 아래에서 8번째줄, 2785 Page 밑에서 7번째줄, 

// 현재 라인에서 남은 문자 수와 한 라인에 출력할 수 있는 문자 수 를 비교하여 작은 것을 선택


*. 2692 Page, 위에서 12번째 줄

g_stGameInfo.iBlockX = -1;

g_stGameInfo.iBlockY = -1;


*. 2693 Page, 위에서 10번째 줄

게임판의 블록이 존재하는지 여부는 게임 자료구조의 vvbBoard 필드에 저장되어 있습니다.


*. 2694 Page, 위에서 5번째 줄

게임 자료구조에는 현재 게임판의 정보를 저장하는 vvbBoard 필드가 있으므로 움직이는 블록의 현재 좌표를 그대로 게임판에 저장하면 됩니다.


*. 2720 Page, 아래에서 13번째 줄

g_stGameInfo.iBlockX = -1;

g_stGameInfo.iBlockY = -1;


*. 2766 Page, 위에서 4번째 줄

텍스트 뷰어에 한글 출력 기능을 추가하려면 한글인지를 판단해 2바이트씩 출력하는 코드만 추가하면 되기 때문입니다.


*. 2846 Page, 위에서 1번째 줄

만든 첫 번째 한글 입력 모듈은 오토마타를 사용했습니다.


*. TODO...


제가 운영하는 OS 개발 사이트(http://www.mint64os.pe.kr)에 어떤 분께서 Object File을 coff 형식으로 생성할 수 있는 방법이 있느냐고 물어보시더라구요.

사실 제가 gcc의 각종 옵션에 익숙치 않아서....(매번 기본 옵션으로만 쓰다보니.. ^^;;;;) 구글 신님께 여쭤봤는데... 디버그 정보와 함께 오브젝트 파일을 coff 파일로 생성하는 옵션을 발견했습니다.

gcc -gcoff main.c

뭐, 당연한 거지만 gcc가 coff 파일을 지원해야 가능합니다. ^^;;;
보다 자세한 내용은 http://www.hanb.co.kr/network/view.html?bi_id=1382 내용을 참고하세요 ;)

ps) 혹시 디버그 정보 없이 coff 파일 형식으로 오브젝트 파일을 생성하는 옵션 아시는분 있으세요? ㅠㅠ
간만에 재미있는 질문을 받았습니다. 보안 관련 기술 쪽에 ASLR(Address Space Layout Randomization) 기법이 있는데, 이를 어떻게 MNIT64 OS에 적용할 수 있을까를 묻는 내용이었습니다.

저도 보안 쪽은 좀 생소하여 ASLR을 잠시 찾아봤는데, 응용프로그램을 로딩할 때 항상 정해진 어드레스가 아닌 매번 다른 어드레스로 로딩하여 크래커로부터 보호하는 기법이더군요. 사실 어드레스를 매번 변경한다고 해도 찾아서 뚫을려고 마음 먹으면 어쩔 수 없기 때문에 완벽한 방법은 아닙니다만, 나름대로 괜찮은 아이디어라는 생각이 들었습니다.

그래서, 어떻게 하면 MINT64 OS에도 이를 적용할 수 있을까 생각을 해봤는데 의외로 답은 간단했습니다. ^^;;; MINT64 OS는 응용프로그램을 메모리에 로딩할 때 동적 메모리 관리 모듈에서 먼저 메모리를 할당 받은 뒤에 그 메모리에 올려서 응용프로그램을 동작시킵니다. 따라서, 많은 응용프로그램이 실행되고 종료되는 상황이라면, 저절로 어드레스가 랜덤하게 할당되는 것이지요.

물론, 응용프로그램 하나만 계속 생성되었다가 종료되는 상황이라면 여전히 문제가 있습니다. 이 문제도 사실은 간단히 해결할 수 있습니다. 동적 메모리 관리 모듈에서 메모리를 할당받을 때, 메모리 블록을 항상 인덱스 0번부터 검색할 것이 아니라 랜덤한 인덱스부터 검색하도록 하면 됩니다. ^^;;; 나중에 여유가되면 한번 기능을 추가해봐야겠군요. ^^)/~

그럼 즐거운 밤 되세요 ;)
"64비트 멀티코어 OS 원리와 구조" 책의 첫 서평이 올라왔습니다. ㅠㅠ 
(다행히도 서평이 좋네요. ㅠㅠ 감사드립니다. ㅠㅠ)

<64비트 멀티코어 OS 원리와 구조 - 출처 yes24.com>

서평을 써주신  somesing님, charsyam님, niceness님, ageman1님 감사드립니다.  ㅠㅠ

앞으로 더욱 열심히하는 kkamagui가 되겠습니다. (__)

 
ps)  다들 즐거운 추석 연휴 보내세요 ;) 
제 책 "64비트 멀티코어 OS 원리와 구조"가 나온지도 벌써 3달이 다되어 가는군요. ^^ 부족한 책이지만 많은 분들이 구매해주신 덕분에 순조롭게 진행되고 있는 것 같습니다(물론 손익 분기점까지는 아직 멀었지만 말입니다 ㅠㅠ).

<64비트 멀티코어 OS 원리와 구조>



책의 내용 중에서 가장 많이 질문 받는 내용 중에 두 가지가 초반에 환경 구축할 때 크로스 컴파일러를 만드는 과정과 QEMU 0.10.4 버전을 어디서 구하는가 하는 것입니다. ^^;;; 그래서 얼마전에 Cygwin 최신 버전으로 64비트 크로스 컴파일러를 만드는 글(http://kkamagui.tistory.com/762)을 올렸습니다.

이번에는 QEMU 0.10.4 버전을 어디서 다운로드할 수 있는가 하는 것인데... 가장 간단한 방법은 여기에 올려드린 첨부 파일을 다운로드 하는 것입니다. ^^;;; QEMU 0.10.4 버전은 제가 MINT64 OS를 만들기 시작할 때 쓰던 버전이라... 지금은 구하기가 힘들기 때문이지요.


QEMU에 최신 OS를 설치하려면 최신 버전을 다운로드하시는게 아무래도 이득이겠지만, MINT64 OS를 실습하는데는 0.10.4 버전을 사용하시는 것이 정신의 평화와 안정을 유지하는데 도움이 되실겁니다. ^^;;;;

그럼 즐거운 OS 프로그래밍하세요 ;)

제 책 "64비트 멀티코어 OS 원리와 구조"가 나온지도 벌써 2달 이상 지났습니다. ^^;;; 책이 출간됨과 동시에 가장 많이 질문을 받는 것이 OS 제작을 위한 환경 구축 방법인데요... 얼마전부터 환경 구축에 어려움을 겪는 분들이 많아지셔서 Cygwin 최신 버전을 다운 받아서 빌드를 해봤습니다. ^^;;; 실제로 빌드를 진행하다보니 한가지 변경점이 보이더군요. ㅠㅠ 그래서 그 내용을 여기다가 정리해놓습니다. ㅠㅠ


<출처 - yes24.com>


Cross Compiler를 만들려면 먼저 Cygwin 사이트(http://www.cygwin.com/install.html)로 이동해서 Cygwin Installer를 다운로드 받습니다. Setup.exe 파일을 다운하면 됩니다. ^^;;;

다운로드 후 파일을 실행하면 어떻게 설치할 것이고 패키지 소스는 어디에서 다운 받을 것인지 선택하는 부분이 나오는데,

책에 나와있는 카이스트 사이트(ftp://ftp.kaist.ac.kr)가 더이상 유효하지 않으니 다른 사이트를 선택해야합니다.

우리나라 근처에 있는게 아무래도... 속도도 빠르니 가까운 일본 주소인 ftp://ftp.jaist.ac.jp를 선택하면 됩니다. ^^;;;

패키지 소스를 다운 받을 주소를 선택하고 난 뒤에는 "Select Package" 화면이 나올 때까지 적당히 Next를 선택해주면 됩니다. ^^;;;

"Select Package" 화면이 나오면 아래의 항목들을 설치해줍니다. 책을 쓸 때는 C++ 관련 항목이 없어도 정상적으로 빌드가 되었지만, 지금은 C++ 컴파일러를 설치하지 않으니 configure 중에 오류가 발생하더군요. ㅠㅠ 가장 아래쪽에 있는 libmpc-devel이 변경된 부분입니다.

+Devel  
    + binutils - 2.21.53-2 버전, 소스 및 바이너리 모두 설치  
    + bison - 2.4-2-1 버전, 바이너리만 설치  
    + flex - 2.5.35-1 버전, 바이너리만 설치  
    + gcc4-core - 4.3.4-3 버전, 소스 및 바이너리 모두 설치  
    + gcc4-g++ - 4.3.4-4 버전, 바이너리만 설치  
    + libiconv - 1.14-1 버전, 바이너리만 설치  
    + libtool - 2.2.7a-15 버전, 바이너리만 설치  
    + make - 3.81-2 버전, 바이너리만 설치  
    + patchutils - 0.3.1-1 버전, 바이너리만 설치  
+Libs  
    + libgmp-devel - 4.3.2-1 버전, 바이너리만 설치  
    + libmpfr-devel -3.0.1-1 버전, 바이너리만 설치
    + libmpc-devel - 0.8-1 버전, 바이너리만 설치

위의 항목이 설치되고 나면 binutils부터 차례대로 빌드를 시작하면 됩니다.


binutils를 빌드하려면 /usr/src 디렉터리 아래에 있는 binutils 디렉터리로 이동해서 다음과 같은 순서로 커맨드를 입력하면 빌드와 설치가 끝납니다.

// 디렉터리 이동 후 아래 작업 수행

$> cd /usr/src/binutils-2.21.53-2  <== 디렉터리 이름은 binutils 버전에 따라 다를 수 있음
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> ./configure --target=$TARGET --prefix=$PREFIX --enable-64-bit-bfd --disable-shared --disable-nls  
$> make configure-host  
$> make LDFLAGS="-all-static"  
$> make install  

// 아래는 테스트를 위한 부분 커맨드를 실행했을 때 x86\_64 관련 항목이 보이면 제대로 된 것입니다. ^^;;;;  
$> /usr/cross/bin/x86\_64-pc-linux-ld --help | grep "supported "  
/usr/cross/bin/x86\_64-pc-linux-ld: supported targets: elf64-x86-64 elf32-i386 a.  
out-i386-linux efi-app-ia32 efi-bsdrv-ia32 efi-rtdrv-ia32 efi-app-x86\_64 efi-bsd  
rv-x86\_64 efi-rtdrv-x86\_64 elf64-little elf64-big elf32-little elf32-big srec sy  
mbolsrec tekhex binary ihex  
/usr/cross/bin/x86\_64-pc-linux-ld: supported emulations: elf\_x86\_64 elf\_i386 i38  
6linux  

binutils 빌드 및 설치가 끝났다면 gcc를 cross compile할 차례입니다. gcc는 아래와 같은 순서로 입력하면 빌드와 설치가 완료됩니다. ^^;;;

// 압축 해제, 파일명은 cygwin에서 다운받은 GCC 버전에 따라서 다를 수 있으니 실제 디렉터리를 확인하여 입력해야 합니다. ^^;;; 아래 패치 파일도 모두 마찬가지 입니다.  
$> cd /usr/src

$> tar -xvf gcc-4.3.4.tar.bz2  
$> patch -p1 < gcc4-4.3.4-3.src.patch  
$> patch -p1 < gcc4-4.3.4-3.cygwin.patch  
$> export TARGET=x86\_64-pc-linux  
$> export PREFIX=/usr/cross  
$> export PATH=$PREFIX/bin:$PATH

// 압축 해제가 끝났으니 소스가 있는 디렉터리 이동 후 나머지 작업 수행  
$>cd /usr/src/gcc-4.3.4 <== 디렉터리 이름은 GCC 버전에 따라 다를 수 있음

$> ./configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c --without-headers --disable-shared --enable-multilib  
$> make configure-host  
$> cp /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.dll.a /lib/gcc/i686-pc-cygwin/4.3.4/libgcc\_s.a  
$> cp /lib/libmpfr.dll.a /lib/libmpfr.a  
$> cp /lib/libgmp.dll.a /lib/libgmp.a  
$> make all-gcc  
$> make install-gcc  

// 테스트용입니다. 아래와 같이 입력했을 때 m64가 보이면 정상적으로 설치된 것입니다.  
$> /usr/cross/bin/x86\_64-pc-linux-gcc -dumpspecs | grep -A1 multilib\_options  
    *multilib\_options:  
    m64/m32  

자, 이제 64비트 바이너리를 생성할 수 있는 gcc가 생성되었으니,
즐거운 OS 프로그래밍하세요 ;)

Intel과 AMD에서는 IA-32e Mode, 즉 Long Mode로 전환할 때 Protected Mode(보호 모드)를 거치도록 되어있습니다. 아래 그림은 Intel Manual에서 가져온 Operating Modes Transition Diagram입니다. ^^
 


위의 그림에서 보면 Real Mode(이하 리얼 모드)에서 IA-32e Mode or Long Mode(이하 IA-32e Mode)로 전환할 때 바로 가는 화살표가 없고 Protected Mode(이하 보호 모드)를 거쳐서 IA-32e 모드로 가게 되어 있습니다. 

그.런.데 익명의 제보로 바로 가는 것이 가능하다는 것을 알게 되었습니다. 그래서 구글을 검색해보니 실제로 2005년도에 바로 갈수있는 방법을 찾아내신 분이 있더군요. ^^)-b

OSDev에서 발견했는데, http://forum.osdev.org/viewtopic.php?t=11093에서 그 내용을 보실 수 있습니다. 방법은 비교적 간단합니다. 보호 모드에서 하는 작업을 그대로 리얼 모드에서 한 뒤에 IA-32e 모드로 jump를 하는 것입니다. 아래는 OSDev 링크의 방법을 그대로 옮겨 놓은 것입니다. ^^;;;;

1) Build paging structures (PML4, PDPT, PD and PTs)

2) Enable PAE in CR4

3) Set CR3 so it points to the PML4

4) Enable long mode in the EFER MSR

5) Enable paging and protected mode at the same time (activate long mode)

6) Load a GDT

7) Do a "far jump" to some 64 bit code


때마침 여유가 좀 생겨서 실제로 가능한 예제 코드를 한번 만들어 봤습니다. 기본 뼈대로는 MINT64 OS의 부트 로더 코드와 보호 모드 코드를 사용했고, IA-32e 모드로 전환 가능한지 확인하는 것이 목적이었기 때문에 최소한의 코드만 작성했습니다. 

아래는 실제로 동작하는 화면을 캡쳐한 것입니다. QEMU를 사용해서 확인했습니다. ^^


<실제로 QEMU에서 구동한 화면>


리얼 모드에서 보호 모드를 거치지 않고 IA-32e 모드로 전환하는 방법은 Manual에 의해 보장된 방법이 아니므로, 이런 것도 가능하다는 팁 정도로 보시면 될 것 같네요. ^^;;;

그럼 아래에 실제 코드 나갑니다. ^^
(첨부 파일에 소스 코드와 컴파일된 바이너리도 같이 넣어두었으니 참고하시기 바랍니다)


그럼 좋은 하루 되세요 ;)
 

첨부 파일 :



Intel Architecture Manual을 보면 아래와 같은 Operating Mode Diagram이 있습니다. 각 Mode에 따라서 어떤 Mode로 전환할 수 있으며 이때 필요한 Register 설정은 무엇인지를 나타내는 그림이지요. ;)
 

이 그림을 자세히보면 리얼 모드에서는  IA-32e 모드로 전환할 수 있는 방법이 없습니다. 전환 하려면 보호 모드를 거쳐서 전환해야 하지요. 실제로 Intel Architecture Manual Volume 3A의 9.8.5를 봐도 "The operating system must be in protected mode with paging enabled before attempting to initialize IA-32e mode"로 보호 모드를 거쳐야 한다고 나와있습니다.

그런데~!!! 지나다가님의 제보로 리얼 모드에서 바로 IA-32e 모드로 전환할 수 있는 방법을 알게되었습니다. 물론 제조사 Manual에 나와있지 않은 내용이라, 팁 정도로 봐야겠지만 상당히 흥미로운 내용이라 한번 올려봅니다.

원본의 내용은 http://forum.osdev.org/viewtopic.php?f=1&t=11093&start=0 에서 보실 수 있으며, IA-32e 모드로 변경하려면 실제로 아래와 같이 7가지의 단계를 거쳐야합니다.

    1) Build paging structures (PML4, PDPT, PD and PTs)
    2) Enable PAE in CR4
    3) Set CR3 so it points to the PML4
    4) Enable long mode in the EFER MSR
    5) Enable paging and protected mode at the same time (activate long mode)
    6) Load a GDT
    7) Do a "far jump" to some 64 bit code 
 

위의 단계 중에서 6번은 리얼 모드에서 보호 모드로 전환하는 단계에서 하고, 나머지 6 가지는 보호 모드에서 수행하여 IA-32e 모드의 64비트 서브 모드로 전환합니다. But~!!! 리얼 모드에서 위의 7단계를 모두 수행해서 한번에 IA-32e 모드로 전환하는게 바로 Magic의 정체입니다. @0@)-b

과연 동작할까 싶지만, 실제로 동작하더군요. ㅎㄷㄷ 실제로 동작하는 코드는 http://bcos.hopto.org/temp/init.html에서 보실 수 있으며, 지나가다님이 작성하신 http://jsandroidapp.cafe24.com/xe/1936 에서도 보실 수 있습니다. ^^

정말 깜짝 놀랄 일이군요. ㅎㅎ 어떻게 이런 방법을 찾았는지... ㅎㅎ 세상에는 별별 사람들이 다 있는 것 같습니다. >ㅁ<)-b

안녕하세요, 이벤트가 끝나자마다 다시 이벤트 소식으로 찾아뵙는군요. ^^
 
<진행 중인 이벤트~!! ㅠㅠ 언능 신청한다면 8월 1일까지는 어떻게든 되지 않을까요? ㅠㅠ>


지금 Yes24에서 리뷰어 신청을 하시면 1권을 무료로 증정해주는 리뷰어 이벤트를 진행하고 있습니다. ^^)-b

사실 신청자가 그리 많지 않다는 소식(?)을 들어서,
그동안 책값이 부담되셨던 분들께 도움을 드리고자 이렇게 급하게 올리게되었습니다 .ㅠㅠ
(사실 바로 올렸어야 하는데 주말에 일이 생겨 정신없이 보내다보니... 이제야 올리게됬네요. ㅠㅠ)

월요일(8월 1일)이 당첨자 발표이긴 한데, 
발표전까지만 신청하시면 어떻게든 되지 않을까 하는 희망을 갖고 있습니다.

관심있으신 분들은 지금 바로 신청하시면 될 것 같습니다.
당첨되고 나면 2권만 사서 보시면 되니 괜찮은 이벤트가 아닌가 싶네요. ^^)-b


그럼 언능 신청하시고 책 받으세요 >ㅁ<)-b
회사일 하랴, 질문에 답변 달랴, 오탈자 제보 수정하랴 요즘 정신없이 하루하루를 보내고 있습니다. ^^ 그래도 MINT64 OS의 커뮤니티(http://www.mint64os.pe.kr)에 많은 분들이 관심을 가져 주셔서 몸은 좀 힘들지만 즐거운 나날을 보내고 있습니다. ^^
(감사합니다~ 다 여러분들 덕이에요 ;) )

<MINT64 OS 랍니다. ^^>

질문에 답변을 하다가 문득 든 생각인데, 압축 파일 형태로 제공되는 MINT64 OS가... 마치 생명력을 잃어버린 것 같더군요. 뭐랄까요... 질문과 답변을 통해 커뮤니티는 앞으로 나아가는데 MINT64 OS의 소스는 계속 그 자리에 멈춘듯한 느낌이랄까...

그래서 고민 끝에 MINT64 OS의 최신 코드를 웹상에 공개하기로 했습니다. 지금 생각하는 곳은 소스포지(http://sourceforge.net/)나 구글 코드(http://code.google.com/intl/ko-KR/)인데, 어느 곳이 딱 맞을지는 잘 모르겠네요. ^^;;;

둘 중에 어느 한 곳을 골라서 이번 주에 프로젝트를 개설할까 하는데... 혹시 괜찮은 곳 있으시면 추천 부탁드립니다. ^^
그럼 즐거운 하루 되세요 ;) 

<64비트 멀티코어 OS 원리와 구조>


MINT64 OS의 챕터별 예제 소스는 한빛 미디어 웹사이트(www.hanb.co.kr/exam/1836)로 이동하면 받을 수 있습니다.
해당 링크로 이동하면 source_code.zip 파일cygwin_devenv.zip 파일을 볼 수 있습니다.

source_code.zip 파일: 
   각 장별 소스 코드가 담겨 있으며, MINT64 OS를 실행할 수 있는 환경과 각종 데이터 시트를 모아 놓았습니다.
   (책에서 언급한 부록 CD의 내용은 대부분 여기에 들어있습니다. ^^)

cygwin_devenv.zip 파일:
   제가 개발하던 당시 Cygwin 디렉터리를 압축한 것입니다. 
   일반적인 경우라면 최신 버전의 Cygwin을 내려받아서 환경을 구성합니다. 
   하지만 크로스 컴파일러를 만드는데 계속 실패하거나 알 수 없는 오류가 발생한다면 
   cygwin_devenv.zip 파일의 압축을 풀어 C:\cygwin 디렉터리에 덮어써서 문제를 해결할 수 있습니다. ^^


그럼 즐거운 OS 프로그래밍하시고, 출간 기념 이벤트(http://kkamagui.tistory.com/748)도 많이 참여해주세요 ^^
오늘 드디어 그렇게 기다리던 "64비트 멀티코어 OS 원리와 구조"가 제 손에 들어왔습니다. ㅠㅠ 지금까지 A3 용지에 출력된 것만 보다가, 이렇게 책으로 제본된 것을 보니 왠지 울컥(?) 하더군요. ㅠㅠ 그래서 뭔가 저질러야겠다는 생각이 들어서 출간 기념 이벤트를 하기로 했습니다. ^^)/~ 

<64비트 멀티코어 OS 원리와 구조의 실물 사진>


이벤트 응모 방법은 아주 간단합니다. 오늘부터 배송이 시작되었다고 하니 빠르면 내일부터 책을 받으실 겁니다. 그러면...

책을 받았다는 인증 사진을 찍어 저에게 메일(mint64os@gmail.com)로 보내시거나, 블로그에 올리시고 제가 볼 수 있게 이 글(http://jsandroidapp.cafe24.com/xe/216)의 댓글로 링크를 남겨주시면 됩니다. 

그러면 제가 정확히 7월 31일에 랜덤(?)으로 추첨하여 공정하게 1분을 뽑아 소정의 선물을 드릴까합니다. ^^)/~
(7월 31일 자정에 추첨하겠습니다. ^^;;;)

선물은 책을 보시는데 꼭 필요한 것으로 준비할 예정이니 많은 응모 부탁드립니다. ^^

ps) 실제로 보니 책이 정말 잘 나왔네요. 분량이 많아서 내심 걱정했는데, 내용도 알맞게 잘 편집된 것 같습니다. 아주 마음에 쏙~!! 드는군요. :) 

 

 

책 표지

2008년부터 준비했던 "64비트 멀티코어 OS 원리와 구조"가 드디어 주요 서점에서 판매가 시작되었습니다. ^^)/~ 지난번 글(http://kkamagui.tistory.com/745)에서 다음 주 쯤부터 예약 판매가 될 거라고 말씀드렸는데, 하루만에 예약 판매가 시작되서 깜짝 놀랐네요. ^^;;;; 

제 블로그에 가끔씩 오시는 분들은 알고 계시겠지만, "64비트 멀티코어 OS 원리와 구조"는 제가 2008년에 취미로 시작한 프로젝트에서 시작되었습니다(진행 기록은 http://kkamagui.tistory.com/category/OS%20Kernel/MINT64%20OS를 보시면 확인할 수 있습니다). 물론 가끔 이게 처음으로 만든 OS냐고 물어오시는 분들이 계신데, 2002년도부터 치자면 이 OS가 5번 째입니다. ^^;;;;

최초로 만들었던 32비트 OS가 KKAMA OS(http://kkamagui.tistory.com/251) 이구요, 그 다음에 이걸 이용해서 만든 것이 OS 프레임워크(http://kkamagui.tistory.com/category/OS%20Kernel/32bit%20OS%20Framework) 입니다. 그 후 휴대용 기기쪽으로 넘어가서 OS 같은 펌웨어를 간단히 만들어봤다가 다시 PC로 넘어와서 MINT64 OS의 프로토타입(http://kkamagui.tistory.com/551)도 만들었지요. 그리고 마지막이 바로 MINT64 OS 입니다. 그러고보니 참 많이도 만들었군요. 쿨럭..;;;

MINT64 OS의 동작화면

제가 그동안 OS를 만들면서 느꼈던 점이나 힘든 점을 생각하며 작업 과정을 담은 책이니, OS 제작에 관심이 많거나 멀티코어 OS가 어떻게 동작하는지 궁금한 분들에게 많은 도움이 될 거라 생각합니다. ^^;;;

책은 교보문고를 비롯해서 여러 온라인 서점에서 구매하실 수 있으며, 링크는 아래와 같습니다.

1권 도서 링크 : https://www.yes24.com/Product/goods/65061299(ebook), https://www.yes24.com//24/goods/5270659(종이책)
2권 도서 링크 : https://www.yes24.com/Product/goods/65061297(ebook), https://www.yes24.com//24/goods/5270667(종이책)
1/2권 세트 도서 링크 : https://www.yes24.com//24/goods/5271779(종이책)


종이책은 현재 절판 상태이니 ebook을 이용해주시면 감사하겠습니다. ^^;;;


책을 출판하기까지 도움을 주신 많은 분들께 감사드리며, 앞으로 더 열심히 하겠습니다. ^^
그럼 좋은 하루 되세요 ^^

ps) 아래는 MINT64 OS의 구동화면을 동영상으로 만든 것입니다. 화면을 저장하다보니 끊김이 보이는데, 실제로 실행하면 좀더 부드럽습니다. ^^;;; 

 

<책 표지>


제가 2008년부터 만들기 시작한 MINT64 OS에 대한 책, "64비트 멀티코어 OS 원리와 구조"가 나왔습니다. ㅠㅠ 제 블로그를 방문하시는 분은 이미 알고 계시겠지만, 2008년 말에 취미로 64비트 모드에 발을 담갔다가 그대로 64비트에 멀티코어를 지원하는 OS까지 내리 달렸습니다. 그리고 내친김에 GUI에 응용프로그램까지 제대로 한번 해보자는 생각에 2년 넘게 작업을 했더랬지요. 제가 그간 진행했던 과정은 http://kkamagui.tistory.com/category/OS%20Kernel/MINT64%20OS 에서 보실 수 있습니다. ^^;;;

2008년부터 작업 과정을 올리면서 소스 공개를 바라시는 분들이 많았는데, 조금만 더 정리하고 올린다고 했던게 벌써 3년이나 지났네요. 쿨럭..;; 죄송합니다. ㅠㅠ 그래도 소스코드와 덤으로 제가 했던 작업 내역까지 상세하게 풀어쓴 책까지 공개했으니 너그러이 용서해주세요. ^^;;; 

<MINT64 OS의 실행 화면>


책은 2권으로 이루어져 있고 분량은 대충 2800 페이지 정도 됩니다. 페이지만 봐도 얼마나 내용이 자세한지는 대략 추측할 수 있을 꺼라 생각합니다. OS 만들기가 그렇지만 어셈블리어나 C 코드 한 줄만 틀려도 재부팅되거나 멈추기 때문에, 작업한 내용을 최대한 빼먹지 않도록 노력했습니다. 이 책을 보면 제가 부트로더부터 GUI를 거쳐 응용프로그램을 만들기까지 모두 들어있기 때문에, 장담컨데 이 책만 있으면 누구나 "취미"로 64비트와 멀티코어를 지원하는 OS를 만들 수 있습니다~!! 


글을 올리고 하루만에 판매가 시작되었네요. ^^;;;; 주요 서점에서 구하실 수 있구요, 링크는 아래와 같습니다.


1권 도서 링크 : http://www.yes24.com/Product/goods/65061299(ebook)http://www.yes24.com//24/goods/5270659(종이책) 

2권 도서 링크 : http://www.yes24.com/Product/goods/65061297(ebook)http://www.yes24.com//24/goods/5270667(종이책)

1/2권 세트 도서 링크 : http://www.yes24.com//24/goods/5271779(종이책)


종이책은 현재 절판 상태이니 ebook을 이용해주시면 감사하겠습니다. ^^;;;

그럼 다들 즐거운 하루 되세요 ^^


ps 1) 책이 나오기까지 도움을 주시고 응원해주신 많은 분들께 진심으로 감사드립니다. (__)

      이 책이 나올 수 있었던 것은 다 여러분들 덕입니다.
ps 2) 아래는 MINT64 OS의 구동 화면입니다. 화면 캡쳐를 하다보니 끊기는 부분이 보이는데, 실제로 실행하면 좀더 부드럽습니다. ^^;;;




 

<깔끔하게(?) 정리된 MINT64 OS의 실행 화면>


한동안 정신 없이 바쁘다가 다시 코드를 볼 일이 생겨서 얼마 전부터 코드를 보고 있습니다. :) 코드를 새로 추가하는 것은 아니고 기존 코드를 정리한 것뿐이지만… 어쨌든 내부가 변하긴 했으니 기념 삼아 올려봅니다. ^^;;; 가만히 생각해보니, 그동안 MINT64 OS에 대해서 많이 올리긴 했지만 제대로 된 설명을 한번도 한적이 없는 것 같네요. 코드도 한번 정리한 김에 MINT64 OS에서 실행 가능한 애플리케이션과 커맨드도 같이 정리해둡니다.

MINT64 OS가 기본으로 내장하고 있는 애플리케이션은 5개로 왼쪽 위에 있는 “Application” 버튼으로 실행할 수 있습니다. 각 애플리케이션의 역할은 아래와 같습니다.


  • Base GUI Task : 모든 GUI 애플리케이션의 기본 뼈대 역할을 하는 태스크로 윈도우를 생성하고 윈도우에 관련된 이벤트를 처리하는 단순한 애플리케이션입니다.
  • Hello World GUI Task : 가장 기본적인 GUI 애플리케이션으로 윈도우 시스템이 전달하는 메시지를 화면에 출력하고 자신과 같은 Hello World GUI Task로 유저 이벤트를 전송하는 기능도 같이 가지고 있습니다.
  • System Monitor Task : OS의 상태를 표시하는 애플리케이션이며 프로세서의 상태와 메모리의 상태를 표시합니다.
  • Console Shell for GUI : GUI 모드에서 동작하는 콘솔 셸로 커맨드 라인 해석기(Command Line Interpreter) 입니다. 여기에 대해서는 잠시 후에 설명하겠습니다. ;)
  • Image Viewer Task : JPG 파일을 읽어서 화면에 출력해주는 애플리케이션입니다. 하드 디스크에 image1.jpg와 image2.jpg, 그리고 image3.jpg가 있으니 파일명에 이를 입력하면 이미지를 볼 수 있습니다.


  <MINT64 OS에 내장된 GUI 애플리케이션들>


GUI 애플리케이션도 좋지만 키보드로 커맨드를 입력하는 재미(?)도 무시할 수 없어서, 초반에 MINT64 OS를 개발할 때 쓰던 콘솔 커맨드를 그대로 GUI 애플리케이션으로 만들었습니다. 콘솔 셸에서 테스트할 수 있는 커맨드에는 여러 가지가 있지만, 그 중에서 특히 유용한 몇 가지를 추린다면 아래와 같습니다.


  • help : 콘솔 셸이 지원하는 커맨드 목록을 출력합니다.
  • dir : 하드 디스크에 들어있는 파일을 출력합니다.
  • hddinfo : 하드 디스크의 정보를 출력합니다.
  • filesysteminfo : 파일 시스템의 정보를 출력합니다.
  • exec <application nane> <argument> : 파일 시스템에 저장된 애플리케이션 파일을 실행합니다. 애플리케이션은 ELF 파일 형식을 사용하며, 하드 디스크에 helloworld.elf부터 onelinememo.elf까지 총 6개가 저장되어 있습니다. <Argument> 부분은 옵션으로 애플리케이션마다 필요로 하는 정보가 다르고, 이는 잠시 후에 설명하겠습니다. ;)


콘솔 셸 커맨드 중에서 exec는 아주 특별한 커맨드로 파일 시스템에 저장된 GUI 애플리케이션을 실행하는 역할을 합니다. 파일 시스템에 저장된 애플리케이션은 6가지가 있고 각 애플리케이션마다 필요한 Argument와 역할은 아래와 같습니다.


  • exec helloworld.elf : MINT64 OS에 내장된 helloworld 애플리케이션과 같습니다.
  • exec textviewer.elf asciiart.txt : 파일 시스템에 저장된 파일을 읽어서 화면에 출력해주는 애플리케이션으로, Argument로 넘어온 파일을 읽어서 표시합니다.
  • exec bubble.elf : 풍선을 쏘는 버블 슈터라는 게임입니다. ^^;;;
  • exec hexa.elf : 같은 색깔의 블럭을 없애는 헥사 게임입니다. ^^;;;
  • exec hangulviewer.elf main.c : 파일 시스템에 저장된 파일을 읽어서 화면에 출력해주는 애플리케이션으로, textviewer.elf와 다른 점은 한글을 지원한다는 것입니다.
  • exec onelinememo.elf : 한 줄 메모장으로 간단한 메모를 남길 수 있는 애플리케이션입니다.


  <exec 커맨드로 실행한 애플리케이션들>

 

기능은 얼마 없는데 쭉 나열하고 보니 많은 것처럼 보이는 군요(착시 효과가 엄청난 듯…). ㅠㅠ 실제로 어떤 모습인가 확인하고 싶은 분들은 아래에 있는 압축 파일을 다운로드한 뒤에 MINT64OS.bat 파일을 실행하면 됩니다. 가상 머신에서 동작하는지라 사용하는 PC의 성능에 따라 약간 편차가 있을 수 있는데… 듀얼 코어 정도면 실행하는데 큰 문제가 없을 겁니다. ^^;;;



아우~ 주말 내내 정신 없이 보냈더니 이제 좀 쉬어야겠네요. 그럼 다들 좋은 밤 되시길~ ;)

그동안 여러 크고 작은 문제로 신경을 거의 못쓰다가 이제서야 정신을 좀 차렸습니다. 물론 아직 처리해야 할 문제는 많지만 사고가 났을 당시에 비하면 아무것도 아니지요. ㅎㅎ 여러분들이 많이 걱정해주신 덕분에 여자친구가 빨리 회복하고 있습니다. ^^)-b 많이 감사 드립니다. ㅎㅎ

에궁… 집 –> 병원 –> 회사 –> 병원 –> 집만 반복하다 보니 본의 아니게 블로그를 오래 버려두었네요. 여러분의 댓글에 일일이 댓글을 달아드리지 못한 점 죄송하게 생각하고, 시간 날 때마다 차근차근 답글을 드리겠습니다. ㅠㅠ 회사 일도 요즘 한참 마무리 중이라서 더 신경을 쓰지 못한 것 같네요. ㅎㅎ

그래도 마냥 시간만 보낸 것은 아닙니다. ;) 주말 동안은 병원에서 틈틈이 MINT64 OS를 손봐서 이제 나름대로 그럴듯한(?) 모습이 됐습니다. 아래는 바뀐 MINT64 OS의 인증샷입니다. ;)

image <한글 입출력 기능과 각종 게임이 추가된 MINT64 OS의 구동 화면>

사실 별것 아니지만 난리가 난 통에 여기까지 오는데도 상당히 오래 걸렸네요. ㅠㅠ 중간에 몇 번이나 고비를 넘었는지… 숨겨져 있던 버그가 나오는 바람에 크로스 컴파일러를 새로 만들었는데 새로 만든 크로스 컴파일러 때문에 다시 다른 버그가 나오는 문제가… 쿨럭..;;; 정말 환장하는 줄 알았습니다. ㅠㅠ 그래도 여기까지 오고 나니 나름대로 뿌듯하네요. ;)

이제 사는 소식도 좀 전할 겸 해서 슬슬 다시 블로깅을 할 예정이니 앞으로 자주 MINT64 OS에 대한 소식을 전하겠습니다. ;) 그리고 그 외에 여러 가지에 대해서도 말이죠. ㅎㅎ

그럼 좋은 밤 되시고, 또 뵙겠습니다. ;)

 

<이미지 뷰어와 콘솔 셸이 추가된 MINT64 OS>

 오늘 너무 황당한 일이 있어서 오랜 적막(?)을 깨고 한자 적어 올립니다(사실 다시 삽질 안 하려고 잊기 전에 올리는 것이지만... ㅡ_ㅡ;;;). 요즘 유저 레벨 응용 프로그램을 추가하려고 시스템 콜 부분을 구현하고 있는데, 인터럽트나 콜 게이트 방식 말고 다른 방식이 아닌 새로운 방식을 한번 도입해봤습니다. 이미 이 글의 제목에도 나와있지만 SYSCALL과 SYSRET 명령어를 사용하는 것이지요.;)


SYSCALL과 SYSRET 명령어는 INTEL과 AMD 양쪽에서 모두 사용할 수 있으며, IA-32e 모드에서 Ring 0와 Ring 3을 순식간에 오가는데 아주 유용하....다고 적혀있습니다. ㅡ_ㅡa... 실제로 얼마나 빠른지는 잘 모르겠지만 콜 게이트나 인터럽트처럼 스택에 데이터를 저장하고 특권 레벨을 체크하는 부분이 없으므로, 이전 것들(?)보다는 빠를 듯 합니다. ^^;;;;


뭐, 일단 SYSCALL과 SYSRET 명령어를 사용하려면 어떻게 환경을 설정해야 하는지는 INTEL 문서 Volume 3에 4.8.8 부분에 잘 나와있으니 생략하고... 실제로 SYSCALL과 SYSRET를 NASM으로 사용할 때 주의할 점만 한 줄로 정리해보면 다음과 같습니다.


IA-32e 모드의 64bit 서브 모드를 사용할 경우
SYSRET 명령어 앞에 REX.W 비트를 반드시 명시적으로 켜줘야 한다.


위의 사실을 찾는 데만 무려 3시간이 걸렸습니다. ㅠㅠ INTEL 문서를 보면 SYSRET의 경우 IA-32e 모드의 서브 모드 중에서 호환 모드(Compatibility Mode)와 64 비트 모드 중에서 선택해서 돌아갈 수 있으며, 그 핵심은 REX.W 비트라고 적혀있습니다. MINT64 OS는 64비트 서브 모드를 사용하니 REX.W 비트를 켜줘야 하는데, REX.W 비트가 켜지지 않아서 시스템 콜을 호출하고 돌아올 때 문제가 계속 생겼습니다.


코드를 생성할 때 64bit로 생성했기 때문에 NASM이 알아서 붙여 줄거라 생각했는데... 확인 결과 아무것도 없이 그냥 SYSRET 커맨드만 덩그러니 있었습니다. 그래서 시스템 콜을 호출한 뒤에 돌아오면... 잘못된 명령어라는 예외가 발생하더군요. ㅠㅠ 그래서 REX.W 비트를 키려고 봤더니... 


얼래... NASM에는 SYSRET 명령어 앞에 REX.W 비트를 명시적으로 붙이는 접두사나 키워드가 없었습니다~!!! (여운산님이 o64 키워드가 있다는 사실을 제보해주셨습니다. o64 키워드를 붙이니까 잘 되더군요 >ㅁ<)-b 완전 감사합니다). ㅠㅠ 오퍼랜드가 있는 다른 명령어들은 뒤에 오는 오퍼랜드의 크기에 따라 REX.W 비트를 켜주는 모양이던데, SYSRET는 오퍼랜드가 없으니 그냥 넘어간 모양입니다. ㅠㅠ 그래서 아래처럼 설정해줬습니다.


DB 0x48  <== REX Prefix로 W 비트가 1로 설정된 상태입니다. ^^;;;; (제가 해결한 무식한 방법입니다)
SYSRET

o64  <== REX.W 비트를 1로 설정하는 키워드 입니다. ;) (여운산님이 제보해주신 방법입니다, 아주 깔끔하네요 ;) )
SYSRET


이걸 해놓고 나니까 겨우 정상적으로 동작하네요. 이제야 겨우 유저 레벨 코드를 작업할 수 있게 되었습니다. ㅠㅠ)-b 안 그래도 할 일이 산더미 같은데... 이런 일로 시간 낭비(?)를 하고 나니 머리가 어찔하네요. ㅠㅠ 에휴... 이제 다시 작업하러 가야겠습니다.


ps) 위의 화면은 MINT64 OS에 이미지 뷰어와 콘솔 셸이 추가된 화면입니다. ㅎㅎ 조만간 또 테스트할 수 있는 바이너리... 보다는 동영상으로 한번 올리겠습니다. ;)

요즘 회사일 때문에 눈코 뜰새 없이 바쁜지라 거의 블로그를 버려뒀습니다. ㅠㅠ 회사에서 머리를 풀 회전시키고 집에 와서 잠시 쉬었다가 다시 작업하고 이런 날들을 거의 추석 근처부터 반복했더니만... 머리가 타는 듯(?) 하네요. ㅠㅠ 그래도 작업은 꾸준히 해야 하는지라 틈틈이 기능을 추가해서 화면 그리기 알고리즘 업그레이드 + 작업 표시줄 + 시스템 모니터까지 진행되었습니다. 아래는 진행된 것을 캡쳐한 화면입니다.

<작업 표시줄과 시스템 모니터가 추가된 화면>


이제 조금만 더 만들어서 콘솔 쉘까지 추가하면 그럴듯해지겠군요. ㅎㅎ 이번에는 동영상보다 직접 실행할 수 있는 QEMU의 이미지를 올렸습니다(절대 동영상을 찍기 싫어서가 아닙니다. ㅠㅠ). 어떻게 돌아가는지 궁금하신 분들은 한번 다운 받아서 실행해보시면 얼마나 허접한지(?) 볼 수 있을 겁니다. ㅎㅎ 파일을 다운받아서 압축을 푼 후 디렉터리 안에 있는 MINT64OS.bat를 실행하시면 됩니다.



아우... 새벽형 인간으로 거듭난지 꽤 되었지만 아침에 일찍 일어나는 건 여전히 힘드네요 ㅎㅎ 이제 그만 또 작업하러 가봐야겠습니다. ;) 다음 글이 또 언제 올라올지 모르겠지만, 틈나는 대로 진행상황을 올리겠습니다. 그럼 다들 좋은 하루 되세요 ;)

<현재 진행 중인 GUI 시스템의 화면> 

추석 연휴 때부터 이것 저것 일이 많아서 미친 듯이 달려왔더니 이제야 블로그에 한자 적어 올립니다. ㅠㅠ 아흑... 요즘 회사에서도 신경 쓸게 많다 보니 점점 작업시간이 줄어들어서 이러다가 큰일(?)나게 생겼네요 ㅠㅠ. 그래도 작업은 해야 하는지라 아침에 좀 무리해서 진행하고 있습니다(이러다 쓰러지는 게 아닌가 모르겠군요. 쿨럭..;;;)

그동안 아주 쉬운 알고리즘을 사용해서 GUI 시스템 작업을 했는데... 이제야 어느 정도 모양이 나와서 올려봅니다. ^^;;; 이제 조금만 더 있으면 바이너리 정도는 공개할 수 있는 퀄러티가 나오겠군요. 일단 윈도우 생성, 닫기, 선택/선택 해제, 이동 정도 구현된 상태입니다. 크기 변경이랑 화면을 좀더 효율적으로 그리는 부분은 좀더 진행되어야 할 수 있을 것 같군요. 아래는 지금까지 구현된 MINT64 OS의 구동 화면입니다. ;)


 



어휴... 이제 또 달려봐야겠네요. ㅠㅠ 다음 포스팅은 언제가 될지 모르겠지만... 조만간(?) 다시 하나 올리겠습니다.

ps) 어휴... 이것 참... 언능 해야 될 텐데... 큰일이군요. ㅠㅠ

지난 주에 아우~ 새벽형 인간으로 바꾼지 일주일쯤 지났습니다. 그리고 아침에 꾸준히 작업한 결과 MINT64 OS에 새로운 기능을 추가할 수 있었습니다. ;) 바로 클리핑(Clipping) 기능입니다.

클리핑 기능은 화면에 표시되지 않는 영역을 잘라 내어 이미지가 요상(?)하게 출력되는 것을 막는 작업입니다. 요상하게 표시되는 게 어떤 건지는 아래 두 화면을 비교해 보면 금방 알 수 있습니다. 위의 그림과 아래 그림을 비교해 보면 클리핑 처리를 하지 않았을 때는 화면 영역을 벗어난 나머지 영역이 그 반대편에 표시됩니다.

clip_image002

<클리핑 전 화면>

clip_image002[4]

<클리핑 후 화면>

클리핑 처리가 필요한 이유는 비디오 메모리가 연속된 하나의 덩어리기 때문입니다. 즉, 우리가 화면에서 보는 라인 단위로 딱딱 구분되어 있는 것이 아니라, 라인들이 순서대로 주욱 연결되어 하나의 메모리 공간을 형성하고 있습니다. 그래서 윗 라인의 끝부분에 윈도우를 출력하면 그 다음 라인까지 영향을 받습니다. 클리핑 처리는 보이지 않는 부분은 그리지 않음으로써 이러한 문제를 해결하는 기법입니다. ^^;;;;

사실 어렵게 하려면 한없이 어렵게 할 수 있고, 속도를 좀 포기하면 한없이 쉽게 할 수 있는 것이 클리핑 처리인데... 저는 쉬운 방법을 택했습니다(어떻게 했는지는 “비밀” 입니다. ㅎㅎ 나중에 공개할께요 ^^;;).

에휴~ 이제 슬슬 마우스를 추가해야겠군요. 마우스가 없으니 원... 그냥 랜덤하게 출력하는 것 말고는 별로 할 게 없네요. 급히 하나 추가해 봐야겠습니다. ㅎㅎ 그럼 다들 좋은 주말 되시길 ;)

이번 주와 지난 주 2주에 걸쳐 MINT64 OS에 2D 그래픽 라이브러리를 추가하고, 그걸로 윈도우 프로토타입을 만들어 봤습니다. 아우, 이미지로 만든 윈도우 프로토타입은 24bit Color 였는데, 실제 MINT64 OS는 16bit Color를 사용하고 있어서 색을 맞추는데 시간이 좀 많이 걸렸습니다. ㅠㅠ 그리고 닫기 버튼을 그리는데도 상당한 시간이 걸렸네요 ㅠㅠ

아래는 인증샷~!! 입니다. ;) 이미지랑 상당히 비슷하죠? ㅎㅎ

image

<실제 코드로 구현된 MINT64 OS의 윈도우 프로토타입>

image

<포토샵으로 만든 윈도우 프로토타입>

꼭두새벽부터 일어나서 작업을 했더니 머리가 좀 머엉~ 하네요 ㅎㅎ 그래도 만들어 진 녀석을 보고 있으니 왠지 흐뭇합니다. 이제 클리핑 처리 좀 하고 마우스를 집어 넣은 다음 윈도우 시스템을 추가하면 그럴듯한 녀석이 나오겠군요. ;) ㅎㅎ 신납니다.

에혀 언능 언능하고 응용프로그램쪽으로 넘어가야 하는데, 역시나 작업 능률이 문제군요. ㅡ_ㅡa.. 아침형 인간으로 재탄생할 때까지는 아무래도 어정쩡~ 할 것 같습니다. 역시나 노력하는 수 밖에는 없겠네요 ㅎㅎ 에궁~ 잠시 쉬었다가 또 작업을 시작해야겠군요. ㅎㅎ

마우스와 클리핑이 추가되면 동영상으로 하나 만들어 올리겠습니다. 그럼 좋은 하루 되세요 ;)

+ Recent posts