《Inside Microsoft IL Assembler》學習筆記2:讓IL代碼簡短些

來源:互聯網
上載者:User
還是學習筆記1中的那個例子,可以改成如下的樣子,功能不變,但運行時佔用的資源會小一些。我在所有和筆記1中代碼有了變化的位置加上了注釋,如下: 1//----------- Program header
 2.assembly extern mscorlib { }
 3.assembly OddOrEven  { }
 4.module OddOrEven.exe
 5//----------- Class declaration
 6.namespace Odd.or {
 7    .class public auto ansi Even extends [mscorlib]System.Object {
 8//----------- Field declaration
 9        .field public static int32 val
10//----------- Method declaration
11        .method public static void check( ) cil managed {
12            .entrypoint
13            .locals init (int32 Retval)
14        AskForNumber:
15            ldstr "Enter a number"
16            call void [mscorlib]System.Console::WriteLine(string)
17            call string [mscorlib]System.Console::ReadLine()
18            ldstr "%d" // 所有的字串常量都不需要特殊的聲明,il彙編器看到這樣的字串之後會自動將其加入到中繼資料中
19            ldsflda int32 Odd.or.Even::val
20            call vararg int32 sscanf(string,string,,int32*) 
21            stloc.0 // java的虛機和.net clr都使用0,1,2,3這樣的編號來表示本地變數。這裡的"0"就指向唯一的一個本地變數Retval
22            ldloc.0 // 將第一個本地變數的值壓棧
23            brfalse.s Error  // brfalse.s指令是brfalse的簡化指令。當指令被編譯成作業碼之後,brfalse接受的是一個4位元組的參數,
24        //而brfalse.s僅接受一個單位元組的參數,這意味著只能在程式碼片段的{-128位元組~~+128位元組}的範圍內(相對於當前位置而言)跳轉。
25            ldsfld int32 Odd.or.Even::val
26            ldc.i4.1  // 向棧頂壓入一個單位元組常量,值為1(ldc.i4 1也是向棧頂壓入1,但要用4個位元組)
27            and
28            brfalse.s ItsEven  
29            ldstr "odd!"
30            br.s PrintAndReturn 
31        ItsEven:
32            ldstr "even!"
33            br.s PrintAndReturn  
34        Error:
35            ldstr "How rude!"
36        PrintAndReturn:
37            call void [mscorlib]System.Console::WriteLine(string)
38            ldloc.0  
39            brtrue.s AskForNumber  
40            ret
41        } // End of method
42    } // End of class
43} // End of namespace
44//----------- Calling unmanaged code
45.method public static pinvokeimpl("msvcrt.dll" cdecl) 
46    vararg int32 sscanf(string,string) cil managed { }
47

  另外,提起上文中的ldloc.0這樣的指令,筆者一開始也是未明其意。其實,在clr執行程式的過程中,涉及到的記憶體使用量主要有三類,除了我們常說的託管堆,每個線程都有自己專屬的兩個棧:計算棧(Evaluation Stack)和調用棧(Call Stack)。這兩個棧都經常被提到,又都專屬於clr線程,所以有的時候會混,其實它們的功能是完全不同的。調用棧就是最傳統的用來記錄方法調用次序的棧,每個線程會得到1MB的調用棧空間,每調用一個新的方法都會壓棧,傳入參數、臨時變數等都會壓入棧中,待方法執行完畢就完全釋放。ldloc.0中的"0",所指的就是當前調用棧上的第一個臨時變數。而計算棧在某種程度上可以視為clr虛擬機器的寄存器(這麼說只是因為它是和虛機上的計算功能直接互動的儲存單位),我們常說的clr虛機是完全基於“棧”的,指的就是計算棧。虛機上的所有操作,都要從計算棧的參數,結果也都會壓入到計算棧頂。計算棧的單位既不是字,也不是位元組,而是slot(怎麼翻譯合適呢,咳咳),根據slot內所裝資料類型的不同,slot的大小也不同。當clr棧頂的slot裡取到資料之後,在運算之前會檢驗資料的類型,如果無法轉換成運算期望的類型,會拋出異常。蔡學庸在msdn上有篇文章,裡面的一個貼圖看著很明白,就在這裡借用一下吧:

 參考資料:MSIL instruction table

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.