이번 장에서는 명령어 몇개를 사용하여 첫 스크래치 프로젝트를 만들어 보겠습니다. 완료 후에 프로젝트를 실행 하면 캐릭터가 말풍선을 출력하고 보였다 사라졌다를 반복하는 간단한 프로젝트 입니다.

1) 명령어 배치하기
스크래치는 명령어들을 해당 스프라이트의 스크립트 영역에 배치하고 이 명령어들이 조건에 맞게 순차적으로 실행됩니다.

사용자 삽입 이미지
각각의 명령어들은 좌측과 같이 8개의 항목으로 분류되어 있습니다. 명령어 블럭들의 색을 보면 어느 분류에 속해 있는지 알 수 있습니다. 

현재 선택된 분류는 Control과 같이 전체 색상으로 구분되며 하단에는 Control과 관여된 블럭이 오게 됩니다. 이제 이 Control 블럭에서 깃발모양의 [when clicked] 블럭을 마우스로 드래그 해서 스크립트 영역으로 가져다 놓습니다.

사용자 삽입 이미지

[when clicked] 블록은 사용자가 깃발 버튼을 클릭하면 실행되는 블럭입니다. 이제 이 프로젝트가 시작할 때 해야할 작업을 위해서 다른 블록들을 연결합니다.

사용자 삽입 이미지
Looks 항목에서 [say[Hello!]] 블럭을 가지고 옵니다. 각각의 블럭들은 블록한 부분과 오목한 부분에 맞으면 연결할 수 있습니다.

[say[Hello!]]을 드래그해서 [when clicked]하단의 홈에 위치시키면 좌측과 같이 연결이 가능하다는 표시로 하얀 줄이 생깁니다. 이 줄이 생길 때 마우스 버튼을 놓으면 블럭들이 결합됩니다.

사용자 삽입 이미지
결합된 블럭들은 순서에 따라서 위에서 아래로 실행됩니다. 테스트를 위해 깃발을 클릭하면 스프라이트 위로 'Hello!'라는 말풍선이 출력됩니다.


이제 스프라이트를 반복적으로 보여 주었다 사라졌다 하도록 만들기 위해 다른 명령어 블럭들을 추가해 보겠습니다.

사용자 삽입 이미지
반복적으로 실행되게 하기 위해서 Control에서 forever 블럭을 가져와 배치 합니다. forever는 보이는 모습과 같이 명령어들을 내부에 포함할 수 있으며, 이 포함된 블럭들은 반복적으로 실행됩니다. 

show는 해당 스프라이트를 출력하고 반대로 hide는 보이지 않게 만듭니다. 그리고 [wait (1) secs]는 1초동안 아무 동작을 하지않고 기다리게 만드는 명령어 입니다. 너무 빠르게 깜빡이지 않게 하기 위해서 show와 hide 명령어 사이에 각각 배치합니다. 최종적으로 완성된 블럭은 아래와 같습니다.

사용자 삽입 이미지

2) 테스트
사용자 삽입 이미지
이제 다시 깃발 버튼을 클릭하여 실행하면 좌측과 같이 캐릭터과 보였다 사라졌다를 반복하는 모습을 확인할 수 있습니다.

실행을 멈추기 위해서는 깃발 옆의 스톱 버튼을 클릭합니다.





3) 프로젝트 저장
이제 다음에도 이 프로젝트를 실행하거나 수정할 수 있도록 상단의 [save] 버튼을 클릭하여 저장합니다.

사용자 삽입 이미지

디렉토리를 선택하여 New Filenames항목에 프로젝트 이름을 입력합니다. 여기서는 'firstScratch'라고 입력하였습니다. Projec author에는 제작자의 이름을 입력하고 About this project에서 이 프로젝트에 관한 설명을 입력하고 하단의 [OK]를 클릭합니다.

한가지 유의하실 점은 아쉽게도 스크래치는 아직 한글을 지원하지 않으므로 영문으로 입력하셔야 합니다.
AND

