내가 리플렉터있는 유효한 방법의 IL 코드를 찾고 있었고, 난이로 실행했습니다일리노이 간략한 설명이 짧지 않습니까?
L_00a5: leave.s L_0103
지침을 접미사 .s
로는 INT8 연산을하기로하고, this should be the case with Leave_S as well 충분히 확인된다. 그러나 0x0103은 259이며 이는 int8의 용량을 초과합니다. 방법은 어떻게 든 작동하지만이 방법의 지침을 읽을 때가 INT8해야하는데 있기 때문에,
L_00a5: leave.s L_0003
입니다
, 3 대신 259를 검색 Mono.Reflection.Disassembler.GetInstructions
. 그래서, 제 질문 : 원래의 지시 (leave.s L_0103
)는 어떻게 가능합니까? ECMA documentation for that (파티션 III : CIL 명령어 세트)을 살펴본 결과 설명을 찾을 수 없습니다.
아이디어가 있으십니까? 감사.
수정 # 1 : 좋아, 나는 바보입니다. 분기 명령어의 경우 오프셋은 현재 명령어 다음의 명령어 시작부터 계산해야합니다. 나는 설명서를 읽었는데 맹세했지만 어쨌든 그걸 건너 뛰었습니다. 내 방어에서, 나는 오늘 꽤 아파. 한숨.
감사합니다.
편집 # 2 : 그런데, 아무도 관심이 경우, Mono.Reflection.Disassembler.GetInstructions
그것을 변경 지침을 분해 할 때 : (P이 꽤 바보에도 불구하고, 나에게 바보를 호출하지 않는 덕분) 분기 명령에서 피연산자의 의미. 특히 지적했듯이 분기 명령어의 피연산자는 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
으로 캐스팅됩니다. 이는 내가 259 대신 3을 얻는 이유입니다. 이것은 버그 (0에서 시작하는 오프셋은 sbyte
보다 클 수 있습니다) 인 것으로 보입니다. 나는 Jb Evain (저자)에게 물어보고 다시보고 할 것이다.
수정 # 3 : 그는 아직 대답하지 않은하지만 난 그것을 변경했습니다 :
switch (instruction.OpCode.OperandType) {
...
case OperandType.ShortInlineBrTarget:
instruction.Operand = ((sbyte) il.ReadByte()) + il.position;
break;
...
}
내 문제를 해결 한 것으로 보인다. 나는 sbyte
로 캐스팅하여 역방향 점프 (음수 오프셋) 인 경우에 대비하고, int
인 il.position
을 추가하면 결과는 int
입니다.
나는 그가 당신이 어쨌든 말하는 것을 알려줄 것입니다.
편집 # 4 : 내가 다시보고하는 것을 잊었다. 저자는 이것이 버그라고 확인합니다. 1 바이트로 표현
작은 마이크로 컨트롤러 (Motorola MC68HC11 누구?) 및 상대 분기 지침에 대한 어셈블리 언어에 대한 과거 경험에서 문서에서 "offset"단어를 검색했습니다. 그 이전의 경험이 없었다면 그리워하기 쉽습니다. 또한 BTW 상대 분기는 PC에서 재배치 가능한 코드의 큰 이점입니다. DLL은 서로 다른 메모리 주소에서로드 할 수 있습니다. 동적 로더가이를 수정하지 않아도되기 때문입니다. 물론 .NET에는 JIT가 포함되어 있으므로이 최적화는 실제로 적용되지 않습니다 ... 단지 공간을 절약하기 위해 완료되었습니다. –