标签: il

存在哪些CLR/.NET字节码工具?

我非常了解用于操作,生成,反编译JVM字节码(ASM,cglib,jad等)的Java工具.CLR字节码有哪些类似的工具?人们为CLR做字节码操作吗?

.net clr il bytecode

7
推荐指数
3
解决办法
4885
查看次数

你对.NET CLR和CIL的好书有什么建议?

您是否知道有关CLR,.NET FrameworkCIL的工作方式的任何好书,而不是任何特定的.NET语言?

.net clr il cil

7
推荐指数
2
解决办法
3029
查看次数

使用null初始化局部变量会影响性能吗?

让我们比较两段代码:

String str = null;
//Possibly do something...
str = "Test";
Console.WriteLine(str);
Run Code Online (Sandbox Code Playgroud)

String str;
//Possibly do something...
str = "Test";
Console.WriteLine(str);
Run Code Online (Sandbox Code Playgroud)

我一直认为这些代码是相同的.但是在我构建这些代码(检查了优化的发布模式)并比较生成的IL方法后,我注意到第一个样本中还有两个IL指令:

第一个示例代码IL:

.maxstack 1
.locals init([0] string str)
IL_0000:ldnull
IL_0001:stloc.0
IL_0002:ldstr"Test"
IL_0007:stloc.0
IL_0008:ldloc.0
IL_0009:call void [mscorlib] System.Console :: WriteLine (字符串)
IL_000e:ret

第二个示例代码IL:

.maxstack 1
.locals init([0] string str)
IL_0000:ldstr"Test"
IL_0005:stloc.0
IL_0006:ldloc.0
IL_0007:call void [mscorlib] System.Console :: WriteLine(string)
IL_000c:ret

可能这个代码是由JIT compiller优化的?那么带有null的本地bethod变量的初始化会影响性能(我知道这是非常简单的操作,但无论如何)我们应该避免它吗?先谢谢.

c# performance il jit initialization

7
推荐指数
2
解决办法
1393
查看次数

CLR在调用struct的方法时如何工作

我想我已经知道了一堂课的答案,只想确认我的理解是正确的.假设我有一个ClassA名为的实例a.何时a.MethodA()被调用:

(1)CLR找到的类型ClassA由所述类型的指针a在堆(类型已经装载到堆)

(2)MethodA在类型中找到,如果没有找到,则转到它的基类型,直到object上课.

也许我的理解不太准确,但我认为这是基本正确的(纠正我,如果它是错的!).这是一个简单结构的问题.

struct MyStruct
{
   public void MethodA() { }
}
Run Code Online (Sandbox Code Playgroud)

我有var x = new MyStruct();,它的值在堆栈上,并且MyStruct已经加载到堆中的类型.执行时x.MethodA(),当然没有拳击.CLR如何找到MethodA并获取IL并执行/ JIT呢?我想答案可能是:(再次,如果我错了,请纠正我)

(1)我们有声明类型x堆栈上.CLR通过堆栈上的信息找到它的类型,并MethodA在其类型中查找.- 让我们来称呼它assumptionA.

如果你告诉我我assumptionA是对的,我会很高兴的.但即使它是错的,它也说明了一个事实:CLR有一种方法可以在没有装箱的情况下找到结构类型.

现在怎么样x.ToString()还是x.GetType()?我们知道该值将被加框,然后它将像一个类一样执行.但为什么我们需要拳击呢?既然我们可以得到它的类型(假设A告诉我们),为什么不去它的基类型并找到方法(就像一个类)?为什么这里需要昂贵的箱子操作?

.net c# clr il value-type

7
推荐指数
1
解决办法
2253
查看次数

为双数组生成IL

我正在使用System.Reflection.Emit名称空间编写一些IL机构来创建intdouble使用数组.

为了创建int数组我正在使用以下代码.

LocalBuilder arr = gen.DeclareLocal(typeof(int));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Newarr, typeof(int));
gen.Emit(OpCodes.Stloc, arr);
gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldc_I4, 500);
gen.Emit(OpCodes.Stelem_I4);

gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldelem_I4);
gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(int)}));
Run Code Online (Sandbox Code Playgroud)

它按预期工作,并在控制台上打印500.

我尝试创建double数组的方式如下所示.

LocalBuilder arr = gen.DeclareLocal(typeof(double));
gen.Emit(OpCodes.Ldc_I4_1);
gen.Emit(OpCodes.Newarr, typeof(double));
gen.Emit(OpCodes.Stloc, arr);
gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldc_R8, 500D);
gen.Emit(OpCodes.Stelem_R8);

