2009-08-27 91 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

相关问题