Heim  >  Artikel  >  Backend-Entwicklung  >  CLR (Common Language Runtime) und IL (Intermediate Code) in C#

CLR (Common Language Runtime) und IL (Intermediate Code) in C#

黄舟
黄舟Original
2017-02-07 15:44:011911Durchsuche

CLR in der .net-Plattform

Zunächst ist zu beachten, dass die .NET-Plattform nicht dasselbe ist wie C#. Es ist die Plattform, auf der Programme wie C# und VB.net laufen .

CLR ist die Common Language Runtime und ein wichtiger Bestandteil des .NET Frameworks. Es bietet Dienste wie Speicherverwaltung, Thread-Verwaltung und Ausnahmebehandlung und ist außerdem für die Implementierung strenger Typsicherheitsprüfungen des Codes verantwortlich, um die Korrektheit des Codes sicherzustellen.

Tatsächlich werden viele Funktionen in C# wie Typsicherheit (Type Checker), Garbage Collection (Garbage Collector), Ausnahmebehandlung (Exception Manager), Abwärtskompatibilität (COM Marshaler) usw. von der CLR bereitgestellt .

Was ist IL

.NET Framework ist eine virtuelle Laufplattform, die auf der Windows-Plattform basiert. Sie können sich vorstellen, die unterste Ebene von Windows durch andere Betriebssysteme wie Linux zu ersetzen Es ist möglich, eine .NET-Sprache zu verwenden, die CLS (Common Language Specification, Common Language Specification) entspricht. Dies ist tatsächlich die Funktion, die Mono erreichen möchte. Daher ist C# theoretisch eine plattformübergreifende Sprache.

Eine weitere Sache, die C# eher zu Java macht, ist, dass es auch eine Sprache ist (in einem besonderen Sinne wird der in C# geschriebene Programmcode zunächst vom C#-Compiler in ein Sonderzeichen kompiliert). Code, (Microsoft Intermediate Language, MSIL, Microsoft) Zwischensprache, wird von einem bestimmten Compiler (JIT-Compiler, Just In tIME, JITer) zur Laufzeit zur Ausführung durch das Betriebssystem in Maschinencode kompiliert.

IL ist eine Zwischensprache. Die Compiler verschiedener Hochsprachen (wie C#, VB, F#) auf der .NET-Plattform konvertieren ihre jeweiligen Textausdrücke in IL. Verschiedene Textformen wurden schließlich im IL-Ausdruck vereinheitlicht

Nachdem CLR IL geladen hat, wird JIT verwendet, um den IL-Code in Maschinencode zu kompilieren und tatsächlich zu assemblieren Es gibt eine Eins-zu-eins-Entsprechung. Dies kann folgendermaßen verstanden werden: Assembly ist die Textdarstellung von Maschinencode und bietet einige „Mnemoniken“, die sich die Leute leicht merken können.

Für dieselbe IL generiert JIT unterschiedliche Maschinencodes für unterschiedliche CPU-Architekturen (z. B. x86/IA64 usw.).

C#-Code und der entsprechende IL-Zwischencode

CLR (Common Language Runtime) und IL (Intermediate Code) in C#

//hidebysig指令表示如果当前类为父类,用该指令标记的方法将不会被子类继承
//cil managed表明方法体中的代码是IL代码,且是托管代码,即运行在CLR运行库上的代码
.method private hidebysig static void Main(string[] args)cil managed
{
    .entrypoint //该指令代表该函数程序的入口函数。每一个托管应用程序都有且只有一个入口函数,CLR加载程序时,首先从.entrypoint函数开始执行。
    .maxstack 2 //执行构造函数时,评估堆栈可容纳数据项的最大个数。评估堆栈是保存方法中所需要变量的值的一个内存区域,该区域在方法执行结束时会被清空,
    或者存储一个返回值。
    .locals init (
        [0] int32 num,
        [1] int32 num2,
        [2] int32 num3) //表示定义int类型的变量,变量名分别为num,num2,num3。存储在调用栈。
    L_0000: nop  //No operation的意思,即没有任何操作。
    L_0001: ldc.i4.1  //将“1”压入评估栈,此时“1”处于评估栈的栈顶。
    L_0002: stloc.0  //此指令表示把值从评估栈中弹出,并赋值给调用栈的第0个变量num。
    L_0003: ldc.i4.2
    L_0004: stloc.1
    L_0005: ldc.i4.3
    L_0006: stloc.2 //从.locals init到L_0006,相当于C#代码的为i,j,k赋值。
    L_0007: ldloc.0  //取调用栈中位置为0的元素压入评估栈(取i的值)。
    L_0008: ldloc.1  //取调用栈中位置为1的元素压入评估栈(取j的值)。
    L_0009: add  //做加法操作
    L_000a: ldloc.2 //取调用栈中位置为2的元素压入评估栈(取k的值)。
    L_000b: add  //做加法操作
    L_000c: call void [mscorlib]System.Console::WriteLine(int32) //调用输出方法
    L_0011: nop  //No Operation
    L_0012: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() //调用ReadKey方法
    L_0017: pop //把评估栈的内容清空
    L_0018: ret  //return 标记返回值
} //Main方法结束

Durch den obigen Code können wir Folgendes zusammenfassen: .maxstack: Variablen im Code, die es benötigt um mehrere Positionen im Aufrufstapel zu belegen (Call Stack); .locals int(...): Variableninitialisierung definieren und in den Aufrufstapel einfügen (Call Stack); Schieben Sie die Zeichenfolge in den Auswertungsstapel.


ldc.i4.1: Schieben Sie den Wert 2 in Form einer 4-Byte-Ganzzahl in den Auswertungsstapel. Legen Sie den Wert im Auswertungsstapel (Evaluation) ab und weisen Sie ihn dem Aufrufstapel (Call Stack) zu. ldloc: Nehmen Sie den Wert an der angegebenen Position im Aufrufstapel (Call Stack) heraus (kopieren Sie ihn) und verschieben Sie ihn in den Auswertungsstapel (Auswertungsstapel); Aufruf: Diese Anweisung wird im Allgemeinen zum Aufrufen statischer Methoden verwendet. Callvir wird im Allgemeinen zum Aufrufen von Instanzmethoden verwendet.

Sehen wir uns ein weiteres Beispiel an

namespace TestConsole
{
    class Program
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void SomeMethod()
        {
            Console.WriteLine("Hello World!");
        }
 
        static void Main(string[] args)
        {
            Console.WriteLine("Before JITed.");
            Console.ReadLine();
 
            SomeMethod();
 
            Console.WriteLine("After JITed");
            Console.ReadLine();
        }
    }
}

Der entsprechende IL-Code der Hauptmethode:

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 8
    // 分配字符串"Before JITed"
    L_0000: ldstr "Before JITed."
    // 调用Console.WriteLine方法
    L_0005: call void [mscorlib]System.Console::WriteLine(string)
    // 调用Console.ReadLine方法
    L_000a: call string [mscorlib]System.Console::ReadLine()
    L_000f: pop
    // 调用Program.SomeMethod方法
    L_0010: call void TestConsole.Program::SomeMethod()
    // 分配字符串"After JITed"
    L_0015: ldstr "After JITed"
    // 调用Console.WriteLine方法
    L_001a: call void [mscorlib]System.Console::WriteLine(string)
    // 调用Console.ReadLine方法
    L_001f: call string [mscorlib]System.Console::ReadLine()
    L_0024: pop
    L_0025: ret
}

Das Obige ist die CLR (Common Language) in C# Laufzeit) und IL-Inhalte (Zwischencode). Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn