【问题标题】:IL short-form instructions aren't short?IL 短格式指令不短?
【发布时间】:2010-06-09 00:59:59
【问题描述】:

我正在使用 Reflector 查看有效方法的 IL 代码,但遇到了这样的情况:

L_00a5: leave.s L_0103

后缀为.s 的指令应该采用int8 操作数,当然this should be the case with Leave_S as well。但是0x0103是259,超出了一个int8的容量。该方法以某种方式有效,但是当我使用方法 Mono.Reflection.Disassembler.GetInstructions 阅读说明时,它会检索

L_00a5: leave.s L_0003

也就是说,3 而不是 259,因为它应该是 int8。所以,我的问题是:原始指令 (leave.s L_0103) 怎么可能?我查看了ECMA documentation for thatPartition III:CIL 指令集),但找不到任何解释。

有什么想法吗?谢谢。


编辑#1:好吧,我是个白痴。在分支指令的情况下,偏移量必须从当前指令之后的指令的开头开始计算。我发誓我阅读了文档,但不知何故我设法跳过了它。在我的辩护中,我今天病得很重。叹息。

谢谢。 (感谢你没有叫我白痴,尽管这很白痴:P)


编辑#2:顺便说一句,如果有人感兴趣,当Mono.Reflection.Disassembler.GetInstructions 反汇编指令时,它会改变分支指令中操作数的含义。特别是,正如已经指出的那样,分支指令的操作数表示从下一条指令开始的偏移量,而不是从 0。但是,Mono.Reflection 会返回从 0 开始的偏移量(这可能是我感到困惑的原因;虽然它没有解释我是如何设法跳过部分文档的)。

MethodBodyReader.ReadOperand(Instruction instruction) 的摘录:

switch (instruction.OpCode.OperandType) {
...
case OperandType.ShortInlineBrTarget:
    instruction.Operand = (sbyte) (il.ReadByte () + il.position);
    break;
...
}

如您所见,它添加了il.position,这是下一条指令的偏移量(从 0 开始)。此外,它转换为sbyte,这就是我得到3 而不是259 的原因。这似乎是一个错误(从0 开始的偏移量可能大于sbyte)。我会问 Jb Evain(作者)并报告。


编辑#3:他还没有回答,但我已将其更改为:

switch (instruction.OpCode.OperandType) {
...
case OperandType.ShortInlineBrTarget:
    instruction.Operand = ((sbyte) il.ReadByte ()) + il.position;
    break;
...
}

它似乎解决了我的问题。我投射到sbyte 以使符号正确,以防它是向后跳转(负偏移),然后当我添加il.position(这是一个int)时,结果是一个int

无论如何,我会让你知道他说了什么。


编辑#4:我忘了报告。作者确认这是一个错误。

【问题讨论】:

  • 为您辩护,根据过去使用小型微控制器(摩托罗拉 MC68HC11 有人吗?)的汇编语言和相关分支指令的经验,我在文档中搜索了“偏移”一词。如果没有先前的经验,很容易错过。顺便说一句,相对分支在 PC 上的可重定位代码中也是一个很大的好处,例如可以在不同内存地址加载的 DLL,因为动态加载器不必修复它们。当然,在 .NET 中涉及到 JIT,所以这种优化并不真正适用……它只是为了节省空间。

标签: c# .net reflection reflection.emit il


【解决方案1】:

目标指令,表示为从当前指令之后的指令开头的 1 字节带符号偏移量

0xA5 在 0x103 的 127 字节内。但是,leave.s 无法从 0xA5 到达 0x03。

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2018-09-16
    • 2018-04-09
    • 1970-01-01
    • 2022-01-19
    相关资源
    最近更新 更多