C# 等高階語言隱藏底層實作,但 CIL 實際上是完全基於堆疊的語言。虛擬執行堆疊負責:
鐵律: CIL 不允許直接存取任何資料(區域變數、參數、欄位),必須先 load 到堆疊,使用時再 pop。這解釋了 IL 程式碼看似冗餘的原因。
public void PrintMessage() {
string myMessage = "Hello";
Console.WriteLine(myMessage);
}
.method public hidebysig instance void PrintMessage() cil managed
{
.maxstack 1
.locals init ([0] string myMessage)
IL_0000: nop
IL_0001: ldstr "Hello" // 載入字串常數到堆疊
IL_0006: stloc.0 // 存儲堆疊頂端值到區域變數索引 0
IL_0007: ldloc.0 // 載入區域變數索引 0 到堆疊
IL_0008: call void [mscorlib]System.Console::WriteLine(string)
IL_000d: nop
IL_000e: ret
}
.locals init ([0] string myMessage):宣告索引 0 的區域變數ldstr:載入字串常數stloc.0:存儲至區域變數 0(Store)ldloc.0:載入區域變數 0(Load)call:呼叫方法,消耗堆疊上的參數| 類別 | 常用指令 | 說明 |
|---|---|---|
| 常數載入 | ldc.i4, ldstr, ldnull | 載入數值、字串、null |
| 區域變數 | ldloc, stloc, ldloca | 載入/存儲/取址區域變數 |
| 參數 | ldarg, starg, ldarga | 載入/存儲/取址方法參數 |
| 欄位 | ldfld, stfld, ldflda | 載入/存儲/取址實例/靜態欄位 |
| 陣列 | ldelem, stelem, ldelema | 載入/存儲/取址陣列元素 |
IL 支援 // 單行與 /* ... */ 多行註解,編譯器會忽略。
理解「Load/Store 雙向流動」與「虛擬執行堆疊」是閱讀寫作 IL 的基石。下一篇將進入實戰:Round-trip Engineering 修改既有組件。