공통 중간 언어

Common Intermediate Language

Common Intermediate Language(CIL;[1] 공통 중간 언어)는 Common Language Infrastructure(CLI; 공통 언어 인프라스트럭처) [2]사양 내에서 정의된 중간 언어 바이너리 명령 세트입니다.CIL 명령은 Common Language Runtime 등의 CLI 호환 런타임 환경에서 실행됩니다.CLI를 대상으로 하는 언어 CIL로 컴파일합니다.CIL은 객체 지향, 스택 기반 바이트 코드입니다.런타임은 보통 CIL 명령을 네이티브코드로 컴파일합니다.

CIL은 의 베타판 릴리즈에서는 Microsoft Intermediate Language(MSIL; 중간 언어)로 알려져 있었습니다.NET 언어C#과 CLI의 표준화에 의해 바이트 코드는 공식적으로 CIL로 [3]불리게 되었습니다.Windows Defender 바이러스 정의는 MSIL로 [4]컴파일된 바이너리를 계속 참조합니다.

일반 정보

CLI 프로그래밍 언어를 컴파일할 때 소스 코드는 플랫폼 고유 또는 프로세서 고유 오브젝트 코드가 아닌 CIL 코드로 변환됩니다.CIL은 CPU 및 플랫폼에 의존하지 않는 명령어세트로, 등 공통 언어 인프라스트럭처를 지원하는 모든 환경에서 실행할 수 있습니다.WindowsNET 런타임 또는 크로스 플랫폼 Mono 런타임.이를 통해 이론적으로 플랫폼 및 CPU 유형에 따라 서로 다른 실행 파일을 배포할 필요가 없어집니다.CIL 코드는 실행 시 안전성을 검증하여 기본적으로 컴파일된 실행 파일보다 뛰어난 [5][6]보안과 신뢰성을 제공합니다.

실행 프로세스는 다음과 같습니다.

  1. 소스 코드가 CIL 바이트 코드로 변환되어 CLI 어셈블리가 생성됩니다.
  2. CIL 어셈블리의 실행 시 해당 코드는 런타임의 JIT 컴파일러를 통해 네이티브 코드를 생성합니다.사전 컴파일을 사용할 수도 있습니다.이 때문에, 이 순서는 불필요하게 됩니다만, 실행 파일의 이식성을 희생합니다.
  3. 컴퓨터의 프로세서가 네이티브 코드를 실행합니다.

지침들

CIL 바이트 코드에는 다음 작업 그룹에 대한 명령이 있습니다.

계산 모델

Common Intermediate Language는 객체 지향적이고 스택 기반입니다.이는 명령 파라미터와 결과가 대부분의 프로그래밍 언어에서와 같이 여러 레지스터나 다른 메모리 위치 대신 단일 스택에 유지된다는 것을 의미합니다.

x86 어셈블리 언어로 두 개의 숫자를 추가하는 코드. eax 및 edx는 두 개의 다른 범용 레지스터를 지정합니다.

더하다 이액스, 엣지 

중간 언어(IL)의 코드(0은 eax, 1은 edx):

ldoc.0    // 로컬 변수 0을 스택에 푸시합니다. ldoc.1    // 로컬 변수 1을 스택에 푸시합니다. 더하다        // 상위 2개의 스택 항목을 팝업하여 추가한 후 결과를 스택에 푸시합니다. 스택.0    // 상위 스택 항목을 로컬 변수 0에 팝업하여 저장합니다. 

후자의 예에서는, eax 와 edx 의 2 개의 레지스터의 값이 최초로 스택에 푸시 됩니다.add-instruction이 호출되면 오퍼랜드가 "팝"되거나 검색되고 그 결과는 스택에 "푸시"되거나 저장됩니다.그런 다음 결과 값이 스택에서 팝되어 eax에 저장됩니다.

객체 지향 개념