사실 이 포스팅을 하는 이유는 책소개 보다 먼저 제 실수를 사과드릴려고 하는 것입니다. 이전 제 포스트에서 Beutiful Code란 책을 소개하면서 번역에 대한 문제점에 대해서 이야기 하였습니다.

문제가 된 부분은 inite automata를 "유한자동차"로 번역되었다고 한 부분입니다. 이는 제가 착각한 것으로 실제 책에는 "유한자동자"로 되어 있습니다. 제가 읽은 부분까지 두세번 나온 것 같은데 왜 모두 자동차로 읽었는지 모르겠습니다. (난독증 아니면 노안이 왔나 봅니다.) 제 무지와 실수로 잘못된 정보를 접한 그 포스트를 읽어 보신 분들과 역자분께 깊이 사과 드립니다.

역자분이 제 개인 일상을 올리는 블로그에 오셔서 남긴 댓글을 보고 뒤늦게 확인하게 되었습니다. 아래는 역자분이 남기 신 댓글입니다.

사용자 삽입 이미지

링크된 역자분의 홈페이지를 방문해 보니 다수의 관련서적 번역 경험을 가지고 계시고, 올바른 번역을 위하여 많은 노력을 하고 계신 것 같은데 제가 누를 끼친 것 같습니다. 다시 한번 모든 분들께 죄송하다는 말씀 드립니다.

이제 본론으로 들어 가겠습니다.

사용자 삽입 이미지
레이몬드 첸의 윈도우 개발 282 스토리

저자: Raymond Chen
역자: 손광수
출판사: ITC
정가: 24,000원


(이미지 출처: YES24)

작년 연말에 가볍게 읽어 볼 생각으로 Beautiful Code와 윈도우 개발 282 스토리란 책을 온라인으로 주문하였습니다. 사실 화장실이나 나들이 시에 가볍게 읽을 책인줄 알고 구입하였습니다. 그러나 과장하여 이야기 하면 하나는 알고리즘, 또 하나는 윈도우 시스템 프로그래밍에 관련된 책이 었습니다.

물론 가볍게 볼 수 있는 부분도 있지만 깊은 이해를 위해서는 두 책 모두 "뇌"를 많이 써야 했습니다. 두 책을 같이 보기엔 제 "뇌"의 스펙이 많이 딸리기 때문에 제 기준으로 보다 쉽고, 재미있는 윈도우 개발 282 스토리를 먼저 읽고 있습니다. 지금은 2/3정도 읽었습니다.

제목과 같이 "스토리"도 있지만 샘플코드들도 적지 않게 있습니다. Win api에 대한 지식이 조금은 있어야 보기가 편할 것 같습니다. 내용은 win16 부터 Vista까지 윈도우즈 개발에 관한 재밌는 에피소드와 이를 설명하고 증명하는 샘플소스로 되어 있습니다.

저자도 이야기 하지만 오래전(지금도 있는지는 잘 모르겠습니다.) 실제로 존재는 하지만 공식적으로는 존재하지 않는 Win API에 대한 책이 있었습니다.  저도 당시 그 책을 구입하여 "MS 개발자 지들끼리만 편리하게 쓸려고 만든 API 함수"들을 찾아 보았고, "편리"를 위해서 사용하기도 했습니다.

책을 읽으면서 이런 문서화 되지 않은 비공식 API를 사용하는 어플리케이션들 때문에 MS 개발자들이 노력(그 노력이 윈도우 OS 자체에 끼친 영향이 옳고 그름은 정확히 판단되지 않습니다.)을 많이 했다는 생각이 들었습니다. 이뿐만 아니라 대충 짐작은 하고 있었지만 하위 호환, 잘못된 하드웨어/소프트웨어를 수용하기 위한 많은 노력에 관한 에피소드들을 그 중심에 있었던 개발자에게 직접 들으니 매우 현실감 있고 재미있었습니다.

