标签: il

发送IL以调用Math函数

C#调用

Math.Pow(2,3);
Run Code Online (Sandbox Code Playgroud)

在ILDASM中:

ldc.r8   2.
ldc.r8   3.
call     float64[mscorlib]System.Math::Pow(float64, float64)
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我如何通过ILGenerator发出该调用语句吗?谢谢.

.net il cil

6
推荐指数
1
解决办法
1375
查看次数

为什么LocalBuilder.SetLocalSymInfo没有发出变量名?

我试图运行出现的文档页面上的示例代码System.Reflection.Emit.LocalBuilder类,但它看来,调用LocalBuilder.SetLocalSymInfo(string, int, int)没有做任何事情,因为IL反汇编显示了这个作为IL的SampleAssembly.dll:

.method public static string  Function1(int32 A_0) cil managed
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init (string V_0,
           int32 V_1)
  IL_0000:  ldarg.0
  IL_0001:  stloc.1
  IL_0002:  ldstr      "string value"
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  ret
} // end of method Example::Function1
Run Code Online (Sandbox Code Playgroud)

为什么不在Dissasembler中列出变量名(myStringmyInt)?

环境信息:

  • Windows 7 64位
  • Visual Studio 2010 Professional SP1
  • .Net 4.0.30319 SP1
  • 目标框架:.Net 4客户端配置文件
  • 调试配置(对于使用System.Reflection.Emit的程序)

编辑:正如我在评论中提到的,有一个SampleAssembly.pdb文件与SampleAssembly.dll文件一起生成.

il reflection.emit .net-4.0 variable-names debug-symbols

6
推荐指数
1
解决办法
309
查看次数

ldstr在内部实现newobj吗?

众所周知,字符串是隐式实例化的,这意味着我们不必使用new它来获取对象的对象的引用.

因此,我一直认为框架正在处理这个问题,因此如果我这样做,我会得到相同的IL:

String first = new String(new char[] {'a'});
string second = "a";
Run Code Online (Sandbox Code Playgroud)

然而,似乎第一行是使用newobj instance void [mscorlib]System.String::.ctor(char[]) 和第二行完成的ldstr "a".

那么为了获得一个字符串引用,ldstr内部调用newobj,我在哪里可以看到规范/细节来支持它?

.net c# il jit cil

6
推荐指数
1
解决办法
818
查看次数

C#动态类型导致使用IL中的反射解析Console.WriteLine

我一直在使用LINQPad中的一些C#语句来理解发出的中间语言代码.

我首先尝试了以下代码:

var Container = new {Name = "James"};
Console.WriteLine(Container.Name);
Run Code Online (Sandbox Code Playgroud)

并且看到以下六行IL发射:

IL_0001:  ldstr       "James"
IL_0006:  newobj      <>f__AnonymousType0<System.String>..ctor
IL_000B:  stloc.0     
IL_000C:  ldloc.0     
IL_000D:  callvirt    <>f__AnonymousType0<System.String>.get_Name
IL_0012:  call        System.Console.WriteLine
Run Code Online (Sandbox Code Playgroud)

这是我所期望的,并且非常好地演示了匿名类型是如何只读/不可变的,因为没有set_Name属性.

接下来我尝试了这些陈述:

dynamic Container = new System.Dynamic.ExpandoObject();
Container.Name = "James";
Console.WriteLine(Container.Name);
Run Code Online (Sandbox Code Playgroud)

这会导致大量的IL被释放.我不会在这里粘贴它,但你可以在这个pastebin中找到它.

我理解在管理动态类型和ExpandoObject方面存在相当多的开销,但我不明白为什么看起来System.Console.WriteLine在这种情况下调用是通过内部反射来执行的.

IL_0072:  ldstr       "WriteLine"
....
IL_00BF:  ldtoken     System.Console
Run Code Online (Sandbox Code Playgroud)

在第一段代码中,在检索并存储属性之后,它是一个调用的单行IL语句System.Console.WriteLine.

那么为什么一个dynamic类型的呼叫需要额外的所有这些?

c# compiler-construction reflection il dynamic

6
推荐指数
1
解决办法
1543
查看次数

基于反汇编的简单C#代码的手工编码IL的问题

我刚开始看一下IL,我很好奇我的尝试(如下所示)从编译器输出中删除多余的代码有任何意想不到的副作用.

关于结果的几个问题:

  1. 原始操作中nop操作的目的是什么?
  2. 原始方法结束时br.s的目的是什么?
  3. 重写版本是否以任何方式不正确?

原始C#代码:

class Program {
    public static int Main() {
        return Add(1, 2);
    }
    public static int Add(int a, int b) {
        return a + b;
    }
}
Run Code Online (Sandbox Code Playgroud)

