코드 작성 후 

Project > Settings 에 진입한다.

그 후 다음과 같이 설정


그리고 컴파일하면 다음과 같이 Debug 폴더에 asm 파일이 생성된다...



수고~
Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

  1. 스파게티코더 2009.11.24 21:54  댓글주소  수정/삭제  댓글쓰기

    앗 교육시간에 포스팅을~!

  2. BlogIcon louis vuitton replicas 2012.09.12 13:22  댓글주소  수정/삭제  댓글쓰기

    아직 트윗된 메시지가 없습니다. 가장 먼저 공유하세요!

터보 C 3.0 에서 실행 ( DOS )

#include <stdio.h>
#include <bios.h>
#include <ctype.h>
#include <conio.h>

#define RIGHT  0x01
#define LEFT   0x02
#define CTRL   0x04
#define ALT    0x08

void main(void)
{
 clrscr();
   int key,shift;

   /* function 1 returns 0 until a key is pressed */
   while (bioskey(1) == 0);
   while(1)
   {
   /* function 0 returns the key that is waiting */
   key = bioskey(0);
   shift = bioskey(2);

   /* print out the character read */
   printf("%c ascii : '%#x scan : %#x'", key, key & 0x00ff,  key >> 8);
   if(shift & RIGHT) printf(" [RShift]");
   if(shift & LEFT) printf(" [LShift]");
   if(shift & CTRL) printf(" [Ctrl]");
   if(shift & ALT) printf(" [Alt]");

   printf("\n");
   if((key >> 8) == 1) // scan code 1 : ESC
 break;
   }
   getch();


}

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

  1. BlogIcon 김광용 2009.11.06 17:06 신고  댓글주소  수정/삭제  댓글쓰기

    아... 어떠케 ㅋㅋㅋㅋㅋㅋㅋ
    형 이제 C만하는겨?? ㅋㅋㅋ
    java, java하던 형은 어디로 가고..

  2. BlogIcon 미남 2009.11.06 20:53  댓글주소  수정/삭제  댓글쓰기

    자바는 이제 끝났다. 돈이 안돼.ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ


브루 어플리케이션은 각각의 고유한 bid 를 갖습니다.

개발자 익스트라넷에서 발급을 받는 것이 정석이지만 개발을 할 때 local 에서 테스트해야 하는 경우가 많으므로

local bid 를 생성해야합니다.

방법은 MIF Editor 를 이용하는 것힙니다.

다음의 절차를 밟습니다.

먼저 mif 에디터를 실행한 뒤 새 애플릿 만들기 버튼을 클릭합니다.



클래스 id 와 name 을 지정하고, 로컬용을 선택합니다.

그리고 확인 클릭.



중요한 건 mif 파일의 위치입니다.

보통의 경우 프로젝트마다의 mif 파일들을 한 디렉터리에 모아둡니다.

그래서 다음과 같이 MIFs 디렉터리를 만들었습니다.


MIFs 디렉터리를 지정해서 저장하면 끝!


이렇게 해서 생성된 bid 파일을 비쥬얼 스튜디오에서 개발할 때 include 해주면 됩니다.

#include "HelloBrew.bid"

이렇게~~

Posted by 행복한 프로그래머 궁금쟁이박
TAG bid, brew, 브루

댓글을 달아 주세요

  1. BlogIcon hermes bags 2012.09.11 17:17  댓글주소  수정/삭제  댓글쓰기

    私はちょうど地区の後にエルメスのレプリカ4分の1を愛して

 

회사에서 브루를 하게 되었습니다.

한 귀로 듣고 한 귀로 흘렸던 Qualcomm 사의 모바일 플랫폼 Brew 가 밥줄이 됐습니다.ㅋ

그 첫 단계로 책의 첫 부분에 있는 브루 SDK 를 설치하고 있습니다.

지금부터 한 단계씩 진행될 때마다의 과정을 포스팅합니다.

브루 SDK 를 설치하기 전에 Microsoft Visual Studio 를 설치해야합니다.

6.0 부터 .NET, 2005 까지 별 상관은 없을 것 같아 2005 를 설치했습니다.

MSDN 은 덤으로... 오랜만에....ㅋ








여기까지는 그냥 MSDN 설치 완료만 캡쳐.ㅋ

그럼 이제부터 브루 SDK 를 홈페이지에서 다운받아 설치합니다. 

http://www.qualcomm.com/brew : 브루 홈페이지.

 


버전을 선택하여 설치를 시작합니다.



쭉쭉 넥스트 했습니다.ㅋ





계속해서...Next






환경변수를 set 할거냐인데... set 해줬습니다.




그럼 Finish!



책에 보니까 개발지 인증을 받아야 한다고 나왔습니다. 그래서 브루 홈피의 개발자 리소스로 가서 인증을 받습니다.





