2010-05-21 35 views
6

Tôi đã nhìn vào mã IL của một phương pháp còn hiệu lực với Reflector và tôi đã chạy vào trong này:Hướng dẫn ngắn gọn về IL không ngắn?

L_00a5: leave.s L_0103 

dẫn với hậu tố .s có nghĩa vụ phải có một toán hạng int8, và đủ chắc chắn this should be the case with Leave_S as well. Tuy nhiên, 0x0103 là 259, vượt quá dung lượng của một int8. Phương pháp này bằng cách nào đó làm việc, nhưng khi tôi đọc các hướng dẫn với phương pháp Mono.Reflection.Disassembler.GetInstructions nó lấy

L_00a5: leave.s L_0003 

có nghĩa là, 3 thay vì 259, bởi vì nó được coi là một int8. Vì vậy, câu hỏi của tôi: làm thế nào là hướng dẫn ban đầu (leave.s L_0103) có thể? Tôi đã xem số ECMA documentation for that (Phân vùng III: Bộ chỉ dẫn CIL) và tôi không thể tìm thấy bất kỳ điều gì giải thích nó.

Bất kỳ ý tưởng nào? Cảm ơn.


EDIT # 1: Ok, tôi là thằng ngốc. Trong trường hợp các lệnh rẽ nhánh, giá trị offset phải được tính từ đầu lệnh sau lệnh hiện tại. Tôi thề tôi đã đọc tài liệu, nhưng bằng cách nào đó tôi đã bỏ qua điều đó. Trong phòng thủ của tôi, hôm nay tôi khá ốm. Thở dài.

Cảm ơn bạn. (Và nhờ vì không gọi tôi là một thằng ngốc, mặc dù đây là khá ngu ngốc: P)


EDIT # 2: Bằng cách này, trong trường hợp có ai quan tâm, khi Mono.Reflection.Disassembler.GetInstructions disassembles các hướng dẫn nó thay đổi ý nghĩa của toán hạng trong hướng dẫn chi nhánh. Cụ thể, như nó đã được chỉ ra, toán hạng của lệnh chi nhánh biểu diễn offset từ đầu lệnh kế tiếp, không phải từ 0. Tuy nhiên, Mono.Reflection trả về giá trị bù trừ bắt đầu từ 0 (có thể là lý do tại sao tôi nhầm lẫn; mặc dù nó không giải thích cách tôi quản lý để bỏ qua một phần tài liệu).

Một trích MethodBodyReader.ReadOperand(Instruction instruction):

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

Như bạn có thể nhìn thấy nó thêm il.position, đó là bù đắp (bắt đầu từ 0) của lệnh tiếp theo. Ngoài ra, nó phôi thành sbyte, đó là lý do tôi nhận được 3 thay vì 259. Điều này dường như là một lỗi (bù đắp bắt đầu từ 0 có thể lớn hơn sbyte). Tôi sẽ hỏi Jb Evain (tác giả) và báo cáo lại.


EDIT # 3: Ông đã không trả lời được nêu ra nhưng tôi đã thay đổi nó để:

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

và nó dường như đã giải quyết vấn đề của tôi. Tôi chuyển sang sbyte để lấy dấu hiệu đúng, trong trường hợp đó là một bước nhảy ngược (độ lệch âm), và sau đó khi tôi thêm il.position (là int), kết quả là int.

Tôi sẽ cho bạn biết những gì anh ấy nói.


EDIT # 4: Tôi quên báo cáo lại. Tác giả xác nhận đây là một lỗi.

+0

để bảo vệ bạn, từ kinh nghiệm trong quá khứ với ngôn ngữ lắp ráp cho vi điều khiển nhỏ (Motorola MC68HC11?) Và hướng dẫn chi nhánh tương đối tôi đã tìm kiếm từ "offset" trong tài liệu. Nếu không có kinh nghiệm trước đó, nó sẽ khá dễ bỏ lỡ. Các nhánh tương đối BTW cũng là một lợi ích lớn trong mã có thể định vị lại trên PC, ví dụ: Các tệp DLL có thể tải tại các địa chỉ bộ nhớ khác nhau, vì trình tải động không cần phải sửa chúng. Tất nhiên trong .NET có một JIT liên quan để tối ưu hóa này không thực sự áp dụng ... nó chỉ được thực hiện để tiết kiệm không gian. –

Trả lời

3

hướng dẫn mục tiêu, thể hiện dưới dạng một 1-byte đã ký bù đắp từ đầu của hướng dẫn theo hướng dẫn hiện hành

0xa5 là trong vòng 127 byte của 0x103. Không có cách nào cho một leave.s để đạt được từ 0xA5 đến 0x03 tuy nhiên.

Các vấn đề liên quan