MSIL 初級讀本 第二部分:局部變數

來源:互聯網
上載者:User

 

聲明:

    本文譯自 Kenny Kerr  的 blog,如果大家有更好的 MSIL 入門文章也歡迎推薦,謝謝。

    在本文的第二部分裡,我將探討一下局部變數的使用。為了展示這個過程,讓我們來寫一個將兩數相加的簡單程式。
    在 MSIL 方法中,使用 .locals 指示符來聲明局部變數

    

.local init( int32 first, 
                  int32 second,
                  int32 result )

   
    該語句為當前方法聲明了三個局部變數。在本例中,恰巧都是 int32 類型—— System.Int32 類型的同義字。init 指定這些變數需要以其對應類型的預設值進行初始化。變數名稱也可以被省略,那樣的話你需要通過聲明時的zero-based 索引來指明變數。當然,使用變數名會增加代碼的可讀性。
    在我們繼續之前,需要先明確一下 MSIL 當中顯式使用棧的方式。當你需要向一個指令傳值的時候,首先需要把那些值壓棧。而指令需要進行彈棧操作以讀出數值。類似地,在調用方法時也需要將對象引用 ( 如果有的話 ) 和需要傳遞的參數按順序壓棧。在開始調用方法時,所有的參數以及對象引用會被彈棧。使用 ldloc 指令來將變數的值壓棧;使用 stloc 指令將棧頂的值彈出並儲存到指定變數中。另外要時刻記得,實值型別的右值會被直接儲存到棧中,而對象 ( 參考型別的執行個體 ) 不會,因為 CLI 不允許在棧上為參考型別的對象分配記憶體,而只是將對象的引用儲存到棧上。這類似於將一個原生C++對象分配在堆上並將一個指向它的指標儲存在棧中。請在閱讀本文的時候記住這個棧的存在,這將有助於理解為什麼數值會不停地在棧上壓入彈出。 
    下一步是要讓使用者輸入相加的數值。

    

ldstr "First number: "
call void [mscorlib]System.Console::Write(string)
call string [mscorlib]System.Console::ReadLine()
call int32 [mscorlib]System.Int32::Parse(string)
stloc first

    
    上一篇文章中提到, ldstr 指令將字串壓棧,而 call 指令調用 Write 方法,並將其參數彈棧。下一個 call 指令調用 ReadLine 方法,該方法從控制台讀入並返回的字串被壓棧。因為傳回值正好位於棧頂,所以我們直接調用 Int32::Parse 方法,將讀入的字串彈棧並將其等價的 int32 類型的數值壓棧。注意為了清楚起見,我省略了所有的錯誤處理。接下來用 stloc 指令將數值彈棧並儲存於局部變數 first 當中。第二個數值以同樣的方式獲得,並儲存於變數 second 當中。
    接下來,我們使用 add 指令完成加法並將結果儲存到變數 result 。 

    

ldloc first
ldloc second
add
stloc result

    
    最後顯示結果。

   

ldstr "{0} + {1} = {2}"
ldloc first
box int32
ldloc second
box int32
ldloc result
box int32
call void [mscorlib]System.Console::WriteLine(string, object, object, object)

    我們使用WriteLine 的一個重載版本,它接收一個格式化字串和三個 object 對象作為參數。調用之前,每一個參數都必須按順序壓棧。因為數值是以 int32 這個實值型別來儲存的,所以我們需要對其進行裝箱操作,否則將無法匹配方法簽名。 ldloc 指令將每一個參數壓棧,隨後 box 指令被應用於每個參數。裝箱操作將數值彈棧,而後構造一個包含該數值拷貝的新對象,並將新對象的引用壓棧。
    完整地程式如下:

.method static void main()
{
    .entrypoint
    .maxstack 4

    .locals init (int32 first,
                 int32 second,
                 int32 result)
    ldstr "First number: "
    call void [mscorlib]System.Console::Write(string)
    call string [mscorlib]System.Console::ReadLine()
    call int32 [mscorlib]System.Int32::Parse(string)
    stloc first

    ldstr "Second number: "
    call void [mscorlib]System.Console::Write(string)
    call string [mscorlib]System.Console::ReadLine()
    call int32 [mscorlib]System.Int32::Parse(string)
    stloc second
    ldloc first
    ldloc second
    add
    stloc result
    ldstr "{0} + {1} = {2}"
 
    ldloc first
    box int32

    ldloc second
    box int32

    ldloc result
    box int32
    
    call void [mscorlib]System.Console::WriteLine(string, object, object, object)??? 
    ret
}
     
    最後值得注意的是,本例中的程式需要大小為4的棧空間,因為最後調用 WriteLine 方法時需要傳入4個參數。 
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.