어떻게 된 일인지... Sign in 페이지가 계속 로딩이 되지 않아 인증은 다음에 받기로 했습니다.ㅡㅡ;

필수는 아니라고 했습니다 책님이...ㅋㅋ

아 뭐 별거 아니었습니다 여기까지.ㅋㅋ

그럼 이제 Hello World 를 찍어볼 차례.

Visual Studio 2005 를 켭니다.!

와... 처음 써봤는데 화면이 근사했습니다.ㅋ

촌놈이라고 비웃으실 분이 많겠죠. ㅠㅜ




먼저 에이콘 출판사 홈페이지에가서 소스파일들을 다운받았습니다.... 다 치려고 했으나...

퇴근 버스시간이 다가왔기 때문!!

여기서 받으면 됩니다.

http://www.acornpub.co.kr





받았으며 적당한 디렉터리에 압축을 풀고 프로젝트를 open 합니다.

파일 > 새로 만들기 > 프로젝트

그리고 빌드를 하는데 중요한 것은 먼저 프로젝트의 소스에 있는 파일의 경로가 아마 잘못되어 있을 것입니다. 저는 그랬습니다.

sdk 를 인스톨할 때 아마 C:\Program Files\BREW 3.1.5\sdk\src 여기에 보면

AEEAppGen.c

AEEModGen.c

이 두개의 파일이 깔렸을겁니다.

이 두개의 파일들이 일련의 유틸리티 함수와 함께 모든 어플들의 root 클래스인 IApplet 클래스의 인스턴스 안에 우리가 개발한 어플을 넣을 수 있게 해주는 wrapper 들을 포함하고 있다

고 합니다... 나중에 꼭 살펴보라네요^^;

프로젝트의 소스파일에 있는 잘못된 경로의 이 파일들을 지우고 본래의 위치의 파일들을 열어서 프로젝트에 추가시킵니다.

그런다음 빌드 > 솔루션빌드 를 실행합니다.

뭔가 잘못되었는지 워닝이 엄청나게 나면서 성공은 했습니다.;;



그런다음 디버깅 > 디버깅 시작 을 선택하여 애플을 시작합니다.

dll 을 실행할 어플리케이션으로 퀄컴 브루 에뮬레이터를 선택합니다.

이 것은 C:\Program Files\BREW 3.1.5\sdk\bin\BREW_Simulator.exe 을 의미하는 것 같습니다.

그런데 선택하고나니 디버깅 정보를 찾을 수 없거나 정보가 일치하지 않는다며... 디버깅을 계속 하겠냐고 묻더군요...

짜증나서 그냥 '예' 했습니다.

그랬더니 윈도우창 하나가 뜨더니 옛날 공짜 핸드폰 같은 것이 떡하니 나타나는 것이었습니다.



저기 화면 좌측 상단에 보이는게 Hello world 어플같았습니다.

여기서 또 해줘야할 것이 Tools > Settings 를 선택한 다음 Specify MIF Directory 를 체크한 뒤 프로젝트 디렉터리로 바꿔주는 일입니다.



그리고 마지막으로 Initial Applet Directory 를 프로젝트의 상위 디렉터리로 바꿔줘야 합니다.




그럼 이제 어플을 실행시켜봅니다.

hello 어플에 포커싱이 되어있으므로 OK 버튼을 클릭합니다.

헬로월드가 다음과 같이 찍히게 되는 것입니다...!!!





아 요거참... 찝찝하게 성공했네요...ㅠㅜ

생략한 부분이 좀 많은데 하다보면 문제가 정말 많습니다.

제 생각에는 Visual Studio 2005 가 브루 개발 환경과는 궁합이 잘 안맞는 것 같습니다. 책에서는 6.0 을 대상으로 한다고 써있었는데...

역시 책 말을 잘들어야 하는건가...ㅠㅜ

담주에 와서 다시 6.0  도 깔아서 깔끔하게 끝낼 생각입니다.

그럼 이만~


Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

  1. chpie 2009.09.01 05:04  댓글주소  수정/삭제  댓글쓰기

    헐퀴....

  2. BlogIcon 행복한 프로그래머 궁금쟁이박 2009.09.01 09:08 신고  댓글주소  수정/삭제  댓글쓰기

    헉 빼먹은게 있는데 SDK Tools 도 설치해야합니다..
    그래야 비쥬얼 스튜디오에서 브루 프로젝트 생성이 가능해집니다.

  3. chpie 2009.09.02 06:53  댓글주소  수정/삭제  댓글쓰기

    네.. ㅋㅋ


출처 : http://recipes.egloos.com/


컴파일 공장 이야기는 컴파일이 어떻게 이루어져서 결국에는 우리가 흔히 말하는 Binary Image라는 것을 어떻게 만들어 낼까 하는 뭐 그런 얘기를 말합니다. 큰걸 기대 했다면 약간 미안하지만 하하. 컴파일 공장을 설명하자면 상당히 공장에 온 것 같은 느낌이 듭니다만, 공장이라는 건 뭔가 시스템화 되어 있으니까 조금은 정리되어 있는 느낌도 있습니다.

 

