国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

.NET編譯技術(shù)內(nèi)幕(1)

2024-07-10 13:02:11
字體:
供稿:網(wǎng)友


通過msil了解clr的運(yùn)行原理
作者: wednesday, april 17 2002 2:12 pm



作為.net最低層次的公共基礎(chǔ),微軟中介語言(msil或il)對一般開發(fā)者具有非常重要的意義。除了好奇心以外,仔細(xì)研究應(yīng)用程序的il能讓你更為清楚地了解到公共語言運(yùn)行時(clr)執(zhí)行高級c#或vb.net代碼的基本原理,從而有助于你發(fā)現(xiàn)和解決一些比較細(xì)微的問題。

在這篇文章里,我將引領(lǐng)讀者了解il,學(xué)習(xí)有關(guān)的一些關(guān)鍵指令,同時對clr的操作機(jī)理做一點(diǎn)基礎(chǔ)性解釋。我不打算教你用il編程,而是分析一些il語法和語句使你對il有更多了解。

ildasm簡介
微軟的il拆卸實(shí)用程序ildasm.exe(通常位于/program files/microsoft.net/frameworksdk/bin目錄下)可以析構(gòu).net assembly(裝配)、根據(jù)你的要求從程序中抽取il代碼。對某一assembly調(diào)用該使用程序后,ildasm會給出該assembly中所有類和名稱空間的一個視圖,如圖a所示:

" target=_blank>http://www.zdnet.com.cn/i/developer/story/39032789/image001.gif

圖a


ildasm瀏覽assembly

當(dāng)你進(jìn)到某個類的成員或其方法,ildasm就會為你顯示該成員的il代碼。如果之前你曾經(jīng)看到過匯編器或j++字節(jié)碼,那么il可能在你看來會覺得有點(diǎn)眼熟。在另一方面,如果你僅對抽象的高級程序語言有所了解,那么il看起來更像是胡言亂語。

好,現(xiàn)在你知道如何窺視assembly的il代碼了,但這些代碼都意味著什么呢?在回答這個問題之前,首先讓我們先來了解下clr的有關(guān)知識。

虛擬cpu
對.net程序來說,.net clr在功能上就如同一塊虛擬的cpu,它執(zhí)行il代碼、操作數(shù)據(jù)。clr和真實(shí)的cpu類似之處在于它們都不直接操作內(nèi)存中的變量而是使用程序變量的臨時拷貝,clr把這些程序變量存放在堆棧上。從內(nèi)存拷貝某個變量到堆棧的行為稱做裝載(loading),而從堆棧拷回某個變量到內(nèi)存的行為則被稱做存儲(storing)。

所以把兩個數(shù)字相加的過程應(yīng)該是這樣的:

1.裝載第1個數(shù)字并把它推入堆棧。

2.裝載第2個數(shù)字并把它推入堆棧。

3.從堆棧中取出這兩個數(shù)字并把它們相加。

4.把結(jié)果存儲到內(nèi)存。

什么是堆棧?
理解il的關(guān)鍵是知道堆棧的工作原理。堆棧是一種抽象數(shù)據(jù)結(jié)構(gòu),其操作機(jī)理是后進(jìn)先出。當(dāng)你把新條目推進(jìn)堆棧時,已經(jīng)在堆棧內(nèi)的任何條目都會壓到堆棧的深處。同樣的,把一個條目從堆棧移出則會讓堆棧內(nèi)的其他條目都向堆棧的頂部移動。只有堆棧最頂端的條目能從堆棧中取出,條目離開堆棧的順序和它們被推進(jìn)堆棧的順序一樣。你不妨回想下自動售貨機(jī)的裝貨和取貨過程就明白了。

重要的il語句
既然你已經(jīng)明白了clr操作的基礎(chǔ)知識,下面我們就接著討論你面前的那些代碼。怎么?沒有看到什么代碼?那么請你看看這里列出的il代碼。

sidebar a: sample il listing


