2009-08-27 94 views

回答

7

事情是這樣的:

IL_0001: /* 1F | 32    */ ldc.i4.s 50 
IL_0003: /* 0B |     */ stloc.1 
IL_0004: /* 07 |     */ ldloc.1 
IL_0005: /* 0A |     */ stloc.0 

在一個較低的水平,這取決於機器架構和優化水平。這樣的代碼特別的,沒有效果,可能完全被省略。否則,這將是簡單的代碼,或許是這樣的:

movsx eax, word ptr [ebp+12] 
mov [ebp+8], eax 

movsx是x86指令它保存在它被裝載到一個更大的目標更短的數字的符號;基本上,它會查看較小數據源的最重要位,並在擴展數字時將其複製到其餘位中。

+0

嘿嘿......這真的很低級......我在想一個縮小轉換的路線...... blah ...... blah ...... blah .... :) – klabranche 2009-08-27 05:43:20

+0

很有意思,我曾與摩托羅拉大會合作過,但已經有一段時間了。謝謝。 – ChaosPandion 2009-08-27 05:46:43

+0

您提供的代碼中不需要縮小轉換; 50是靜態已知適合範圍,並且任務擴大,而不是縮小。爲了明確縮小,可以使用'conv。[type]'IL。 'conv.i2'將堆棧頂端截斷爲Int16。在x86彙編中,根據它的使用方式,可能不需要轉換,或者可能會應用'和0xffff'等。 – 2009-08-27 05:49:20

2

從反射器:

.method public hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 1 
    .locals init (
     [0] int32 num, 
     [1] int16 num2) 
    L_0000: nop 
    L_0001: ldc.i4.0   ; Load the constant 0 
    L_0002: stloc.0   ; Store the value into local var 0 
    L_0003: ldc.i4.s 50  ; Load the constant 50 - notice it treats it as a 32-bit value 
    L_0005: stloc.1   ; Store the value into local var 1 
    L_0006: ldloc.1   ; Load local var 1 
    L_0007: stloc.0   ; Store the value into local var 0 
    L_0008: ret 
} 

在IL級,沒有什麼特別發生在分配,但是請注意ldc.i4.s 50對待字面值作爲一個4字節(32位)整數。

當代碼編譯爲JIT時,生成的彙編代碼可能只是將值50提升爲32位寬的值。

0

評估堆棧沒有小於32位的表示。 [編輯,大多數個案(感謝您對評論的更新:)]直到您實際存儲除堆棧以外的某個16位值,沒有任何特殊情況發生,因爲shortint的大小相同。這裏是唯一的操作,其中,你會看到一個區別:

  • b = (short)a
    會結果的16位符號擴展到一個完整的32位寬的變量。這是評論中提到的conv.i4指令。
  • *(short*)c = b分配到該結構被標記StructLayout.Explicit或具有結構構件的襯墊小於4
    只會寫入其32位表示的低16位。
  • checked { b = (short)a; }
    如果(a < -32768 || a > 32767)會拋出異常。
+0

直到存儲除堆棧以外的其他內容都沒有效果。類型轉換Int32到Int16將導致堆棧上的值被截斷,例如, conv.i2。 – 2009-08-27 06:56:36

+0

@巴里:謝謝。我在列表中發現了它,但是我忘記了在發佈之前更新了介紹段落。 :) – 2009-08-27 16:50:37

相關問題