그 외에 "윈도우는 왜 그랬었어야만 했나"에 대한 많은 재미있는 이야기 들이 있습니다. 윈도우 개발자가 아니더라도 한 번은 읽어볼 만한 책이라고 생각합니다. 윈도우 개발자라면 반드시 읽어보라고 추천하고 싶습니다.

'책 이야기 > IT 일반' 카테고리의 다른 글

미래를 만든 Geeks  (1) 2010.06.24
번역서의 표지 디자인  (8) 2009.08.31
소프트웨어 크리에이티비티 2.0  (0) 2009.07.21
드리밍 인 코드  (2) 2009.05.20
스티브 워즈니악  (4) 2007.12.31
AND

MS윈도우에서 사용하는 PE와 유닉스의 ELF 포맷은 유명하지만 맥에서 사용하는 Mach-O 포맷은 상대적으로 덜 알려져 있는 것 같습니다. 그래서 OS X의 실행파일 포맷 중 헤더 부분에 대해서만 간단히 알아 보도록 하겠습니다.

실행 파일 헤더 구조라는 다소 무거운 제목과는 달리 간단히 구조만 알아 보고 몇가지 편리한 툴들을 살펴 볼려고 합니다. 상세한 자료가 필요하신 분들은 ADC에서 아래의 문서를 참조하시면 될 것 같습니다.

1. Mach-O & fat-binary

사용자 삽입 이미지
Mach 커널을 사용하는 OS X는 Mach-O란 실행파일 포맷을 사용합니다. Mach-O 파일 포맷은 좌측과 같이 되어 있습니다. (이미지는 ADC에서 가지고 왔습니다.)

Mach-O 파일은 헤더와 load commands, 세그먼트들로 구성된 데이터로 이루어져 있습니다.

load commands는 OS가 어플리케이션 실행시에 라이브러리를 올리는 등의 실행에 필요한 명령어들의 집합입니다.

헤더에 대한 상세한 내용은 툴 사용법과 함께 알아 보겠습니다.


fat-binary (멀티아키텍쳐 바이너리)
위의 구조는 한 아키텍쳐를 위한 단일 구조이며, OS X에서는 여러 아키텍쳐를 지원하는 유니버셜 바이너리를 위하여 fat이란 구조를 사용하고 있습니다.

사용자 삽입 이미지
fat은 하나의 실행파일이 여러 아키텍쳐에 적용될 수 있게 하기 위한 포맷입니다. 이는 OS X에서 PPC(PowerPC)와 x86 코드를 사용할 수 있게 하여줍니다. 우리가 흔히 유니버셜 바이너리(UB)라고 부르는 실행파일 포맷입니다.

좌측을 보면 위의 구조(thin)와는 달리 fat에 관련된 헤더들이 추가되었습니다. 각각의 Fat Architecture는 각각의 실행 코드를 가르키고 있으며, OS에서 로드시에 해당 아키텍쳐에 맞는 코드 블록(Mach-O 포멧)이 로딩됩니다.     




2. lipo
lipo는 OS X에서 유니버셜 바이너리를 관리하기 위한 툴입니다. lipo를 이용해서 유니버셜 실행 파일로 부터 한 아키텍쳐를 지원하는 실행파일을 추출을 할 수 있습니다.

사용자 삽입 이미지
웹브라우져인 오페라 실행파일로 테스트를 해보겠습니다. 실행파일은 해당 어플리케이션 디렉토리 (Opera.app)에서 Contents/MacOS/ 내에 있습니다.

터미널에서
> lipo -detailed_info ./Opera
를 실행하시면 좌측과 같은 fat과 지원하는 각 아키텍쳐들의 세부 정보를 확인할 수 있습니다.


오페라는 유니버셜 바이너리(fat)로 되어 있으며 위와 같이 nfat_arch(fat_arch 구조체 갯수)가 2이이므로 두개의 네이티브 코드를 가지고 있습니다. 그 아래의 메지시로 PPC와 i386(x86)을 지원한다는 것을 알 수 있습니다. 각각의 내용은 fat_arch 구조체의 내용입니다. fat_arch 구조체는 아래에서 확인해 보겠습니다.

