值 0 的 CIL 指令 "isinst [System.Runtime]System.Int32" (int32) - 将返回什么?



我有一个简单的C#函数

public bool Isinst_intSimple(object value)
{
return value is int;
}

如预期,Isinst_intSimple(0)返回true

反编译后,函数看起来像:

IL_0000: nop
IL_0001: ldarg.1      // 'value'
IL_0002: isinst       [System.Runtime]System.Int32
IL_0007: ldnull
IL_0008: cgt.un
IL_000a: stloc.0      // V_0
IL_000b: br.s         IL_000d
// [196 9 - 196 10]
IL_000d: ldloc.0      // V_0
IL_000e: ret

执行后,IL_0002 isinst [System.Runtime]System.Int32指令会在评估堆栈上推送什么(输入为0(int32((

根据MS文档,Isinst指令应该返回一个对象引用——结果(对象引用或空引用(被推送到堆栈上。

但是对0的引用是什么?以及如果。指令IL_0008: cgt.un应该做什么?

我的解释

在我对所有IL指令的解释中,函数retrun0。我找不到返回true的方法。

以下是我对功能执行的解释:

IL_0000: nop
IL_0001: ldarg.1      // push 0 on evaluation stack – stack after {0}
IL_0002: isinst       [System.Runtime]System.Int32    //pop and object reference is pushed onto the stack. - stack after { 0* or reference to 0 – boxing? }
IL_0007: ldnull //– stack after {null, 0*}
IL_0008: cgt.un //– 0* is not greater than null so its return 0 -  stack after {0}
IL_000a: stloc.0      // V_0 – pop to V_0 – stack after {}
IL_000b: br.s         IL_000d // – stack after {}
// [196 9 - 196 10]
IL_000d: ldloc.0      // V_0 //– push V_0 – stack after {0}
IL_000e: ret    //return {0}

我认为问题出在IL_0002: isinstIL_0008: cgt.un,但我找不到。

背景

我正在一个虚拟机上工作,它逐个指令地模拟C#dll(在"虚拟机"中执行C#(,但我在模拟测试函数Isinst_intSimple(0)时遇到了问题。我的版本返回0,但应该返回true

ECMA-335规范定义了IL字节码,说明如下:

I.12.1.6.2.6值类型上的castclassisinst

不允许向值类型实例进行强制转换和从值类型实例强制转换(等效的操作有box和unbox(。然而,当被装箱时,可以使用isinst指令来查看类型为System.Object的值是否是特定类的装箱表示。

III.4.6-isinst

测试obj是否是typeTok的实例,返回null或该类或接口的实例。

堆栈转换:。。。,obj=>。。,结果

描述typeTok是一个元数据标记(typeref、typedef或typespec(,表示所需的类。如果typeTok是不可为null的值类型或通用参数类型,则将其解释为"盒装"typeTok

可验证性:验证将result的类型跟踪为typeTok

因此,值类型(结构(上isinst的结果是该值的装箱ObjectRef。

II.1.5操作数类型表

cgt.un在ObjectRefs(O(上是允许的并且是可验证的。这通常用于将ObjectRef与null进行比较(没有"compare not equal"指令,否则这将是一个更明显的解决方案(

因此isinstldnullcgt.un将告诉您对象是否属于特定类型

相关内容

  • 没有找到相关文章

最新更新