C C++Java C#JSコンパイル、実行プロセスの原理入門分析

9020 ワード

C、C++は典型的なコンパイル型プログラミング言語であり、リンクをコンパイルした後、クリックすると実行できる.
JS,解釈型スクリプト言語は,コンパイルを必要とせず,直接解釈実行する.
JavaとC#はいわゆる高度な言語で、コンパイル実行の方式は多くの処理をしました.
特にC#,VSコンパイル後に生成されるexeファイルはマシンコードではなく,多くのプログラマーに誤解される.
 
以下、筆者は自分の理解と調べた資料を皆さんと共有します.漏れがあったら、皆さんに指摘して、一緒に勉強してください.
 
1、C、C++
C、C++は典型的なコンパイル型プログラミング言語であり、リンクをコンパイルした後、クリックすると実行できる.
C、C++コンパイル実行の原理も比較的簡単で、直接ソースコードがコンパイルリンクを経た後、マシンコードからなる実行可能ファイルを生成し、直接OSからLoadロード実行を行う.マシンコードはハードウェアの命令に対応しているので、直接クリックして実行することができます.
 
2、JS
JS,解釈型スクリプト言語は,コンパイルを必要とせず,直接解釈実行する.
 
3、Java
.java->コンパイル->class、Javaソースコードのコンパイル後、.classファイルを生成します..classはjvm解釈で実行する必要があります.一部の.classファイルもJIT技術で直接マシン言語を生成し、実行効率を高めます.
Javaという言語は特殊です.コンパイル型だと言えますすべてのJavaコードはコンパイルされるので、.javaはコンパイルされずに何の役にも立たない.それは解釈型だと言えます.Javaコードのコンパイル後は直接実行できないため、JVM上で実行されていることを説明しているので、実行を説明しているので、それは説明してもいいです.現在のJVMは効率のためにいくつかのJIT最適化があります.また.classのバイナリコードをローカルのコードにコンパイルして直接実行するので、コンパイルされます.
 
4、C#
C#のコンパイル実行手順は次のとおりです.
(1)C#=>C#コンパイラ=>IL(中間コード)
(2)IL=>JIT=>Native Code(ターゲットプログラム)(3)入力=>ターゲットプログラム=>出力.C#は全部で2回コンパイルされ、2回目は実行時、つまりexeファイルをクリックした後に発生します.
 
HelloWorldプログラムを例に、exeファイルの本質と実行原理を説明します.
 
HelloWorld.cs
//HelloWorld.cs by Cornfield,2001
//csc HelloWorld.cs
using System;
class HelloWorld
{
   public static void Main()
   {
     Console.WriteLine("Hello World !");
   }
}

 
指摘しなければならないのは、私たちは一般的にC#を使ってHelloWorldのexeファイルを生成しますが、実際には、内部に保存されているのは機械が解読できるマシンコードではありません.接尾辞名exeにだまされないでください.
 
 コンパイル出力のHelloWorld.exeは、中間言語(IL)、メタデータ(Metadata)、およびコンパイラによって追加された追加のターゲットプラットフォームの標準実行可能ファイルヘッダ(例えば、Win 32プラットフォームは、標準Win 32実行可能ファイルヘッダを追加したもの)からなるPE(portable)である executable、移植可能な実行体)ファイルは、従来のバイナリ実行可能ファイルではありません.同じ拡張子を持っていますが.
 
中間言語はCPUとは独立した命令セットであり、インスタントコンパイラJitterによってターゲットプラットフォームのローカルコードに翻訳することができる.中間言語コードは、すべてのMicrosoft.NETプラットフォームの高度な言語C#、VB.NET、VC.NETなどをプラットフォームから独立させ、言語間で相互運用を実現します.メタデータは、PEファイルに埋め込まれたテーブルの集合です.メタデータには、コード内のデータ型など、いくつかの共通言語の実行時(Common)が記述されています. Language Runtime)コード実行時に知る情報が必要です.メタデータにより、.NETアプリケーションコードは自己記述機能を備え、以前は追加のタイプライブラリまたはインタフェース定義言語(Interface)が必要だったタイプセキュリティ保障を提供します. Definition Language、略称IDL). 
このような解釈はまだ少し困惑しているかもしれませんが、実際にこのPEファイルを解剖してみましょう.私たちが採用しているツールは.NETです. SDK Beta 2は、PEファイルの関連データを抽出するのに役立つildasm.exeを持っています.コマンド「ildasm」を入力します /output:HelloWorld.il HelloWorld.exe」は、一般的にhelloworld.ilとhelloworld.resの2つの出力ファイルを得ることができます.後者は抽出されたリソースファイルであり、私たちはともかくhelloworld.ilファイルを見てみましょう.「メモ帳」プログラムで開くと、メタデータと中間言語(IL)コードが表示されます.紙面関係のため、その中の中間言語コードだけを抽出して以下に列挙します.メタデータに関する表項目はしばらく話しません.
 
//  Microsoft (R) .NET Framework IL Disassembler.  Version 1.1.4322.573
//  Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.

