IL 简短指令不短吗?

发布于 2024-09-02 13:52:57 字数 2050 浏览 8 评论 0原文

我正在使用 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 instructions) 的摘录:

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:我忘了回报。作者确认这是一个错误。

I was looking at the IL code of a valid method with Reflector and I've run into this:

L_00a5: leave.s L_0103

Instructions with the suffix .s are supposed to take an int8 operand, and sure enough this should be the case with Leave_S as well. However, 0x0103 is 259, which exceeds the capacity of an int8. The method somehow works, but when I read the instructions with method Mono.Reflection.Disassembler.GetInstructions it retrieves

L_00a5: leave.s L_0003

that is, 3 instead of 259, because it's supposed to be an int8. So, my question: how is the original instruction (leave.s L_0103) possible? I have looked at the ECMA documentation for that (Partition III: CIL Instruction Set) and I can't find anything that explains it.

Any ideas? Thanks.


EDIT #1: Ok, I'm an idiot. In the case of branch instructions the offset must be counted from the beginning of the instruction following the current instruction. I swear I read the documentation, but somehow I managed to skip that. In my defence, I'm pretty sick today. Sigh.

Thank you.
(And thanks for not calling me an idiot, even though this was pretty idiotic :P)


EDIT #2: By the way, in case anyone is interested, when Mono.Reflection.Disassembler.GetInstructions disassembles the instructions it changes the meaning of the operand in branch instructions. In particular, as it has been pointed out, the operand of a branch instruction represents the offset from the beginning of the next instruction, not from 0. However, Mono.Reflection gives back the offset starting at 0 (which may be why I was confused; although it doesn't explain how I managed to skip part of the documentation).

An extract of MethodBodyReader.ReadOperand(Instruction instruction):

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

As you can see it adds il.position, which is the offset (starting at 0) of the next instruction. Also, it casts to sbyte, which is the reason I'm getting 3 instead of 259. This appears to be a bug (the offset starting from 0 may be larger than an sbyte). I'll ask Jb Evain (the author) and report back.


EDIT #3: He hasn't answered yet but I've changed it to:

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

and it seems to have solved my problem. I cast to sbyte to get the sign right, in case it's a backwards jump (negative offset), and then when I add il.position (which is an int) the result is an int.

I'll let you know what he says anyway.


EDIT #4: I forgot to report back. The author confirms this was a bug.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

划一舟意中人 2024-09-09 13:52:57

目标指令,表示为距当前指令后面的指令开头的 1 字节有符号偏移

位于 0x103 的 127 字节以内。然而,leave.s 无法从 0xA5 到达 0x03。

target instruction, represented as a 1-byte signed offset from the beginning of the instruction following the current instruction

0xA5 is within 127 bytes of 0x103. There's no way for a leave.s to reach from 0xA5 to 0x03 however.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文