2010-05-21 9 views
6

yo estaba buscando en el código IL de un método válido con reflector y me he encontrado con esto:¿Las instrucciones cortas de IL no son cortas?

L_00a5: leave.s L_0103 

instrucciones con el sufijo .s se supone que tienen un operando INT8, y bastante seguro this should be the case with Leave_S as well. Sin embargo, 0x0103 es 259, que excede la capacidad de un int8. El método funciona de alguna manera, pero cuando leí las instrucciones con el método Mono.Reflection.Disassembler.GetInstructions recupera

L_00a5: leave.s L_0003 

es decir, 3 en lugar de 259, porque se supone que es un INT8. Entonces, mi pregunta: ¿cómo es posible la instrucción original (leave.s L_0103)? He consultado el ECMA documentation for that (Partición III: CIL Instruction Set) y no encuentro nada que lo explique.

¿Alguna idea? Gracias.


editar # 1: Ok, Soy un idiota. En el caso de las instrucciones de derivación, el desplazamiento se debe contar desde el comienzo de la instrucción siguiendo las instrucciones actuales. Juro que leí la documentación, pero de alguna manera logré omitir eso. En mi defensa, estoy bastante enfermo hoy. Suspiro.

Gracias. (Y gracias por no llamarme idiota, a pesar de que esto era bastante idiota: P)


editar # 2: Por cierto, por si alguien está interesado, cuando Mono.Reflection.Disassembler.GetInstructions desmonta las instrucciones que cambia el significado del operando en instrucciones de bifurcación. En particular, como se ha señalado, el operando de una instrucción de bifurcación representa el desplazamiento desde el comienzo de la siguiente instrucción, no desde 0. Sin embargo, Mono.Reflection devuelve el desplazamiento comenzando en 0 (que puede ser el motivo por el que estaba confundido, aunque no explica cómo pude saltear parte de la documentación).

Un extracto de MethodBodyReader.ReadOperand(Instruction instruction):

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

Como se puede ver que añade il.position, que es el offset (comenzando en 0) de la siguiente instrucción. Además, arroja a sbyte, que es la razón por la que recibo 3 en lugar de 259. Esto parece ser un error (el desplazamiento a partir de 0 puede ser mayor que sbyte). Preguntaré a Jb Evain (el autor) e informaré.


editar # 3: Él no ha recibido ninguna respuesta, pero he cambiado a:

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

y parece haber resuelto mi problema. Eché a sbyte para obtener el signo correcto, en caso de que sea un salto hacia atrás (desplazamiento negativo), y luego cuando agregue il.position (que es un int) el resultado es un int.

Le dejaré saber lo que él dice de todos modos.


editar # 4: Se me olvidó informar. El autor confirma que esto fue un error.

+0

en su defensa, de la experiencia pasada con el lenguaje ensamblador para microcontroladores pequeños (Motorola MC68HC11 alguien?) Y las instrucciones de bifurcación relativos fui en busca de la palabra "compensación" en la documentación. Sin esa experiencia previa, sería bastante fácil perderse. BTW ramas relativas son también un gran beneficio en código reubicable en los ordenadores, por ejemplo DLL que se puede cargar en diferentes direcciones de memoria, ya que el cargador dinámico no tiene que arreglarlos. Por supuesto, en .NET hay un JIT involucrado por lo que esta optimización no se aplica realmente ... que acaba de hacer para ahorrar espacio. –

Respuesta

3

instrucción objeto, representado como un 1-byte con signo desplazado con respecto al inicio de la instrucción que sigue a la instrucción actual

0xA5 está dentro de 127 bytes de 0x103. No hay manera de leave.s acceso desde 0xA5 a 0x03 sin embargo.

Cuestiones relacionadas