이제 lipo의 "-thin" 옵션을 이용해서 PPC만 지원하는 실행파일을 추출하여 보겠습니다. 터미널에서 아래와 같이 lipo 명령을 실행합니다.

사용자 삽입 이미지

실행이 완료되면 위와 같이 Opera2란 파일로 ppc 네이티브 실행파일이 만들어져 있습니다. 파일 크기를 확인하시면 fat 헤더와 x86 코드가 빠져있기 때문에 거의 반으로 줄어 있습니다. 새로 생성한 PPC 파일을 Opera로 이름을 변경하고 GUI에서 확인해 보겠습니다.

사용자 삽입 이미지

좌측이 유니버셜 버젼이 적용된 원래 모습이며, 우측이 lipo를 이용하여 새로 만든 PPC로 적용시킨 후 확인해 본 모습니다. Universal에서 PowerPC로 변경되어 있습니다.

3. otool
otool은 실행파일(or obj, lib 등)의 정보를 보여주는 OS X에 내장된 툴입니다. OS X는 기존의 유닉스 계열과는 달리 "ldd"라는 공유라이브러리의 의존성을 검사하는 툴이 없습니다. otool은 ldd의 기능도 포함하고 있으니 OS X에서는 이를 사용하면 됩니다.

터미널에서 "otool"만 입력하시면 아래와 같이 간단한 사용방법을 보실 수 있습니다.

사용자 삽입 이미지

> otool -L ./Opera 로 오페라에서 사용하는 공유라이브러리 정보를 출력합니다. 위와 같이 오페라는 "카본 프레임워크"를 사용하고 있음을 알 수 있습니다.  또한 위의 lipo 보다 더 실행 파일의 다양한 헤더들과, load command등의 정보를 확인할 수 있습니다. (lipo는 유니버셜 바이너리 파일만 적용할 수 있습니다.)

4. OxED
사용자 삽입 이미지
0xED는 맥에서 바이너리 파일을 볼 수 있는 핵사 에디터입니다. 일반 텍스트 에디터에서 얻을 수 없는 바이너리 파일들의 정보를 얻을 수 있습니다.



아래는 0xED를 이용하여 오페라의 실행파일(유니버셜)을 열어 본 모습입니다.

사용자 삽입 이미지

헤더의 시작은 fat_heaer와 fat_arch로 이루어져 있습니다. 우선 /usr/include/mach-o/fat.h에서 이 구조체들을 확인해 보겠습니다.

#define FAT_MAGIC   0xcafebabe
#define FAT_CIGAM   0xbebafeca  /* NXSwapLong(FAT_MAGIC) */

struct fat_header {
    uint32_t    magic;      /* FAT_MAGIC */
    uint32_t    nfat_arch;  /* number of structs that follow */
};

struct fat_arch {
    cpu_type_t  cputype;    /* cpu specifier (int) */
    cpu_subtype_t   cpusubtype; /* machine specifier (int) */
    uint32_t    offset;     /* file offset to this object file */
    uint32_t    size;       /* size of this object file */
    uint32_t    align;      /* alignment as a power of 2 */
};

fat_header
첫번째 4바이트의 "CA FE BA BE"를 보시면 fat_headerd의 magic 값이며 소스에서 FAT_MAGIC 정의된 값입니다. 이는 실행파일이 fat 구조이며 유너버셜 바이너리라는 것을 알려 줍니다.

두번째 nfat_arch는 이 실행파일이 지원하는 아키텍쳐의 갯수이며 그 아래에 위치할 fat_arch 구조체의 갯수와도 동일합니다. 4바이트 int형으로 [00 00 00 02]로 2개의 아키텍쳐를 지원합니다.

fat_arch
지원하는 아키텍쳐의 정보를 담고 있는 구조체 입니다. 첫번째는 cpu의 종류를 나타내는 cputype입니다. 16진수 [00 00 00 12]로 10진수 18의 값을 가지고 있습니다. 두번째 fat_arch는 이 값이 [00 00 00 07]로  7의 값을 가지고 있습니다.

