6

我正在使用 Reflector 查看有效方法的 IL 代码,我遇到了这个问题:

L_00a5: leave.s L_0103

带有后缀.s的指令应该采用 int8 操作数,果然这也应该是 Leave_S 的情况。但是0x0103是259,超出了一个int8的容量。该方法以某种方式起作用,但是当我使用Mono.Reflection.Disassembler.GetInstructions它检索的方法阅读说明时

L_00a5: leave.s L_0003

也就是说,3 而不是 259,因为它应该是 int8。所以,我的问题是:原始指令 ( leave.s L_0103) 怎么可能?我已经查看了ECMA 文档(第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 开始的偏移量可能大于 a 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:我忘了报告。作者确认这是一个错误。

4

1 回答 1

3

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

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

于 2010-05-21T12:20:05.907 回答