컴파일공장의 목적은 바로 우리가 흔히 말하는 Native code의 집합인 Binary Image를 만들어 내는 것이 목적입니다. Binary의 정체는 바로 Processor만이 알아들을 수 있는 Native Code(기계어)의 집합입니다. 인간의 눈으로는 도저히 무슨 말인지 알아낼 수가 없는 뭐 그런 세상의 것입니다. 컴파일의 단상에서 불쑥 튀어나온 그 녀석입니다.

 

Binary를 만들어 내기 위해서 원료가 필요합니다. 그 원료는 하하 바로 .c나 .h, 그리고 .s 등의 파일들입니다. (.c, .h는 C code와 header 그리고 .s는 ARM assembly file입니다. ) .s의 경우에는 .c를 컴파일하고 나면 Assembly로 만들어 줄 수 있지만, 여러 가지 성능 측면에서 사람이 직접 Assembly로 짠 파일입니다. 뭐 별거 아니지요.

 

컴파일은 Source file들을 C complier (armcc, tcc)를 이용하여, Assembly로 만들고, 또 이를 Assembler (armasm)을 이용하여 실행 가능하고, Symbol정보를 가진 특정한 type (여기서는 Elf - Excutable and linkable format)으로 만든 후, 그 안에 있는 정말 Native Code(기계어)인 1010으로 이루어진

binary를 뽑아냅니다.

 

 

 

 

그런데, 아, 여기서 문제가 하나 발생했습니다. 간단한 Software야 위의 그림처럼 .c file하나 만들어서 compile하면 있고없고없고있고의 binary를 만들어 낼 수 있겠지만,  요즘 같은 세상에 그런 간단한 프로그램이 있을 리가 만무합니다. 음.. 그럼 요즘 같은 세상에는 어떻게 큰 프로그램이 만들어 질까요~? 대단히 긴~ .c file을 컴파일 해서 Assembly로 만든 후 Assembler로 기계어를 만들어 낼까요?

 

음, 인간은 의외로 똑똑 한 개념들을 만들어 내는 재주가 있지요. 인간은 여기에 link라는 개념을 만들었습니다. link라는 것은 여러 개의 .c file을 Assembly로 만든 후 Assembler를 이용하여 Object라는 새로운 기계어 형태를 만들어 내어 이런 object들을 link (연결) 하는 것을 말합니다. (오, 이렇게 하면 여러 개의 .c file을 이용하여 프로그램을 만들 수 있겠네요.) object는 각각의 기계어이긴 하지만 혼자서 완성된 형태는 아니며, 각기 다른 .c를 컴파일 한 object와 연결할 수도 있는 정보와, 디버깅이 가능한 symbol정보를 담고 있습니다.  이 형태는 요즘 흔히들 말하는 elf 형태를 말하는 것이며, elf 형태를 따른 object들은 linker를 이용하여 서로 link할 수 있게 되는 것이죠. 헉헉.

 

자 어쨌거나, 다시 말하면 컴파일은 Source file들을 C complier (armcc, tcc)를 이용하여, Assembly로 만들고, 또 이를 Assembler (armasm)을 이용하여 object file로 만듭니다. 이때 object file은 나중에 linker (armlink)를 이용하여 모두 엮이게 되며, 이때 output으로 나오는 것 또한 elf 라는 확장자를 가진 큰 elf가 나오게 됩니다. 음.. 상당히 쉬운 공장이죠?

 

한가지 비밀을 더 폭로하자면, armcc, tcc는 내부적으로 *.c file을 *.s file로 만들어 주고 , 만들어진 *.s file을 다시 armasm을 이용하여 *.o (object file)로 만들어줍니다. 결국 알아서 두단계를 자동으로 해주니까 편리하네요. 그마저 자동으로 하는 거 보면 사람은 정말 귀찮은 게 싫은가 봅니다.

 

그리고, armcc, tcc가 *.c file을 *.s로 만들기 전에 Preprocessor(전처리기)라고 불리 우는 일을 합니다. 자꾸 복잡한 얘기가 끼어 들기 시작합니다만, 일단 C processor와 lint Processor 라는 걸 이용해서 웬만한 syntax적인 것들을 정리해 둡니다. lint processor라는 건 UNIX계열에서 사용하는 Syntax 정리기 비스므리한 것이에요. 선언된 macro나 define을 compile하기 전에 모두 바꿔 치기 해 놓는다거나, syntax error가 있는지 등을 점검한 후, armcc나 tcc가 제대로 컴파일 할 수 있는 단계까지 만들어 놓으면, armcc나 tcc는 Assembly로 만들고, 그를 최적화 하는 것에만 신경 쓸 수 있게 해주는 거지요. 아.. 사족이 길었네요.

 