#define CPU_TYPE_POWERPC        ((cpu_type_t) 18)

#define CPU_TYPE_X86        ((cpu_type_t) 7)
#define CPU_TYPE_I386       CPU_TYPE_X86        /* compatibility */

이 값들은 /usr/include/mach/machine.h 파일에 아래와 같이 정의 되어 있습니다. 각각 PPC(18)와 x86(7) 아키텍쳐를 지원하고 있음을 알 수 있습니다.

다음은 lipo로 만든 PPC 실행파일을 열어 본 모습니다.
사용자 삽입 이미지

fat_ 과 관련된 구조체 없이 바로 mach_header가 위치합니다. 아래는 mach_header가 정의된 /usr/include/mach-o/loader.h 헤더파일의 일부입니다.

/*
 * The 32-bit mach header appears at the very beginning of the object file for
 * 32-bit architectures.
 */
struct mach_header {
    uint32_t    magic;      /* mach magic number identifier */
    cpu_type_t  cputype;    /* cpu specifier */
    cpu_subtype_t   cpusubtype; /* machine specifier */
    uint32_t    filetype;   /* type of file */
    uint32_t    ncmds;      /* number of load commands */
    uint32_t    sizeofcmds; /* the size of all the load commands */
    uint32_t    flags;      /* flags */
};

/* Constant for the magic field of the mach_header (32-bit architectures) */
#define MH_MAGIC    0xfeedface  /* the mach magic number */
#define MH_CIGAM    0xcefaedfe  /* NXSwapInt(MH_MAGIC) */

각각의 값들은 아래와 같습니다.

magic [FE ED FA CE]
Mach-O 포맷의 파일을 알려 주는 필드입니다. 이는 빅 엔디언을 사용하는 PPC 파일의 값이고 리틀 엔디언을 사용하는 x86을 지원하는 코드에서는 "CE FA ED FE"를 가지고 있습니다.

cputype [00 00 00 12]
12로 위와 동일하게 PPC를 지워합니다.

cpusubtype [00 00 00 00]
PPC subtype의 0은 CPU_SUBTYPE_POWERPC_ALL로 정의되어 있습니다.

filetype [00 00 00 02]
파일타입 2는 MH_EXECUTE로 정의 되어 있으며 실행파일을 의미합니다.

ncmsds [00 00 00 0B]
11개의 load command를 가지고 있음을 의미합니다.

sizeofcmds [00 00 08 CC]
load command의 크기로 2252byte입니다.

flags [00 00 00 85]
bit로 정의된 상세 정보입니다. 아래와 같은 세가지 bit가 세팅되어 있습니다.

#define MH_NOUNDEFS 0x1     /* the object file has no undefined
                       references */
#define MH_DYLDLINK 0x4     /* the object file is input for the
                       dynamic linker and can't be staticly
                       link edited again */
#define MH_TWOLEVEL 0x80        /* the image is using two-level name
                      space bindings */

cputype과 cpusubtype의 값에 대해서는 /usr/include/mach/machine.h 헤더파일을 그 외 정보들은  /usr/include/mach-o/loader.h에서 자세한 정보를 확인하실 수 있습니다.

딱 저의 궁금증 까지만 알아 보았습니다. 더 자료가 필요하신 분들은 위에 링크된 ADC 레퍼런스와 또 다른 문서인 Universal Binary Programming Guidelines가 도움이 되실 것입니다.

'기타' 카테고리의 다른 글

맥미니 분해 및 업그레이드  (4) 2008.03.14
가족과 함께 하기에 좋은 게임 Wormux  (2) 2008.02.29
프로그래밍 언어 인기 순위  (21) 2008.01.09
OS X APM 설치툴 - MAMP  (6) 2007.12.27
블로그 RSS 읽어오는 C++ class  (7) 2007.12.14
AND