아주 간단한 소스코드를 빌드를 하고
IL DASM로 불러들였습니다.

namespace insideCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("OTZ");
        }
    }
}


정말 간단한 소스네요....

이걸 IL DASM으로 불러들이면


이렇게 보입니다.
여기서 두번째 줄에 있는 MANIFEST를 더블클릭하면 어셈블리 정보를 설명하는
메타데이터 정보를 볼수가 있어요

// Metadata version: v2.0.50727
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 2:0:0:0
}
.assembly insideCSharp
{
  .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0C 69 6E 73 69 64 65 43 53 68 61 72 70 00   // ...insideCSharp.
                                                                                              00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 0C 42 6C 61 63 6B 45 64 69 74 69 6F 6E 00   // ...BlackEdition.
                                                                                                00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0C 69 6E 73 69 64 65 43 53 68 61 72 70 00   // ...insideCSharp.
                                                                                                00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 1E 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ...Copyright ..
                                                                                                  42 6C 61 63 6B 45 64 69 74 69 6F 6E 20 32 30 30   // BlackEdition 200
                                                                                                  39 00 00 )                                        // 9..
  .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 64 63 37 31 35 34 62 61 2D 30 30 65 34   // ..$dc7154ba-00e4
                                                                                                  2D 34 33 62 31 2D 61 30 30 61 2D 34 36 62 32 61   // -43b1-a00a-46b2a
                                                                                                  35 62 37 64 32 33 36 00 00 )                      // 5b7d236..
  .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..

  // --- 다음 사용자 지정 특성이 자동으로 추가됩니다. 주석 처리를 제거하지 마십시오. -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )

  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 1:0:0:0
}
.module insideCSharp.exe
// MVID: {8A57E23A-CCB3-4592-9075-A79E5D701B7F}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x03F60000

참 기네요..
이걸 처음봤을때는(지금도 물론) 눈앞이 캄캄하네요....
가뜩이나 가로로 쭉쭉 늘어선 글을 붙여넣으니 당췌 뭐가뭔지 모르겠네요...

여기서 첫번째 블럭은 외부어셈블리를 참조하는데 사용되는 .assembly 레코드입니다.

어셈블리의 가장 큰 장점중 하나는 버전관리가 가능하다는 것... 이라고 하는데요. 아직 저에게는 그다지 와닿지 않는 내용입니다. --ㅋ
제가 컴파일한 insideCSharp  어셈블리는 mscorlib 어셈블리의 2.0.0.0 버전을 사용하고 있다네요.

두번째 블럭은 이 어셈블리에 대한 정보를 포함하고 있습니다.
책에서 본 바로는 명시적으로 빌드 프로세스중에 버전 넘버를 지정하지 않으면 0.0.0.0 이라고 하는데
왜 저는 1.0.0.0 인걸까요.........

책이 version 2003이니.. 바뀐걸수도 있겠고. 제가 모르는 무언가가 있는지도 모르겠네요... ㅠ
위에 노란블럭안을 보면 몇가지 어트리뷰트가 나와 있는데요.
위의 어트리뷰트에 대한 내용들은 공부가 더 진행된후에 다시 언급하도록 할께요.
(그나저나 책에서는 Debug쪽 어트리뷰트만 나오더니. 제꺼에서는 상당히 많은 어트리뷰트가 보이는군요....
 책과 다르면 매우 난감한데요....)

다음으로는 클래스의 생성자를 볼께요. (6번째줄의 .ctor : void() 를 더블클릭하면 나와요)

.method public hidebysig specialname rtspecialname
        instance void  .ctor() cil managed
{
  // 코드 크기       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  ret
} // end of method Program::.ctor

첫째줄에서 두번째줄까지는 단순히 메소드가 public이고, specialname, rtspecialname 어트리뷰트의 특징을 나타냅니다.
이러한 특정 메서드에 대한 코드는 CLI(Common Language Infrastructure)에 대한 의미를 가지고 있다고 하네요.
cil managed 어트리뷰트는 managed 메서드라는 걸 의미합니다.

메소드는 처음으로 Idarg라는 opcode를 통해 인자를 스택으로 로드합니다.
Idarg 다음의 '0'은 첫번째 인수를 뜻합니다.
두번째 call 이라는 opcode는 System.Object를 호출하는데 사용됩니다.
마지막 ret opcode는 단순히 호출메소드로 컨트롤을 반환한다고 하네요.
(코드는 쉬운데. 이놈은 어렵네요....)

이번에는 Main 메소드가 어떻게 생겼는지 볼죠..

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 코드 크기       13 (0xd)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "OTZ"
  IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000b:  nop
  IL_000c:  ret
} // end of method Program::Main
위에서 한번 보고 나니.
조금 눈에 들어오네요

하지만 책과 또 다른!!!!
IL_0000과 000b의 nop은 뭐하는 녀석일까요...

나머지 녀석들은 위랑 비슷한데 말이죠..
Idstr은 문자열 OTZ를 스택에올려주고.
call을 사용해서 System.Console::WriteLine을 불러냅니다.

문자로된 문자열을 넘겨도. 이 값은 실제로는 System.String 클래스의 인스턴스입니다.(문자니깐요)



IL DASM으로 내부정보를 보면
개발자가 알아야할 지식을 갖추는데도 도움이 되고
개발 생산성도 높일수 있을것이라고 하니(책에서... 실제로는 어떨지 아직 모르겠군요.. 도움이 되긴 하겠죠..)
앞으로 이 녀석과 친해질수 있도록 많이 노력해야 겠네요..
by 피요히코~ 2009. 4. 24. 00:17