我无法在SO或互联网上找到类似的问题/答案,并且这个问题可能无用,这可能是我在MSIL上阅读时遇到的一个问题.我非常好奇理解IL操作执行在我的场景中是如何工作的,即使这不是一个我没有其他人要问的实际问题.
前提:
请记住,MSIL命令和函数的执行分三步完成:
步骤1和3是可选的.例如,void函数不会将返回值推送到堆栈.
我知道这是一种方法确定需要多少"处理能力"的方法,但为了我的好奇心,我们可以考虑这两个非常基本的方法:
第一种方法:
void Method1()
{
var result = 1+1;
}
Run Code Online (Sandbox Code Playgroud)
第二种方法:
int Method2()
{
var result = 1+1;
return result;
}
Run Code Online (Sandbox Code Playgroud)
题:
因为void方法不会推送返回值(或者是否存在隐式返回)这是否意味着在执行时需要较少的开销而不是第二种方法?
我看到一个帖子IKVM.Reflection由Marc Gravell,这里是我的发现在IKVM 用户指南:
使用IKVM.NET有两种主要方式:
- 动态:在此模式下,Java类和jar直接用于在.NET运行时上执行Java应用程序.Java字节码即时转换为CIL,无需进一步的步骤.此模式支持完整的Java类加载器模型.
- 静态地说:......
我想用它在WinRT应用程序中发出和执行IL.有什么根本问题可以解决这个问题吗?像Microsoft的政策,或阻止从IKVM执行(可能修补的)Reflection&IL Emitting代码的技术限制?
如果这不可能,是否有任何选项在运行时加载程序集(假设我在外部服务器上发出它们并从那里下载到本地应用程序文件夹)?
我正在考虑实例方法Object.Equals(Object).使用反射,可以将此方法的IL作为字节数组获取,如下所示:
var mi = typeof(object).GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public);
var mb = mi.GetMethodBody();
var bytes = mb.GetILAsByteArray();
Run Code Online (Sandbox Code Playgroud)
我有两台PC:一台是运行Windows XP的32位机器,另一台是Windows 7的64位机器.两台机器都安装了.NET Framework 4.0.30319 SP1Rel.
在x86机器上,生成的数组是:
[0]: 2
[1]: 3
[2]: 40
[3]: 122
[4]: 67
[5]: 0
[6]: 6
[7]: 42
Run Code Online (Sandbox Code Playgroud)
但是在x64机器上,我得到了这个:
[0]: 2
[1]: 3
[2]: 40
[3]: 123
[4]: 67
[5]: 0
[6]: 6
[7]: 42
Run Code Online (Sandbox Code Playgroud)
第四个字节是不同的.
现在我知道mscorlib在64位平台上有两种版本.然而,ILDASM揭示了这种方法的IL在风味之间和机器之间是相同的.在x64机器上,我在"任何CPU"和"x86"都定位了上面的代码,但结果是一样的.
所以我的问题是,任何人都可以解释这两台机器之间的差异吗?
UPDATE
这是Object.Equals(Object)的C#和IL:
public virtual bool Equals(object obj)
{
return RuntimeHelpers.Equals(this, obj);
}
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call bool …Run Code Online (Sandbox Code Playgroud) 值类型可以存储在线程的堆栈中,IL在执行堆栈中运行(抽象概念).
int y=0;
int a=0;
int b=0;
int x = y + (a - b);
IL_0001: ldc.i4.0
IL_0002: stloc.0 // y
IL_0003: ldc.i4.0
IL_0004: stloc.1 // a
IL_0005: ldc.i4.0
IL_0006: stloc.2 // b
IL_0007: ldloc.0 // y
IL_0008: ldloc.1 // a
IL_0009: ldloc.2 // b
IL_000A: sub
IL_000B: add
IL_000C: stloc.3 // x
Run Code Online (Sandbox Code Playgroud)
现在stloc.0弹出执行堆栈中的值并存储到本地变量列表中.因此,局部变量列表必须存储在执行堆栈以外的其他空间中.什么是局部变量列表?它是一个线程的堆栈吗?
另外,哪个堆栈.maxstack = 3参考方法?它是局部变量列表的大小吗?或者将额外存储的最大大小推入执行堆栈?
在我看来,执行堆栈是正确的堆栈,因为它只支持push和pop.局部变量列表支持load索引和store索引.这与堆栈有什么关系?
ECMA 335 I.12.3机器状态明确回答了我的问题.
我正在尝试生成动态方法。假设我arg在堆栈中有 bool 值。我想调用一个方法,该方法接受int将bool通过简单规则从该值转换的类型参数arg ? 1 : 0。对于一些示例代码,生成的 IL 代码如下:
//bool value is already pushed into stack
IL_003d: brtrue.s IL_0042
IL_003f: ldc.i4.0
IL_0040: br.s IL_0043
IL_0042: ldc.i4.1
IL_0043: callvirt --methodName--
Run Code Online (Sandbox Code Playgroud)
发射时OpCodes.Brtrue_S以及OpCodes.Br_S如何正确识别要跳转到的偏移量?
我认为我的问题最好用一个例子来问
Method1(variable var1, variable var2)
{
Method2([null or default value goes here], var1, var2)
}
Method2(variable newvar, variable var1, variable var2)
{
//functionality
}
Run Code Online (Sandbox Code Playgroud)
编译器是否会通过将对方法 1 的所有调用更改为对方法 2 的调用来优化我们的代码?我认为它会内联该方法。但是,如果 method2 调用 3,而 3 又调用 4,而 4 又调用 5,而 5 又调用 6,会怎样呢?编译器是否会将 method1 调用更改为对方法 6 的调用,并使用其将具有的值?
我试图从一个接口创建一个代理类。在方法中,我只想收集对象数组中的所有参数并传递给已知方法。到目前为止,我已经设法让它在没有参数和返回类型的情况下工作。一旦我尝试创建我的数组,我就会收到“附加信息:公共语言运行时检测到无效程序。”.. 真的不知道如何从这里调试,IL 代码似乎是正确的(?)。
public class Program
{
static void Main(string[] args)
{
var v = CreateProxy<IFoo>();
v.DoSomething();
}
public static void TheMethod(object[] args)
{
}
public interface IFoo
{
void DoSomething();
}
public static T CreateProxy<T>()
{
var interfaceType = typeof(T);
AssemblyName assemblyName = new AssemblyName(string.Format("tmp_{0}", interfaceType.FullName));
string moduleName = string.Format("{0}.dll", assemblyName.Name);
string ns = interfaceType.Namespace;
if (!string.IsNullOrEmpty(ns))
ns += ".";
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave);
var module = assembly.DefineDynamicModule(moduleName, false);
var type = module.DefineType(String.Format("{0}Proxy_{1}", ns, interfaceType.Name), TypeAttributes.Class | TypeAttributes.AnsiClass |TypeAttributes.Sealed …Run Code Online (Sandbox Code Playgroud) 我花了好几个小时试图找出问题所在.我知道程序是有用的,因为我通过在MonoDevelop中调试.il来测试,但是我无法通过它进行编译.这是命令提示符下的日志:
任何帮助赞赏.
是否可以复制顶部堆栈项并将其推回?我只知道使用helper局部变量的解决方案,如下所示:
stloc.n
ldloc.n
ldloc.n
Run Code Online (Sandbox Code Playgroud)
是否存在用于复制堆栈项的IL指令?是否可以避免使用辅助局部变量?
使用c#,Net framework 4.5 notePad
尝试理解CIL(IL)语言的原理.目前创建2个简单方法
public static Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public Int32 Add1(Int32 a, Int32 b)
{
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
在ildasm.exe打开后得到了

题
为什么在Add方法CIL中使用堆栈0中的加载参数和堆栈1中的第二个 - 在方法Add1中使用堆栈0或者我错过了什么?