值 0 (int32) 的 CIL 指令 "isinst [System.Runtime]System.Int32" - return 会是什么?
CIL instruction "isinst [System.Runtime]System.Int32" for value 0 (int32) - what will return?
我有一个简单的 C# 函数
public bool Isinst_intSimple(object value)
{
return value is int;
}
符合预期Isinst_intSimple(0)
returns 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
指令应该 return 对象引用 - The result (either an object reference or a null reference) is pushed onto the stack.
但是0的引用是什么?而如果。指令IL_0008: cgt.un
应该做什么?
我的解读
在我对所有IL指令的解释中——函数重新运行0
。而且我找不到 return 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: isinst
或IL_0008: cgt.un
,但我找不到。
背景
我正在使用模拟 C# dll 的虚拟机 - 逐条指令(在“虚拟机”中执行 C#),但我在模拟测试函数时遇到问题 Isinst_intSimple(0)
。我的版本 return 0
但它应该 return true
ECMA-335 specification,它定义了 IL 字节码,表示如下:
I.12.1.6.2.6 castclass
and isinst
on value types
Casting to and from value type instances isn’t permitted (the equivalent operations arebox and unbox). When boxed, however, it is possible to use the isinst
instruction to see whether a value of type System.Object
is the boxed representation of a particular class.
III.4.6 - isinst
Test if obj
is an instance of typeTok
, returning null
or an instance of that class or interface.
Stack Transition: ..., obj => ..., result
Description: typeTok
is a metadata token (a typeref, typedef or typespec), indicating the desired class. If typeTok
is a non-nullable value type or a generic parameter type it is interpreted as “boxed” typeTok
Verifiability: Verification tracks the type of result
as typeTok
.
因此 isinst
在值类型(结构)上的结果是值的装箱 ObjectRef。
II.1.5 Operand type table
cgt.un
is allowed and verifiable on ObjectRefs (O). This is commonly used when comparing an ObjectRef with null (there is no “compare-not-equal” instruction, which would otherwise be a more obvious solution)
所以 isinst
ldnull
cgt.un
会告诉你对象是否属于特定类型
我有一个简单的 C# 函数
public bool Isinst_intSimple(object value)
{
return value is int;
}
符合预期Isinst_intSimple(0)
returns 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
指令应该 return 对象引用 - The result (either an object reference or a null reference) is pushed onto the stack.
但是0的引用是什么?而如果。指令IL_0008: cgt.un
应该做什么?
我的解读
在我对所有IL指令的解释中——函数重新运行0
。而且我找不到 return 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: isinst
或IL_0008: cgt.un
,但我找不到。
背景
我正在使用模拟 C# dll 的虚拟机 - 逐条指令(在“虚拟机”中执行 C#),但我在模拟测试函数时遇到问题 Isinst_intSimple(0)
。我的版本 return 0
但它应该 return true
ECMA-335 specification,它定义了 IL 字节码,表示如下:
I.12.1.6.2.6
castclass
andisinst
on value typesCasting to and from value type instances isn’t permitted (the equivalent operations arebox and unbox). When boxed, however, it is possible to use the
isinst
instruction to see whether a value of typeSystem.Object
is the boxed representation of a particular class.
III.4.6 -
isinst
Test if
obj
is an instance oftypeTok
, returningnull
or an instance of that class or interface.Stack Transition: ..., obj => ..., result
Description:
typeTok
is a metadata token (a typeref, typedef or typespec), indicating the desired class. IftypeTok
is a non-nullable value type or a generic parameter type it is interpreted as “boxed”typeTok
Verifiability: Verification tracks the type of
result
astypeTok
.
因此 isinst
在值类型(结构)上的结果是值的装箱 ObjectRef。
II.1.5 Operand type table
cgt.un
is allowed and verifiable on ObjectRefs (O). This is commonly used when comparing an ObjectRef with null (there is no “compare-not-equal” instruction, which would otherwise be a more obvious solution)
所以 isinst
ldnull
cgt.un
会告诉你对象是否属于特定类型