.method private instance void  listen() cil managed
{
  // code size       169 (0xa9)
  .maxstack  4
  .locals init ([0] unsigned int8[] buff,
           [1] class [system]system.net.sockets.networkstream chatstream,
           [2] class [system]system.net.sockets.tcpclient remoteclient,
           [3] string strhandle,
           [4] class chat.chatserver/textrelayer 'handler',
           [5] class [mscorlib]system.threading.thread t)
  il_0000:  nop
  il_0001:  nop
  .try
  {
    il_0002:  br         il_0091
    il_0007:  ldarg.0
    il_0008:  ldfld      class [system]system.net.sockets.tcplistener chat.chatserver::listener
    il_000d:  callvirt   instance class [system]system.net.sockets.tcpclient [system]system.net.sockets.tcplistener::accepttcpclient()
    il_0012:  stloc.2
    il_0013:  ldloc.2
    il_0014:  callvirt   instance class [system]system.net.sockets.networkstream [system]system.net.sockets.tcpclient::getstream()
    il_0019:  stloc.1
    il_001a:  ldc.i4.s   26
    il_001c:  newarr     [mscorlib]system.byte
    il_0021:  stloc.0
    il_0022:  ldloc.1
    il_0023:  ldloc.0
   il_0024:  ldc.i4.0
    il_0025:  ldc.i4.s   24
    il_0027:  callvirt   instance int32 [system]system.net.sockets.networkstream::read(unsigned int8[],
                                                                                       int32,
                                                                                      int32)
    il_002c:  pop
    il_002d:  call       class [mscorlib]system.text.encoding [mscorlib]system.text.encoding::get_ascii()
    il_0032:  ldloc.0
    il_0033:  callvirt   instance string [mscorlib]system.text.encoding::getstring(unsigned int8[])
    il_0038:  stloc.3
    il_0039:  ldarg.0
    il_003a:  ldfld      class chat.chatserver/incomingchatrequest chat.chatserver::requestconnect
    il_003f:  ldloca.s   strhandle
    il_0041:  callvirt   instance bool chat.chatserver/incomingchatrequest::invoke(string&)
    il_0046:  brtrue.s   il_0051
    il_0048:  ldloc.2
    il_0049:  callvirt   instance void [system]system.net.sockets.tcpclient::close()
    il_004e:  nop
    il_004f:  br.s       il_008f
    il_0051:  nop
    il_0052:  ldloca.s   strhandle
    il_0054:  ldarg.0
    il_0055:  ldflda     class chat.chatserver/incomingtext chat.chatserver::relaytext
    il_005a:  ldloca.s   chatstream
    il_005c:  newobj     instance void chat.chatserver/textrelayer::.ctor(string&,
                                                                          class chat.chatserver/incomingtext&,
                                                                          class [system]system.net.sockets.networkstream&)
    il_0061:  stloc.s    'handler'
    il_0063:  ldloc.s    'handler'
    il_0065:  dup
    il_0066:  ldvirtftn  instance void chat.chatserver/textrelayer::handlechat()
    il_006c:  newobj     instance void [mscorlib]system.threading.threadstart::.ctor(object,
                                                                                     native int)
    il_0071:  newobj     instance void [mscorlib]system.threading.thread::.ctor(class [mscorlib]system.threading.threadstart)
    il_0076:  stloc.s    t
    il_0078:  ldarg.0
    il_0079:  ldfld      class [system]system.collections.specialized.listdictionary chat.chatserver::chatthreads
    il_007e:  ldloc.3
    il_007f:  ldloc.s    t
    il_0081:  callvirt   instance void [system]system.collections.specialized.listdictionary::add(object,
                                                                                                  object)
    il_0086:  nop
    il_0087:  ldloc.s    t
    il_0089:  callvirt   instance void [mscorlib]system.threading.thread::start()
    il_008e:  nop
    il_008f:  nop
    il_0090:  nop
    il_0091:  ldc.i4.1
    il_0092:  brtrue     il_0007
    il_0097:  leave.s    il_00a6
  }  // end .try
  finally
  {
    il_0099:  nop
    il_009a:  ldstr      "listener thread aborted."
    il_009f:  call       void [mscorlib]system.console::writeline(string)
    il_00a4:  nop
    il_00a5:  endfinally
  }  // end handler
  il_00a6:  nop
  il_00a7:  nop
  il_00a8:  ret
} // end of method chatserver::listen





你首先看見的是對當(dāng)前方法的il聲明,其中包括方法的名字,返回類型、參數(shù)列表以及附著于該方法的其他修飾關(guān)鍵詞(static/shared、public、virtual等等)。對象構(gòu)造器則被賦給一個特殊的名字:.ctor。

在il中,方法參數(shù)按照它們在參數(shù)列表中的位置依次被引用。如果方法是靜態(tài)或共享方法,那么參數(shù)0則是參數(shù)列表中的第1個參數(shù)。而對實(shí)例方法來說,參數(shù)0則是指向該方法所在類的實(shí)例的指針(me或者this)。方法中的所有局部變量都在.locals標(biāo)記的段落中以同樣的方式聲明。

在聲明所有的局部變量以后,程序的實(shí)際正文才開始。每條il指令,或opcode都可以根據(jù)你的喜好以一個il_ 標(biāo)記作為代碼行開頭。我們接下來再了解些更重要的il指令。