csc.exeildasm.exe(原始)编译和拆解它:

  .method public hidebysig static int32  Main() cil managed
  {
    .entrypoint
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldc.i4.1
    IL_0002:  ldc.i4.2
    IL_0003:  call       int32 Program::Add(int32, int32)
    IL_0008:  stloc.0
    IL_0009:  br.s       IL_000b
    IL_000b:  ldloc.0
    IL_000c:  ret
  } 
  .method public hidebysig static int32  Add(int32 a, …
Run Code Online (Sandbox Code Playgroud)

c# il

6
推荐指数
1
解决办法
358
查看次数

为什么这个.Net IL无法验证?

我有一些我写的自定义IL,它不会通过PEVerify.我得到的错误是

$ peverify foo.exe

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

[IL]: Error: [Z:\virtualbox_shared\foo.exe : HelloWorld.Program::Main][offset 0x00000021] Stack height at all points must be determinable in a single forward scan of IL.
1 Error(s) Verifying foo.exe

然而,该程序将运行正常,没有任何例外.以下是相关方法的IL:

.method private static hidebysig
  default void Main (string[] args)  cil managed
{
// Method begins at RVA 0x2050
.entrypoint
// Code size 54 (0x36)
.maxstack 2

//custom IL
ldc.i4 1
ldc.i4 1
ceq
switch(first, second) …
Run Code Online (Sandbox Code Playgroud)

.net verification il peverify

6
推荐指数
1
解决办法
464
查看次数

通用结构的大小

我需要找出一个通用结构的大小(我不能像sizeof(T)或使用Marshal.SizeOf(...)0>给我一个错误)

所以我写道:

public static class HelperMethods
{
    static HelperMethods()
    {
        SizeOfType = createSizeOfFunc();
    }

    public static int SizeOf<T>()
    {
        return SizeOfType(typeof(T));
    }

    public static readonly Func<Type, int> SizeOfType = null;

    private static Func<Type, int> createSizeOfFunc()
    {
        var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { typeof(Type) });

        ILGenerator il = dm.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Sizeof); //needs to be il.Emit(OpCodes.Sizeof, typeof(something))
        il.Emit(OpCodes.Ret);

        var func = (Func<Type, int>)dm.CreateDelegate(typeof(Func<Type, int>));
        return func;
    }
}
Run Code Online (Sandbox Code Playgroud)

一个不同之处是il.Emit(OpCodes.Sizeof)需要一个参数,在创建方法(SizeOfType)时我无法传递它.如何使用IL将堆栈中的参数传递给il.Emit(OpCodes.Sizeof)?(或者是一个不同的解决方案,但我想缓存一个函数(委托)而不是第二个答案中提出的结果)

c# generics il structure sizeof

6
推荐指数
3
解决办法
7736
查看次数

使用Mono.Cecil替换对类型/命名空间的引用

背景(不必要,令人困惑,只为好奇)

我正在使用Unity3D for Mobile的免费版本,它不允许我System.Net.Sockets在移动设备上使用命名空间.问题是我正在使用.dll引用的编译库(即IKVM)System.Net.Sockets.我实际上并没有在IKVM中使用引用该引用的类System.Net.Sockets,因此我没有购买$ 3000 Unity Pro移动许可证,而是创建了一个Sockets名为的命名空间的存根库,dudeprgm.Net.Sockets它只是用存根替换了所有的类和方法(我这样做了Mono源代码).


我的问题

我需要将System.Net.Sockets.*我的dll中的所有引用替换为dudeprgm.Net.Sockets.*.我知道这样的事情是可能的并且由其他人完成(参见下面的编辑,在页面底部).我想知道自己该怎么做.

我能够使用Mono.Cecil提出以下代码.
它遍历所有IL指令,检查操作数是否为a InlineType,然后检查内联类型是否属于其中System.Net.Sockets,然后将其重命名为dudeprgm.Net.Sockets并写入.**我不确定这是否是在Mono.Cecil中进行"查找和替换"的正确方法.问题是,这并没有抓住所有Sockets用法(见下文).

private static AssemblyDefinition stubsAssembly;

static void Main(string[] args) {
    AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(args[0]);
    stubsAssembly = AssemblyDefinition.ReadAssembly("Socket Stubs.dll");
    // ...
    // Call ProcessSockets on everything
    // ...
    asm.Write(args[1]);
}

/*
 * This will be run on every property, constructor and method …
Run Code Online (Sandbox Code Playgroud)

c# il types replace mono.cecil

6
推荐指数
1
解决办法
3641
查看次数

检测双精度是否有限的最快方法是什么?

double在没有抛出异常的情况下,在IL中检测值是否为有限值(NaN和正/负无穷大)的最快方法是什么?

我正在考虑以下方法(仅为了方便读者使用c#表示法,在我的项目中,我使用的是IL):

  1. !double.IsNaN(x) && !double.IsInfinity(x) - 最明显的,也可能是最慢的,因为涉及2个方法调用.

  2. (*(((long*) &x)) & 0x7fffffffffffffffL) < 0x7ff0000000000000L

或在IL:

  ldloca x
  conv.u 
  ldind.i8 
  ldc.i8 0x7fffffffffffffff
  and 
  ldc.i8 0x7ff0000000000000
  clt 
Run Code Online (Sandbox Code Playgroud)

我对第二种方法的问题是:

  1. 根据我的研究,这应该精确地确定任何给定是否x是有限的.这是真的?

  2. 它是解决IL中任务的最佳方式(性能方面),还是有更好(更快)的解决方案?

PS我非常感谢建议运行我自己的基准并找出答案,并且肯定会这样做.只是想到也许有人已经有类似的问题,并知道答案.PPS是的,我意识到我们在这里谈论的是纳秒,是的,它们对我的具体情况很重要

.net c# il

6
推荐指数
1
解决办法
1414
查看次数

为什么在MSIL中将RegexOptions编译为RegexOptions.None?

这段代码

  Regex regex = new Regex("blah", RegexOptions.Singleline & RegexOptions.IgnoreCase);
Run Code Online (Sandbox Code Playgroud)

编译后在ILSpy中看起来像这样:

  Regex regex = new Regex("blah", RegexOptions.None);
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,并且它是正则表达式在.Net 3.5中不匹配的原因吗?在4.5它工作.

.net c# regex il

6
推荐指数
1
解决办法
190
查看次数