결국 c-compiler로 .c file 하나를 컴파일 하면,

ⓐ 전처리를 하고 (#define이나, #include등의 것을 잘 처리해서 끼워 넣어서 c 형식의 .i file을 만듦)

ⓑ 전처리 된 녀석을 mnemonic의 Assembly로 만들고 (기계어와 1:1 대응의 .s Assembly로 만들고)

ⓒ Assembly를 실제 기계어로 만들어준다. (elf 형식의 .o file로 만든다)

 

계속 허접하게 늘어놓은 말을 그림으로 그리면 다음과 같습니다.

 

 

 
 
 

ⓐ 뒤에서 다루겠지만, 몇 가지 더 덧붙이자면 lib file은 source code를 제공하고 싶지 않은 개발자가 object 형식으로 미리 컴파일 하여 제공하고, lib은 다른 컴파일 된 object들과 link되어 같이 물려 들어가는 형식을 취합니다.

 

ⓑ 또한 link시에 scl이라는 것이 새로 들어가 있는데요, 이것은 Scatter Loading이라고 부르며, binary를 만들어 낼 때, 메모리의 주소 구성을 원하는 대로 주물럭 주물럭 댈 수 있게 해주는 script file입니다.

 

ⓒ Map file이나 Sym file은 compile된 binary의 메모리 구성을 나타내 주는 text file인데요, 보통 compiler option을 줘서 만들어 낼 수 있는 option file이에요.

 

 

뭐 다 그렇고 그런 얘기 입니다만, 마지막에 큰 elf는 fromelf라는 Utility를 이용하여 symbol정보 같은 군더더기를 빼내고 나서 순수 기계어 덩어리로 만들어 낸 것입니다. - 자 결국에는 또 인간으로는 도저히 알아낼 수 없는 머 그런 세상입니다. 하하.

 

 

Cross Compile 이란.

이제 와서 Cross Compile이란 걸 얘기하는 게 쑥스럽지만, 개발 된 Source Code를 다른 CPU에서 동작할 수 있도록 Target CPU에 맞도록 Compile해 주는 것을 의미하는데요, 예를 들어 X98 계열의 PC Host에서 개발한 Source Code를 ARM에서 동작할 수 있도록 PC Host에서 Compile을 해주는 것을 말하는 거지요. 말은 멋지지만 별건 아니죠

 


 이제부터 Cross Compiler로는 ADS라는 걸 기준으로 가겠습니다. 그러니까 간단하게 말해서 ADS라고 말이 나오면, Compiler로구나! 라고 생각하심 되어요. ARM에서 동작하는 Software를 만들어 주는 Compiler라는 사실이라는 것만 알아두면 되어요. ADS는 ARM社에서 파는 ARM Developer's Suit이라고 하는 건데요, 이게 제일~ 상용으로 많이 쓰이니까 이걸 기준으로 하는 거에요. 실은 GNU 진영의 ARM GCC도 있고요, 머 여러가지 compiler가 있답니다.  

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요


출처 : http://recipes.egloos.com/


프로세서는 많은 전기적 스위치로 이루어져 있으며, 어떤 특정한 전기 스위치를 작동 시키기 위해서는
데이터 버스 선을 따라 전압이 "있고 있고 없고 없고 없고 없고 없고 있고 있고"의 상태로 만들어 주면 된다라는 의미

자, 처음으로 Software에 입문하시는 분들은 Compile이라는 단어를 아주 자주 듣게 되는데요, Compile이라는 단어를 영어 사전에서 찾아보면 책을 편집하다, 안내서를 만들다 라는 뜻이에요. 그럼, Computer에게 안내서를 만든다는 것은 무엇을 의미하는 것이죠?

 

프로세서가 해석할 수 있는 것은 단지 명령어로서, 이 명령어는 "기계어"라고 불리 우는 특정 bit pattern을 말합니다. "Processor는 약속되어진 특정한 Bit Pattern에 반응한다."는 의미에서 특정 Bit Pattern을 명령어라고 부를 수 있습니다.

 

쉽게 말해 프로세서는 많은 전기적 스위치로 이루어져 있으며, 어떤 특정한 전기 스위치를 작동 시키기 위해서는 데이터 버스 선을 따라 전압이 "있고 있고 없고 없고 없고 없고 없고 있고 있고"의 상태로 만들어 주면 된다라는 의미와 일맥상통할 수 있을 것입니다.

 

예를 들어, Processor가 "11000001 10100000 101000 111011"라는 bit pattern (즉 16진수로는 C1 A0 28 3B 라는 32bit pattern)을 Register 1과 Register 2를 더해서 Register 1에 결과를 저장하라는 내용으로 약속을 한다면, Processor에게 Register 1과 Register 2를 더해서 Register 1에 결과를 저장하라고 일을 시키고 싶을 때는 11000001 10100000 101000 111011 의 32bit bit열을 Data Bus를 통하여 Processor에게 던져주면 Processor는 그 일을 실행하게 됩니다.  - 막상 이런 pattern을 해석하는 디지털 회로는 Decoder에요 우훗 -

 

 

 
 

프로그램이란 이런 일련의 기계어 명령의 순차적인 집합이며, 예전에는 이런 기계어 명령을 사람이 직접 Processor에게 입력시켜 주었었드랬습니다. 그러다 보니, 사람이 이런 이진수의 나열을 해석하기 쉽지 않으니까 - 이런 기계어 명령을 Native Code라고 부른다고 했었죠. -Assembly라는 개념을 도입하게 되었는데, Native Code(기계어)와 1:1 matching이 되는 그나마 사람이 보기 쉬운 표기 체제를 만들어 냈습니다. 예를 들어 Memory에 Data를 읽어 오는 "LDR R0,= 0xFF"를 bit pattern으로 분석했더니, 0x3CD1FF과 완전히 같은 말이며, 이것은 bit pattern으로는 1111001101000111111111이 되며, 이것들은 서로 완전히 1:1 대응이 되어 Assembly로 표현 되었을 때 사람이 보기에 훨씬 편하게 됩니다.

 

이런 이유로 인간은 bit pattern을 직접 입력하지 않고, Assembly로 coding을 하게 되었으며, 이를 Native Code(기계어)로 바꾸어 주는 것이 compile의 목적이었습니다. 그래서, 예전에는 인간이 직접 code표를 찾아서 기계어로 바꾸어주는 일을 했죠. 예전에 태어나지 않은 것이 천만 다행입니다. Compile을 손으로 직접 하다 보니, 성격을 많이 버리게 된 거죠. 인간은 귀찮은 일은 딱 질색으로 하는 인종인지라, 코드 표를 찾는 일을 대신 해주는 Assembler라는 것을 만들게 되었습니다. 그것이 compiler의 최초 태동입니다. 원래는 LDR R0,=0xFF 이런 명령어는 기계어에 존재치 않고, 1111001101000111111111 만 있었다는 얘기죠.

 

자, 그런데 이 Native Code(기계어), Assembler라는 것이 특정 Processor에만 통한다는 사실!. Processor는 약속 되어 진 특정한 Bit Pattern에 반응한다는 사실 때문에, Processor마다 다른 Assembler를 지원하므로 특정 Processor에 맞추어서 만들어진 프로그램은 다른 종류의 Processor에서는 동작하지 않는다는 문제점이 있었습니다. 흔히들 말하는 Compatibility 호환성에 한계를 드러냈는데, 서로 다른 Processor에 맞는 Assembly를 만들어내는 Compiler가 있었으면 좋겠다는 인간의 귀차니즘이 또 하나의 새로운 entity를 만들어 냅니다.

 

그것이 무엇이냐 하면, C나 C++같은 High Level Language compiler입니다. C같은 High Level Language로 Coding을 하고 나면, 내가 동작시키고자 하는 Processor에 맞는 C compiler를 이용해서 그 Processor에서 동작 가능한 Assembly를 generation하는 Compiler를 만들어 낸 것이지요. 여기에서 또 하나! 보통 사람들이 C가 이식 성이 좋다고 하는데, 이식 성이 좋다고 함은 많은 Processor들에 C Compiler가 제공된다는 말입니다. C 자체가 이식 성이 좋다고 하기는 쫌 그르치요~

 

결국 ARM core를 예를 든다면, C로 coding을 한 후, compile한다는 의미는 C compiler를 이용하여, ARM이 해석 할 수 있는 Assembly를 만들어 낸 후, ARM Assembler를 이용하여, ARM core가 해석할 수 있는 일련의 Bit pattern의 만들어 낸다고 할 수 있겠습니다.

 

이런 bit pattern을 한 덩어리 뭉쳐놓은 것을 흔히들 말하는 Executable binary image라고 합니다.

 

 

 
 

mnemonic : mnemonic은 사람의 기억을 돕기 위하여 사용되는 Symbol을 의미하는데, 결국 assembly는 기계어와 1:1로 matching되므로 Assembly 코드를 mnemonic이라고 불러도 무방합니다.

 

실은 중요한 것은 이렇게 메모리 안에 들어 있는 숫자들이 CPU가 가져다가 실행하면 명령어고, 수정하거나 고치면 데이터라는 사실이죠.

 

흔히들 cross compile 환경이라는 말을 많이 쓰는데, Cross Compile이란 실제 Target에서 돌아갈 binary image를 PC 상에서 compile 할 수 있게 해주는 환경을 말합니다. 흔해 PC에서 컴파일 한 것은 PC에서 실행하는 게 정상인데, embedded system에서는 target자체에서 컴파일을 수행하기에 너무 작은 시스템이며, 불편하기에 이런 환경을 만들어 binary image를 PC상에서 만들어 내는 거죠.

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요


이제 꼼짝없이 임베디드 시스템을 공부해야 하게 되었습니다.

자료 찾기가 쉽지만은 않았는데 히언 님의 블로그에서 좋은 자료를 찾았습니다.

좋은 내용들 퍼다가 공부해야겠습니다.

출처 : http://recipes.egloos.com/

=================================================================================================================================================================


사람은 processor보다 위대한 존재이죠. 그러니까 형 (big)이고요,
processor는 동생 (little)입니다. - 걸리버 여행기 -

 

숫자로 가득 메워진 - 영화 메트릭스의 오프닝에 다다다다 올라가는 듯한 - 기계의 언어 세상에서 그 숫자들을 제대로 해석하려면 한 가지 익혀두어야 하는 법칙이 하나 있습니다. 메모리 영역이나, 기계어 영역의 숫자들을 제대로 이해하려면 꼭 알아둬야 하는 법칙이기도 합니다.

 

아래의 내용은 어디선가 주워 들은 얘기를 다시 한번 재미 삼아 들려 드릴 테니, 잘 들어보세요. 흥미진진합니다.

 

 

 

 

" 같은 일을 하는데 방법이 두 가지가 있다면, 아마도 두 개의 서로 다른 회사는 서로 다른 방법을 채용할 가능성이 다분할 것입니다.  머피의 법칙이기도 한 이런 가능성은 서로 다른 칩디자이너가 메모리에서 데이터를 서열화하는 방법에도 또한 마찬가지로 통용됩니다.  걸리버 여행기에 등장하는 소인국은 매우 작은 나라인데, 그에 걸맞게 사소한 정치적인 문제를 가지고 있었습니다.   Big-Endian당과 Little-Endian당이 격론을 벌이는데, 그 격론의 내용이라는 것이 반숙된 달걀을 깨고자 할 때, 뭉툭한 끝(Big-End)을 먼저 깰 것인가 아니면 뾰족한 끝(Litttle-End)부터 먼저 깰 것인가라는 것 이었습니다. 1980년 4월 1일, 대니 코헨(Danny Cohen)이 지금에서는 유명하게 된 "On Holy Wars and a Plea for Peace"라는 책에서  워드에서의 바이트 오더링(Byte Ordering in Words)에 대해 논하면서 '엔디안'이라는 용어를 이 문제를 지칭하는데 처음 사용했습니다. 그 후 곧바로 이 용어는 고착되었고, 엔디안 이라는 용어는 Byte Ordering을 의미하게 되었습니다.   유닉스 프로그래머는 "NUXI 문제"라고 부르기도 하는데, 바이트 오더링에 착오가 생기면 'UNIX"라는 단어의 입력에 대해 앞뒤가 뒤바뀌어 'NUXI'라는 출력이 나오니까 말입니다. " 재미있죠?


 

이 이야기에서부터 시작하면 모든 processor는 Little Endian 또는 Big Endian중 하나를 사용하게 되는데, 이는 무엇을 의미하는 걸까요? 이것은 processor가 memory에 저장하는 방식을 의미하는데, 저장 방식이 다를 뿐이죠. 이 방식을 이해하지 못하면, 디버깅 시에 오류에 빠질 수가 있으니 꼭 이해해야 하는 부분 임을 이해해 주세요. 당부.

아래 그림을 보면 이해가 확실히 될 것입니다..

자, 그럼 예를 들어 dword 0x12345678, word 0x1234, 또는 byte 0x12를 0x1000번지부터 저장하는 방식을 볼까요? 번지 하나에는 1byte가 들어갑니다요. (dword는 4byte, word는 2byte, byte는 8bit 크기로 다룰께요.)

                                    0x1000   0x1001   0x1002  0x1003
Big Endian     dword       0x12       0x34      0x56     0x78
                      word        0x12       0x34
                      byte         0x12     

Little Endian  dword       0x78       0x56      0x34     0x12
                      word        0x34       0x12
                      byte        0x12
  

자, 그림을 보니 확 느낌이 오죠?  - 라고 말했지만, 중요한 것은 Little Endian은 그 크기만큼 무조건 거꾸로 읽는다 가 힌트입니다. -

자, 그럼 Big Endian과 Littel Endian은 어떤 차이가 있을까요?

   쉽게 말해서 "Little Endian은 상위bit (MSB)를 상위 주소에 저장을 하고 있습니다요"가 힌트입니다. 네 그렇습니다. Little Endian으로 처리를 하게 되면, Processor는 Software에서 정해준 type 크기 만큼 그대로 읽어와서 처리를 하게 되고요,  Big Endian의 경우에는    대신 낮은 주소부터 읽어와서 MSB로 넣어주면 됩니다. (MSB가 LSB쪽으로 정렬되어 있으니까요, MSB와 LSB는 사족에!)
 
   dword type의 0x12345678을 저장하는 것을 다시 그림을 그려서 본다면 아래와 같습니다.

                                0x12345678
                                 MSB      LSB

                      Big Endian                Little Endian
0x1003                0x78                          0x12
0x1002                0x56                          0x34
0x1001                0x34                          0x56
0x1000                0x12                          0x78

   
사실 어느 게 더 좋다고 말하긴 어려우나, ARM의 경우에는 Little Endian을 지원하니, Little Endian의 경우를 잘 알아 두는 것이 좋겠지요?

근데, 또 재미난 사실이 하나 있습니다.
우리가 소프트웨어를 구성할 때 Little Endian이냐 Big Endian이냐를 compile환경에서 설졍 해 줄 수가 있습니다. 물론 ARM 환경의 Embedded system이라면, Little Endian으로 Memory의 내용을 인식하는 것이 Default이니까, Compile할 때는 Little Endian으로 option을 주고 compile해야겠지요?

컴파일 버전 중 사용하는 ads 의 Compile flag들을 에서 확인해 보면, 다음과 같은 구문을 확인할 수 있을 것입니다.

#-------------------------------------------------------------------------------
# Compiler code generation options
#-------------------------------------------------------------------------------

END = -littleend#               # Compile for little endian memory architecture
....... (생략) ..........
CODE = $(END)
....... (생략) .........


자, 어떤가요? 간단하죠? 교훈이 하나 있어요. 뭐냐하면, 다음과 같은 논리입니다. 사람은 processor보다 위대한 존재이죠. 그러니까 형 (big)이고요, processor는 동생 (little)입니다. 그런 의미에서면, 사람이 읽기 편하게 메모리에 저장되면 big endian, 사람이 읽기 불편하면 little endian이라고 기억해 두면 잘 기억되겠죠?

* 사족 : NUXI 문제를 word씩 읽는다고 가정했을 때, Little Endian으로 NUXI으로 저장되어 있다면, Little Endian으로 읽으면 (1 word = 2 bytes) UNIX가 되지만, 그대로 Big Endian으로 읽으면 NUXI가 됩니다. 마치 띄어쓰기를 잘 못해 아버지가 방에 들어가신다와 비슷한 꼴인 듯한 기분인데요. 

 

        

ARM에서는 어떻게 Big Endian/ Little Endian 지원하는가요?

        기왕 Little Endian과 Big Endian 얘기가 또 나왔으니까 하는 말입니다. ARM의 경우, Little, Big Endian을 모두 지원하는데, 이건 어떻게 결정하느냐, ARM core를 채용해서 구현한 chip이 어떻게 생겼느냐에 따라 다릅니다. 보통은 외부에서 pin을 하나 설정해서 Low/ High로 Endain을 다르게 동작하게 만드는 것이 Alternative입니다만, chip에 따라서는 한가지만 지원하도록 아예 SoC를 하는 경우가 많습니다. 이런 설정에 따라서 compile을 할 때, Little, Big Endian을 제대로 setting해서 compile해줘야 합니다. 또는 이렇게 따로 설정하지 않은 경우에는 ARM은 default Little Endian이며, Co processor 레지스터 CP 15를 통해서 Big Endian으로 만들 수 있습니다.

 

 

 LSB와 MSB는 bit를 따질 때 높은 쪽 자리의 숫자이냐, 낮은 쪽 자리의 숫자이냐를 따질 때 쓰는 용어인데, 예를 들어, 8bit의 이진수가 10001000있다고 치면, 이때 맨 왼쪽 자리를 MSB (Most Significant Bit)라고 부르고요, 이 예에서는 1이 되겠죠. 그리고 맨 오른쪽 자리를 LSB (Least Significant Bit)라고 부르고요, 이 예에서는 0이 되겠네요. 그래서 상위 2bit를 지칭 할 때는 MSB 2bit이라고 하고 맨 왼쪽 두 자리 10이 되고요, 하위 3bit를 지칭 할 때는 LSB 3bit라고 부르고, 맨 오른쪽 세자리 000을 의미해요.

 

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

  1. 2010.05.07 10:28  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

http://kldp.org/KoreanDoc/html/GNU-Make/GNU-Make.html
Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

마지막 학기 윈도우프로그래밍을 들으면서 MFC 를 공부한다...

언제나 그랬듯이 HelloMFC 프로그램을 먼저 작성했다.

그런데 에러가 나는 것이다. 라이브러리 참조가 안되는 듯 했다..

알고보니... 비쥬얼 스튜디오의 설정을 살짝 바꾸어 주어야 했다.

다음 화면에서 보는 것처럼 MFC 라이브러리를 사용하도록 설정해 주어야 하는 것이다.



다음은 HelloMFC.cpp 의 소스코드이다.

 #include <afxwin.h>

// 클래스 선언부
class CHelloApp : public CWinApp
{
public:
 virtual BOOL InitInstance();
};

class CMainFrame : public CFrameWnd
{
public:
 CMainFrame();

protected:
 afx_msg void OnPaint();
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
 DECLARE_MESSAGE_MAP()
};

// 응용 프로그램 객체
CHelloApp theApp;

// 클래스 정의부
BOOL CHelloApp::InitInstance()
{
 m_pMainWnd = new CMainFrame;
 m_pMainWnd -> ShowWindow(m_nCmdShow);
 m_pMainWnd -> UpdateWindow();

 return TRUE;
}

CMainFrame::CMainFrame()
{
 Create(NULL, "HelloMFC Application");
}

void CMainFrame::OnPaint()
{
 char *msg = "Hello, MFC";
 CPaintDC dc(this);

 dc.TextOut(100, 100, msg, lstrlen(msg));
}

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
 MessageBox("마우스 왼쪽 버튼을 클릭했습니다.", "마우스 메시지");
}
void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
 MessageBox("마우스 오른쪽 버튼을 클릭했습니다.", "마우스 메시지");
}
void CMainFrame::OnLButtonDblClk(UINT nFlags, CPoint point)
{
 MessageBox("마우스 왼쪽 버튼을 더블클릭했습니다.", "마우스 메시지", MB_YESNOCANCEL | MB_ICONQUESTION);
}