gen.Emit(OpCodes.Ldloc, arr);
gen.Emit(OpCodes.Ldc_I4_0);
gen.Emit(OpCodes.Ldelem_I8);
gen.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[]{typeof(double)}));
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,当我使用pereview它检查生成的程序集时,给了我以下错误.

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.1
Copyright (c) Microsoft Corporation.  All rights reserved.

[IL]: Error: [C:\temp\Research\Research\bin\Debug\MyMod.exe : Foo::Main][offset 0x00000006][found ref array …
Run Code Online (Sandbox Code Playgroud)

c# il

7
推荐指数
1
解决办法
1962
查看次数

cecil:Instruction.Operand类型对应于Instruction.OpCode.Code值

是否有任何文档或是否有一部分cecil源代码我可以参考,以全面了解Operandcecil将用于给定Code值的类型?例如:我可以搜集来自MethodBodyRocksLdloc接受一个Operand类型的VariableDefinition,但我一直无法追查下来用于其他一些指令代码.

c# mono il cil mono.cecil

7
推荐指数
2
解决办法
2892
查看次数

为什么IF和条件运算符之间的IL有这么大差异?

C#有一个条件运算符和IF语句,我怀疑条件运算符只是语法糖.因此在编译时它将与IF操作相同.

然而,他们没有(见下文),他们确实有不同的IL.试图绕过它,我的假设是,这是条件运算符得到的性能优化,因为它的范围有限.

想知道我的假设是否正确,也许还有更多内容?

同样在IF的IL中,有一些关于int值的检查(L_000c,L_000d,L_000f),我无法弄清楚其含义.这使我认为这是一个更强大的解决方案,因为IF的范围更广,代价是性能.


IF代码

var result = "";
if (Environment.Is64BitOperatingSystem)
{
    result = "Yes";
}
else
{
    result = "No";
}
Console.WriteLine(result);
Run Code Online (Sandbox Code Playgroud)

条件运算符的代码(我意识到差异,但无论我如何改变它 - 分配给变量等......它几乎没有区别)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No");
Run Code Online (Sandbox Code Playgroud)

IL为IF

L_0001: ldstr ""
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem()
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d
L_0013: nop 
L_0014: ldstr "Yes"
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025
L_001d: nop 
L_001e: ldstr "No"
L_0023: stloc.0 
L_0024: nop …
Run Code Online (Sandbox Code Playgroud)

c# il

7
推荐指数
1
解决办法
219
查看次数

关闭一个错误和变异测试

在为我最喜欢的突变测试框架(NinjaTurtles)编写"Off By One"变异测试程序的过程中,我编写了以下代码,以便提供检查我的实现的正确性的机会:

public int SumTo(int max)
{
    int sum = 0;
    for (var i = 1; i <= max; i++)
    {
        sum += i;
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

现在这看起来很简单了,并没有让我觉得尝试改变IL中的所有文字整数常量会有问题.毕竟,只有3(the 0,the 1,and ++).

错误!

在第一次运行中它变得非常明显,它在这个特定的实例中永远不会起作用.为什么?因为将代码更改为

public int SumTo(int max)
{
    int sum = 0;
    for (var i = 0; i <= max; i++)
    {
        sum += i;
    }
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

只在总和上加0(零),这显然没有效果.不同的故事,如果它是多组,但在这种情况下,它不是.

现在有一个相当简单的算法来计算整数之和

sum = max * (max + 1) / 2;
Run Code Online (Sandbox Code Playgroud)

我可以轻易地使突变失败,因为从任一常数中加1或减1会导致错误.(鉴于此max >= …

c# algorithm il mutation-testing ninja-turtles

7
推荐指数
1
解决办法
932
查看次数

IL和论点

IL有一些操作参数的操作码,例如Ldarg.0,Ldarg.1等等.

我知道在call执行操作码之前,这些参数被压入堆栈,在某些情况下Ldarg.0用于获取对this(例如成员)的引用

我的问题是:在启动呼叫时存储的参数在哪里?是否可以从执行的调用中访问调用者堆栈的副本?

我在哪里可以找到有关该主题的更多信息?

更新

我知道虚拟机是抽象的,JIT编译器负责处理这些问题,但让我们想象一下IL是否被解释,就像它在.NET Micro Framework上一样

c# clr il cil

7
推荐指数
3
解决办法
2920
查看次数

protobuf-net如何处理只读字段?

我使用protobuf-net来序列化/反序列化我的数据.

我有一些相当简单的类,所以这不是真正的问题.

据我所知,protobuf-net使用IL生成来创建序列化/反序列化代码.虽然我的模型中只有字段,但我想知道用IL写这样一个字段怎么可能?我可以清楚地看到它运作良好,但我不知道为什么......

我试图在代码中窥探它,但它有点太复杂了.

我自己尝试生成此类代码总是会导致IL验证程序错误.

c# il readonly protobuf-net

7
推荐指数
1
解决办法
2057
查看次数