變量用法
以ld開頭的指令把變量從內(nèi)存裝載到堆棧供其操作。裝載指令有若干條,每一條裝載指令都操作特定類型的變量。以下就是其中的一些裝載指令:

ldc把一個數(shù)字常數(shù)裝入堆棧。這條指令有兩個修飾詞。第一個是類型標(biāo)識符,第二個是實(shí)際的數(shù)值。
ldloc把一個局部變量裝入堆棧。另外還有一條ldloca指令把一個局部變量的地址(而非變量的內(nèi)容)裝入堆棧。變量由它們在.locals節(jié)的位置標(biāo)識。這些指令裝載位置4及以后位置使用不同的語法,但是索引號會出現(xiàn)在指令中。
ldarg裝載成員的一個參數(shù),而ldarga指令則裝載參數(shù)的地址。變量由它們在.locals節(jié)中的位置標(biāo)識。這些指令裝載位置4及以后位置使用不同的語法,但是索引號仍然出現(xiàn)在指令中。
ldelem把數(shù)組元素裝入堆棧而且通常先于表示這個索引的其他裝載語句之前使用。
ldlen把一個數(shù)組的長度裝入堆棧。
ldfld和ldsfld把類域(成員變量)和靜態(tài)類域裝入堆棧。域由一個全名識別。
每一條裝載指令都有對應(yīng)的一條存儲指令,后者以st開頭,負(fù)責(zé)把一個條目存入內(nèi)存。例如,stloc就負(fù)責(zé)把堆棧最頂端的條目存入一個局部變量。存儲指令指定變量的句法規(guī)則通常和它們對應(yīng)的裝載指令類似。

比較操作
如果你不能比較兩個值而且根據(jù)其比較結(jié)果做出決定,那么許多問題都無法用任何程序語言來解決。il有一套比較操作符,它們都以c字母開頭,比較堆棧中的值。通常,如果比較結(jié)果為真則會把1推入堆棧否則就推入0。

大多數(shù)這類指令都很容易由它們的名字區(qū)分出來。例如,ceq比較兩個值是否相等,而cgt則確定堆棧最頂端的值是否比第二個最頂端值更大。 clt類同于cgt,不過執(zhí)行的是小于比較操作。

goto
通常,在對兩個值進(jìn)行比較之后會根據(jù)比較的結(jié)果結(jié)果實(shí)施一些操作。il分支指令(以br開頭)根據(jù)堆棧最頂端的條目中的內(nèi)容跳到其他指令。brtrue 和brfalse彈出堆棧最頂端的條目,然后根據(jù)該項(xiàng)為真(1)還是為假(0)而分別跳到指定的代碼行。如果沒有執(zhí)行指令跳躍則繼續(xù)執(zhí)行下一條指令。另外還有一個無條件分支操作符br,它總是跳到指定的代碼行。

你會發(fā)現(xiàn)分支操作就好像源代碼中的if語句以及顯式執(zhí)行的goto操作。il中的分支命令同樣具有高級流程控制結(jié)構(gòu)的對等體,比如:if, case, while, for等等。

創(chuàng)造新對象和調(diào)用其他代碼
call和callvirt指令調(diào)用其他方法和函數(shù)。call通常表示被調(diào)用的方法是靜態(tài)的或共享的,而callvirt則用于實(shí)例方法。就兩種指令來說,方法的名字都會在指令中包括。被送到方法的任何參數(shù)都會被彈出堆棧而且要在方法被調(diào)用之前裝載。

因?yàn)閯?chuàng)建一個新對象需要調(diào)用構(gòu)造器,所以il的對象創(chuàng)建也類似于其他的方法調(diào)用。參數(shù)首先被裝載到堆棧,然后執(zhí)行newobj指令,它調(diào)用對象的構(gòu)造器同時把對象的索引放回堆棧。指令中得有對象的名字。

以上就是大致的il語法操作。除了滿足你內(nèi)心的求知欲望以外,我希望你能從我的闡述中得到足夠的信息來理解il代碼的真實(shí)含義。



發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 莆田市| 江口县| 姜堰市| 定南县| 日土县| 莱芜市| 渝中区| 甘德县| 隆化县| 教育| 陆丰市| 天长市| 万安县| 东安县| 开封市| 民丰县| 富顺县| 丽江市| 星座| 时尚| 无锡市| 海伦市| 威宁| 文登市| 镇康县| 韶山市| SHOW| 东平县| 闽清县| 醴陵市| 定安县| 白河县| 罗田县| 双峰县| 永修县| 通辽市| 综艺| 靖宇县| 虹口区| 英德市| 陈巴尔虎旗|