标签: 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
查看次数

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的问题

我刚开始看一下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
查看次数

通用结构的大小

我需要找出一个通用结构的大小(我不能像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
查看次数

表达身体的成员如何区分虚空和非虚空?

有了C#6表达身体的成员,我可以写:

public string FullName => $"{_firstName} {_lastName}";

我可以写:

static void Print(string message) => Console.WriteLine(message);

在第一个实例中,表达式返回一些东西.在第二个,它没有.

这里发生了什么,以确定如何"行动"而不需要任何额外的语法?或者它只是在编译期间查看方法签名的情况?

在不知道发生了什么的情况下,我不会把事情留给"正常工作".

.net c# il expression c#-6.0

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

是否有任何从Visual Studio项目中编译CIL代码的示例

我意识到已经被问及并回答Visual Studio不支持CIL/MSIL项目.该MSBuildContrib项目有ILASM任务,它允许您编译IL文件在制作的时候.

关于如何使用此任务的示例,Google搜索结果为空.

是否有任何使用ILASM作为Visual Studio解决方案的一部分的示例?我意识到#develope和ILIDE支持CIL ......这里的目标是编译一些CIL文件作为Visual Studio解决方案的一部分.

il cil visual-studio ilasm

5
推荐指数
2
解决办法
2565
查看次数

如何发出OpCodes.Constrained与OpCodes.Callvirt给定我有所需的MethodInfo和实例类型在手

我有一个递归函数emit : Map<string,LocalBuilder> -> exp -> unit,其中il : ILGenerator是全局的功能,exp是代表与情况的类型检查解析的语言判别工会InstanceCall of exp * MethodInfo * exp list * TypeType是一个属性exp代表表达的类型.

在下面的片段中,我试图为实例调用发出IL操作码,其中instance.Type可能是也可能不是ValueType.所以我理解我可以OpCodes.Constrained灵活高效地对引用,值和枚举类型进行虚拟调用.我是Reflection.Emit和机器语言的新手,因此理解链接文档OpCodes.Constrained并不适合我.

这是我的尝试,但结果是VerificationException"操作可能会破坏运行时的稳定性.":

let rec emit lenv ast =
    match ast with
    ...
    | InstanceCall(instance,methodInfo,args,_) ->
        instance::args |> List.iter (emit lenv)
        il.Emit(OpCodes.Constrained, instance.Type)
        il.Emit(OpCodes.Callvirt, methodInfo)
    ...
Run Code Online (Sandbox Code Playgroud)

查看文档,我认为关键可能是"托管指针,ptr,被推入堆栈.ptr的类型必须是thisType的托管指针(&).请注意,这与未加前缀的情况不同callvirt指令,它需要thisType的引用."

更新

谢谢@Tomas和@desco,我现在知道何时使用OpCodes.Constrained(instance.Type是一个ValueType,但是methodInfo.DeclaringType是一个引用类型).

但事实证明我还不需要考虑那个案例,而我真正的问题是堆栈上的实例参数:我花了6个小时才知道它需要一个地址而不是值(看DLR源码)代码给了我线索,然后在一个简单的C#程序上使用ilasm.exe说清楚了).

这是我的最终工作版本:

let rec emit lenv …
Run Code Online (Sandbox Code Playgroud)

.net f# il reflection.emit

5
推荐指数
1
解决办法
2473
查看次数