.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 1:0:5000:0
}
.assembly Class2
{
  // ---             ,       -------
  //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
  //                                                                                bool) = ( 01 00 00 01 00 00 ) 
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module Class2.exe
// MVID: {A9D4A2DC-A401-4F5F-B16F-B3D40F584E59}
.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000001
// Image base: 0x070c0000
//
// ============== CLASS STRUCTURE DECLARATION ==================
//
.class public auto ansi beforefieldinit Test
       extends [mscorlib]System.Object
{
} // end of class Test

// =============================================================
// =============== GLOBAL FIELDS AND METHODS ===================
// =============================================================
// =============== CLASS MEMBERS DECLARATION ===================
//   note that class flags, 'extends' and 'implements' clauses
//          are provided here for information only

.class public auto ansi beforefieldinit Test
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    //            72 (0x48)
    .maxstack  4
    .locals init (int32[] V_0,
             int32 V_1,
             int32 V_2)
    IL_0000:  ldc.i4.5
    IL_0001:  newarr     [mscorlib]System.Int32
    IL_0006:  stloc.0
    IL_0007:  ldc.i4.0
    IL_0008:  stloc.1
    IL_0009:  br.s       IL_0015

    IL_000b:  ldloc.0
    IL_000c:  ldloc.1
    IL_000d:  ldloc.1
    IL_000e:  ldloc.1
    IL_000f:  mul
    IL_0010:  stelem.i4
    IL_0011:  ldloc.1
    IL_0012:  ldc.i4.1
    IL_0013:  add
    IL_0014:  stloc.1
    IL_0015:  ldloc.1
    IL_0016:  ldloc.0
    IL_0017:  ldlen
    IL_0018:  conv.i4
    IL_0019:  blt.s      IL_000b

    IL_001b:  ldc.i4.0
    IL_001c:  stloc.2
    IL_001d:  br.s       IL_003b

    IL_001f:  ldstr      "arr[{0}]={1}"
    IL_0024:  ldloc.2
    IL_0025:  box        [mscorlib]System.Int32
    IL_002a:  ldloc.0
    IL_002b:  ldloc.2
    IL_002c:  ldelem.i4
    IL_002d:  box        [mscorlib]System.Int32
    IL_0032:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                  object,
                                                                  object)
    IL_0037:  ldloc.2
    IL_0038:  ldc.i4.1
    IL_0039:  add
    IL_003a:  stloc.2
    IL_003b:  ldloc.2
    IL_003c:  ldloc.0
    IL_003d:  ldlen
    IL_003e:  conv.i4
    IL_003f:  blt.s      IL_001f

    IL_0041:  call       int32 [mscorlib]System.Console::Read()
    IL_0046:  pop
    IL_0047:  ret
  } // end of method Test::Main

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

} // end of class Test

// =============================================================
//***********       ***********************
// WARNING: Created Win32 resource file Class2.res

  
以前のアセンブリ言語に似ていますが、オブジェクトの定義と操作の機能があります.System.Objectから継承された定義と実装が見られます のHelloWorldクラスと2つの関数:Main()と.ctor()です.ここで.ctor()はHelloWorldクラスのコンストラクション関数ですが、「HelloWorld.cs」ソースコードではコンストラクション関数を定義していません.はい、コンストラクション関数を定義していませんが、C#のコンパイラが追加してくれました.C#コンパイラもHelloWorldクラスにSystem.Objectクラスを継承するように強制しているのを見ることができますが、これも指定されていません.
一般的なC#/.NETアプリケーションの実行手順を見てみましょう.
ではPEファイルはどのように実行されますか?以下は、(1)ユーザがコンパイラ出力を実行するアプリケーション(PEファイル)、オペレーティングシステムがPEファイルをロードするアプリケーション、および他のDLL(.NETダイナミック接続ライブラリ)の典型的なC#/.NETアプリケーションの実行プロセスである. (2)オペレーティングシステムローダは、前のPEファイルの実行可能ファイルヘッダに従ってプログラムのエントリポイントにジャンプする.明らかに、オペレーティングシステムは中間言語を実行することができず、このエントリポイントもmscoree.dll(.NETプラットフォームのコアサポートDLL)にジャンプするように設計されています. CorExeMain()関数エントリ. (3)CorExeMain()関数はPEファイルの中間言語コードの実行を開始する.ここでの実行とは、汎用言語の実行時に呼び出されたオブジェクトメソッド単位で、中間言語をインスタントコンパイラJITでローカルマシンバイナリコードにコンパイルし、実行し、必要に応じてマシンキャッシュに保存することを意味する. プログラムの実行中、ゴミ収集器はメモリの割り当て、解放などの管理機能を担当します. プログラムの実行が完了し、オペレーティングシステムがアプリケーションをアンインストールします.
 
とにかく、運行中 Microsoft ちゅうかんげんご (MSIL) 以前は、VSコンパイル後に生成されたexeファイルを使用して、共通言語実行ライブラリに基づいてターゲットコンピュータアーキテクチャに適したネイティブコードにコンパイルする必要がありました.
 
C#ILをマシンコードに変換する2つの方法と違い:
.NET Framework このような変換を実行するには、.NETの2つの方法があります. Framework リアルタイム (JIT) コンパイラと .NET Framework ネイティブイメージジェネレータ (Ngen.exe).
 
JIT方式:コンパイラがダイナミックメモリにローカルコードを保存しているため、プログラムを閉じるとローカルコードが失われます.JITコンパイラは、プログラムを再起動したり、同時にプログラムを実行したりする2つのインスタンスについて、ILコードをローカルコマンドに再コンパイルします.
Ngen方式:共通言語実行ライブラリは事前コンパイルモードをサポートする.このプリコンパイルモードでは、ネイティブイメージジェネレータを使用します. (Ngen.exe) 将 MSIL プログラムセットはネイティブコードに変換され、その役割は JIT コンパイラは極めて似ている.
Ngen.exe の操作と JIT コンパイラの操作には3つの違いがあります.
(1)実行中ではなくアプリケーションが実行される前に実行される MSIL ネイティブコードへの変換.
(2)メソッドを一度にコンパイルするのではなく、プログラムセット全体を一度にコンパイルします.
(3)ネイティブイメージキャッシュで生成されたコードをファイル形式でディスクに永続的に保存します.
 
参照:
http://bbs.csdn.net/topics/300168333
http://bbs.csdn.net/topics/390347820?page=1#post-395721998
http://bbs.csdn.net/topics/320240834