2014. 2. 11. 23:30
     

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을 이용하시면 좀더 편리하게 작업하실 수 있습니다. ;)


Android App

Posted by 호기심 많은 kkamagui(까마귀, 한승훈)

댓글을 달아 주세요

  1. whitesky2 2015.08.10 09:51  댓글주소  수정/삭제  댓글쓰기

    커널을 C언어로 제작하기위한 링커 스크립트 부분에서요
    수정된 부분만 따로 링커 스크립트로 만들어서 컴파일해도 상관없나요?