CIL은 객체 지향으로 설계되어 있습니다.오브젝트, 콜 방식 및 필드 등 다른 유형의 멤버를 사용할 수 있습니다.

모든 메서드는 (일부 예외는 있지만) 클래스에 있어야 합니다.이 스태틱 방식도 마찬가지입니다.

.학급 일반의 푸우 {     .방법 일반의 정적인 int32 더하다(int32, int32) 카일 관리되는. {         .최대 스택 2         ldarg.0 // 첫 번째 인수를 로드합니다.         ldarg.1 // 두 번째 인수를 로드합니다.         더하다     // 추가;         리트     // 결과를 반환합니다.     } } 

Add 메서드에서는 Foo 인스턴스가 static으로 선언되어 C#에서 다음과 같이 사용될 수 있으므로 Foo 인스턴스를 선언할 필요가 없습니다.

인트 r = 푸우.더하다(2, 3);    // 5 

CIL에서는 다음과 같습니다.

ldc.i4.2 ldc.i4.3 불러 int32 푸우::더하다(int32, int32) 스택.0 

인스턴스 클래스

인스턴스 클래스에는 하나 이상의 생성자와 일부 인스턴스 멤버가 포함됩니다.다음 클래스에는 Car 객체의 동작을 나타내는 메서드 집합이 있습니다.

.학급 일반의  {     .방법 일반의 특별한 이름 rtspecial name(특정명) 사례 무효 .모니터(int32, int32) 카일 관리되는. {         /* 컨스트럭터 */     }      .방법 일반의 무효 이동(int32) 카일 관리되는. { /* 구현 생략 */ }     .방법 일반의 무효 우측으로 도세요() 카일 관리되는. { /* 구현 생략 */ }     .방법 일반의 무효 좌회전() 카일 관리되는. { /* 구현 생략 */ }     .방법 일반의 무효 브레이크() 카일 관리되는. { /* 구현 생략 */ } } 

오브젝트 작성

C# 클래스의 인스턴스는 다음과 같이 작성됩니다.

 마이카 = 신규 (1, 4);   당신의 차 = 신규 (1, 3); 

이러한 문장은 CIL의 다음 설명과 거의 동일합니다.

ldc.i4.1 ldc.i4.4 새로운 사례 무효 ::.모니터(인트, 인트) 스택.0    // myCar = 신차(1, 4); ldc.i4.1 ldc.i4.3 새로운 사례 무효 ::.모니터(인트, 인트) 스택.1    // 귀하의 차 = 새 차(1, 3); 

인스턴스 메서드를 호출하는 중

인스턴스 메서드는 다음과 같이 C#에서 호출됩니다.

마이카.이동(3); 

CIL에서 호출된 대로:

ldoc.0    // "myCar" 개체를 스택에 로드합니다. ldc.i4.3 불러 사례 무효 ::이동(int32) 

메타데이터

Common Language Infrastructure(CLI)는 컴파일된 클래스에 대한 정보를 메타데이터로 기록합니다.Component Object Model의 유형 라이브러리와 마찬가지로 이를 통해 응용 프로그램은 어셈블리의 인터페이스, 클래스, 유형, 메서드 및 필드를 지원하고 검색할 수 있습니다.이러한 메타데이터를 읽는 프로세스를 "반사"라고 합니다.

메타데이터는 "속성" 형식의 데이터일 수 있습니다.속성을 커스터마이즈하려면Attribute클래스. 이건 강력한 기능입니다.이를 통해 클래스 작성자는 애플리케이션 도메인에 따라 클래스 소비자가 다양한 의미 있는 방법으로 사용할 수 있는 추가 정보로 클래스를 꾸밀 수 있습니다.

아래는 CIL 어셈블러로 작성된 기본적인 Hello, World 프로그램입니다."Hello, world!"라는 문자열이 표시됩니다.

.조립품 안녕 {} .조립품 외부 mscorlib {} .방법 정적인 무효 주된() {     .진입점     .최대 스택 1     ldstr "안녕, 세상아!"     불러 무효 [mscorlib]시스템..콘솔::기입선(스트링)     리트 } 

다음 코드는 연산 코드 수가 더 복잡합니다.

이 코드는 Java 바이트 코드에 대한 기사의 해당 코드와 비교할 수도 있습니다.

정적인 무효 주된(스트링[] args) {     위해서 (인트 i = 2; i < > 1000; i++)     {         위해서 (인트 j = 2; j < > i; j++)         {              한다면 (i % j == 0)                  에 가다 바깥의;         }         콘솔.기입선(i);         바깥의:;     } } 

CIL 어셈블러 구문에서는 다음과 같습니다.

.방법 사적인 숨김 정적인 무효 주된(스트링[] args) 카일 관리되는. {     .진입점     .최대 스택  2     .현지인 초기화 (int32 V_0,                   int32 V_1)                ldc.i4.2               스택.0               br.s       IL_001f     IL_0004:  ldc.i4.2               스택.1               br.s       IL_0011     IL_0008:  ldoc.0               ldoc.1               기억하다               거짓.s  IL_001b               ldoc.1               ldc.i4.1               더하다               스택.1     IL_0011:  ldoc.1               ldoc.0               하지 않다.s      IL_0008               ldoc.0               불러       무효 [mscorlib]시스템..콘솔::기입선(int32)     IL_001b:  ldoc.0               ldc.i4.1               더하다               스택.0     IL_001f:  ldoc.0               ldc.i4     0x3e8               하지 않다.s      IL_0004               리트 } 

이는 CIL이 가상 머신(VM) 레벨에 근접한 모습을 나타낸 것입니다.컴파일 시 메서드는 테이블에 저장되며 명령어는 PE(Portable Executable)인 어셈블리 내부에 바이트로 저장됩니다.

시대

CIL 어셈블리와 명령은 실행 환경과 함께 제공되는 컴파일러 또는 IL Assembler(ILASm)라는 유틸리티에 의해 생성됩니다.

조립된 CIL은 IL 분해 장치(ILDASM)를 사용하여 다시 코드로 분해할 수도 있습니다.등의 다른 툴이 있습니다.CIL을 고급 언어(C# 또는 Visual Basic 등)로 디컴파일할 수 있는 NET 리플렉터.이를 통해 CIL은 리버스 엔지니어링의 매우 쉬운 타깃이 됩니다.이 특성은 Java 바이트코드와 공유됩니다.그러나 코드를 난독화할 수 있는 툴이 있어 코드를 쉽게 읽을 수 없지만 실행할 수 있습니다.

실행

적시 컴파일

JIT(Just-in-Time Compilation)에서는 바이트 코드를 CPU에 의해 즉시 실행 가능한 코드로 변환합니다.변환은 프로그램 실행 중에 점진적으로 수행됩니다.JIT 컴파일은 환경 고유의 최적화, 런타임 유형의 안전성 및 어셈블리 검증을 제공합니다.이를 위해 JIT 컴파일러는 어셈블리 메타데이터에서 부정 액세스 여부를 검사하고 위반을 적절하게 처리합니다.

사전 컴파일

CLI 호환 실행 환경에는 어셈블리의 사전 컴파일(AOT)을 실행하여 런타임에 JIT 프로세스를 제거함으로써 어셈블리를 보다 빠르게 실행할 수 있는 옵션도 포함되어 있습니다.

에서.NET Framework에는 AOT를 수행하는 Native Image Generator(NGEN)라는 특수 도구가 있습니다.AOT의 다른 접근방식은 코어입니다.컴파일을 가능하게 하는 RT.Net Core 코드는 런타임에 의존하지 않는 단일 실행 파일에 할당됩니다.모노에서는 AOT를 실행하는 옵션도 있습니다.

포인터 명령 - C++/CLI

Java의 바이트 코드와 눈에 띄는 차이점은 CIL이 ldind, stind, ldloca 및 C/C++ 코드를 CIL로 컴파일하는 데 필요한 데이터/함수 포인터 조작에 충분한 많은 호출 명령을 가지고 있다는 것입니다.

학급 A {    일반의: 가상 무효 __stdcall 메트() {} }; 무효 test_module_operations(인트 PARAM.) {  인트 k = 0;  인트 * ptr = &k;  *ptr = 1;  ptr = &PARAM.;  *ptr = 2;  A a;  A * ptra = &a;  ptra->메트(); } 

CIL 의 대응하는 코드는, 다음과 같이 렌더링 할 수 있습니다.

.방법 조립품 정적인 무효 모뎀([mscorlib]시스템..런타임.컴파일러 서비스.CallConvCdecl)          test_module_operations(int32 PARAM.) 카일 관리되는. {   .엔트리 1 : 1   // 코드 사이즈 44 (0x2c)   .최대 스택  2   .현지인 ([0] int32* ptr,            [1] 밸류 타입 A* V_1,            [2] 밸류 타입 A* a,            [3] int32 k) // k = 0;   IL_0000:  ldc.i4.0    IL_0001:  스택.3 // ptr = &k;   IL_0002:  ldoca.s   k // 로컬 주소 명령 로드   IL_0004:  스택.0 // * ptr = 1;   IL_0005:  ldoc.0   IL_0006:  ldc.i4.1   IL_0007:  스텐드.i4 // 간접 명령 // ptr = &quot;&quot;   IL_0008:  ldarga.s   PARAM. // 로드 파라미터의 주소 명령   IL_000a:  스택.0 // * ptr = 2   IL_000b:  ldoc.0   IL_000c:  ldc.i4.2   IL_000d:  스텐드.i4 // a = 새로운 A;   IL_000e:  ldoca.s   a   IL_0010:  불러       밸류 타입 A* 모뎀([mscorlib]시스템..런타임.컴파일러 서비스.Call ConvThiscall(디스콜)) 'A.{모니터}'(밸류 타입 A* 모뎀([mscorlib]시스템..런타임.컴파일러 서비스.IsConst) 모뎀([mscorlib]시스템..런타임.컴파일러 서비스.IsConst))   IL_0015:   // ptra = &a;   IL_0016:  ldoca.s   a   IL_0018:  스택.1 // ptra-> method();   IL_0019:  ldoc.1   IL_001a:  이중   IL_001b:  바인드.i4 // 가상 콜용 VMT 읽기   IL_001c:  바인드.i4   IL_001d:  캘리      관리되지 않다 스택 무효 모뎀([mscorlib]시스템..런타임.컴파일러 서비스.Call Conv Stdcall)(원어민 인트)   IL_0022:  리트 } // '글로벌 함수' 메서드의 끝::test_pointers_operations 

「 」를 참조해 주세요.

레퍼런스

  1. ^ "Intermediate Language & execution".
  2. ^ "ECMA-335 Common Language Infrastructure (CLI)" (PDF). p. 32.
  3. ^ "What is Intermediate Language(IL)/MSIL/CIL in .NET". Retrieved 2011-02-17. CIL: ... When we compile [a]. NET project, it [is] not directly converted to binary code but to the intermediate language. When a project is run, every language of .NET programming is converted into binary code into CIL. Only some part of CIL that is required at run time is converted into binary code. DLL and EXE of .NET are also in CIL form.
  4. ^ "HackTool:MSIL/SkypeCracker". Microsoft. Retrieved 26 November 2019.
  5. ^ Troelsen, Andrew (2009-05-02). Benefits of CIL. ISBN 9781590598849. Retrieved 2011-02-17.
  6. ^ "Unmanaged, Managed Extensions for C++, Managed and .Net Framework". www.visualcplusdotnet.com. Retrieved 2020-07-07.

추가 정보

외부 링크