// 메시지맵 ( MFC 의 핵심 )
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 ON_WM_PAINT()     // OnPaint()
 //ON_WM_LBUTTONDOWN()    // OnLButtonDown()
 ON_WM_RBUTTONDOWN()    // OnRButtonDown
 ON_WM_LBUTTONDBLCLK()   // OnLButtonDblClk()
END_MESSAGE_MAP()

마우스 왼쪽, 오른쪽 버튼 클릭 이벤트와 더블클릭 이벤트를 테스트 해보았다.

메시지 박스의 세번째 인자에 의해 아이콘이나 버튼 종류를 결정하는 코드도 보인다.

MFC 세계 ㄱㄱ

Posted by 행복한 프로그래머 궁금쟁이박
TAG MFC

댓글을 달아 주세요

 오늘은 이중 연결 리스트에 대해 다시한번 기억을 되살렸다.

자료구조의 기본 중의 기본이지만 구현해 볼 때마다 책 없이 혼자하라고 하면

시간이 꽤 걸린다. 나만그런가;ㅋ

어쨌든 오늘 중요한 자료구조를 또 한번 코딩해본 것은 의미있는 일이다.

 으허허~


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4
      5 struct A
      6 {
      7         char name[20];
      8         int age;
      9         int salary;
     10         struct A *before;
     11         struct A *next;
     12 } *head, *tail;
     13
     14 void input(void);
     15 void output(void);
     16
     17 int main()
     18 {
     19         head = tail = NULL;
     20         input();
     21         output();
     22         return 0;
     23 }
     24
     25 void input (void )
     26 {
     27         struct A *ptr;
     28
     29         while(1)
     30         {
     31                 if((ptr = (struct A *)malloc(sizeof(struct A))) == NULL)
     32                 {
     33                         printf("Memory Allocation Error\n");
     34                         exit(1);
     35                 }
     36
     37                 printf("\n성명 ? ");
     38                 gets(ptr -> name);
     39                 if(!strcmp(ptr -> name, "end"))
     40                         break;
     41                 printf("나이 ? ");
     42                 scanf("%d", &ptr -> age);
     43                 printf("월급 ? ");
     44                 scanf("%d%*c", &ptr -> salary);
     45                 ptr -> before = NULL;
     46                 ptr -> next = NULL;
     47
     48                 if(head == NULL)
     49                         head = tail = ptr;
     50                 else
     51                 {
     52                         ptr -> before = tail;
     53                         tail -> next = ptr;
     54                         tail = ptr;
     55                 }
     56         }
     57         free(ptr);
     58 }
     59
     60 void output(void)
     61 {
     62         struct A *ptr;
     63
     64         printf("\nNode List head -> tail \n");
     65         ptr = head;
     66         while(ptr)
     67         {
     68                 printf("name : %s, age : %d, salary : %d\n", ptr -> name, ptr -> age, ptr -> salary);
     69                 ptr = ptr -> next;
     70         }
     71         printf("\nNode List tail -> head \n");
     72         ptr = tail;
     73         while(ptr)
     74         {
     75                 printf("name : %s, age : %d, salary : %d\n", ptr -> name, ptr -> age, ptr -> salary);
     76                 ptr = ptr -> before;
     77         }
     78 }
     79
     80

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요