2012-08-29 41 views
17

我在C#我是否正確理解這個MSIL代碼?

// test.Program 
private static void Main() 
{ 
    int x = 5; 
    int y = 100; 
    Console.WriteLine(y + ", " + x); 
} 

下面的代碼,我正在讀的IL代碼,所以之前我問,如果我每行確實是正確的我從來沒有編程組件。

.method private hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2058 
    // Code size 33 (0x21) 
    .maxstack 3 // maximum stack in this method is 3 
    .entrypoint // method is initial entry point 
    .locals init (// reserves memory for x and y variables 
     [0] int32 x, // x variable is reserved on position 0 of the stack 
     [1] int32 y // y variable is reserved on position 1 of the stack 
    ) 
    IL_0000: ldc.i4.5  // integer of 4 bytes in size and the value of 5 is loaded onto the evaluation stack position 0 
    IL_0001: stloc.0  // put evaluation stack position 0 into the stack position 0, the evaluation stack is emptied 
    IL_0002: ldc.i4.s 100 // integer of 4 bytes in size and the value of 100 is loaded onto the evaluation stack position 0 
    IL_0004: stloc.1  // put evaluation stack position 0 onto the stack position 1, the evaluation stack is emptied 
    IL_0005: ldloc.1  // load stack position 1 into the evaluation stack position 0 
    IL_0006: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack 
    IL_000b: ldstr ", " // put reference to string on evaluation stack position 1 
    IL_0010: ldloc.0  // load stack position 0 into the evaluation stack position 2 
    IL_0011: box [mscorlib]System.Int32 // box last valuetype placed on evaluation stack, replace valuetype with reference on evaluation stack position 0, do not empty stack 
    IL_0016: call string [mscorlib]System.String::Concat(object, object, object) // call Concat, pass values on evaluation stack, empty evaluation stack, put result of concat on evaluationstack 
    IL_001b: call void [mscorlib]System.Console::WriteLine(string) // pass first value in evaluation stack 
    IL_0020: ret   // return 
} // end of method Program::Main 

我對此程序的理解是否正確?

回答

11

非常多;我唯一需要澄清的是盒子(IL_0006和IL_0011)是類型特定的,所以它明確地構造了一個int類型的盒子(它不僅僅是「最後一個valueType」)。

此外,「空白評估堆棧」具有誤導性;這是不完全正確的 - 例如,call消耗給定數量的職位 - 它不「空」它。有從來沒有一個「空評估堆棧」的語義 - 它總是「消耗一些值,放回一些值」(其中任何一個可能爲零)。

+0

當n個職位被某些東西消耗(例如調用)時,只有最高職位被消費了嗎?然後將一些數值放回評估堆棧中?我想這是真的,因爲畢竟它是一個'疊加',但我只是要求確定。 – ProgrammerAtWork

+1

是的。讀取A,B,C,D併產生Y,Z的假設操作會從堆棧*中彈出4個條目,計算結果*,然後將2個新條目推送到其上。 (*)並不一定按順序排列,但推動總是最後一個。 – quetzalcoatl

3

是的,你的理解幾乎完全正確。有一件事:IL_0010不從堆棧加載,它從本地加載。 (當地人最終在運行時間堆棧上,但是在IL層次上,這些稱爲本地人)。

+0

OP正在向棧上的當地人單獨描述「評估棧」,但我同意將它們稱爲當地人會更好。 –

2

這是正確的,但我要說一點與一些措辭不清,例如:

放計算堆棧位置0到堆棧位置0,計算堆棧被清空

我想說

把從堆棧頂部第0進入堆棧變量零,然後彈出

僅僅因爲我認爲一種「不太正式」的措辭在大多數時候都更加清晰易讀,但更確切地說,它似乎沒問題。

編輯:嗯..在事後,我會說沒有兩件事情像「堆棧」和「評估堆棧」。只有「堆棧」。可見部分堆棧的標記部分,即帶有局部變量的部分可以稱爲「槽」。我假設用IL,你可以說「局部變量Nth」,通常情況下都會很清楚,但我認爲可以將幾個不同的變量映射到同一個插槽,因此可能會導致一些混淆。另外,當您使用堆棧時,沒有像「清空」的操作。只需按下/彈出一個明確指定數量的條目進行復制。