Краткие инструкции IL не являются короткими? - PullRequest
6 голосов
/ 21 мая 2010

Я искал код IL действительного метода с Reflector, и я столкнулся с этим:

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)


EDIT # 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 : Я забыл сообщить. Автор подтверждает, что это была ошибка.

1 Ответ

3 голосов
/ 21 мая 2010

целевая инструкция, представленная 1-байтовым смещением со знаком от начала инструкции, следующей за текущей инструкцией

0xA5 находится в пределах 127 байтов от 0x103. Однако у leave.s нет возможности достичь уровня от 0xA5 до 0x03.

...