2012-02-12 23 views
10

Tôi có thể biên dịch hướng dẫn sang bytecode và thậm chí thực hiện chúng dễ dàng nhưng hàm duy nhất tôi tìm thấy để trích CIL là GetILAsByteArray và, như tên ngụ ý, nó chỉ trả về byte chứ không phải lệnh CIL.Lập trình CIL

Vậy làm cách nào để bạn lập trình CIL trên .NET?

Lưu ý rằng tôi không muốn kết quả ở dạng người có thể đọc được. Tôi muốn viết metaprogram để thao tác CIL được tạo ra từ các chương trình khác.

+1

Khi @JohnPalmer đề xuất câu trả lời của anh ấy, [Mono.Cecil] (http://www.mono-project.com/Cecil) là một lựa chọn tốt cho việc này. [Ở đây] (http://plaureano.blogspot.com/2011/05/introduction-to-il-rewriting-with-cecil.html) là một blog tốt thảo luận về IL viết lại có thể hữu ích. –

Trả lời

8

Bạn có thể nhận được một cách hợp lý đến nay chỉ sử dụng các mảng byte từ GetILAsByteArray phương pháp, nhưng bạn' sẽ cần phải tự phân tích cú pháp các byte (nếu bạn không muốn dựa vào thư viện của bên thứ 3).

Cấu trúc của mảng là có một hoặc hai byte xác định lệnh theo sau là toán hạng cho lệnh (không có gì, một số mã thông báo 4 byte hoặc số 8 byte).

Để nhận mã, bạn có thể xem cấu trúc OpCodes (MSDN) từ System.Reflection.Emit. Nếu bạn liệt kê trên tất cả các lĩnh vực, bạn có thể khá dễ dàng xây dựng một bảng tra cứu để đọc các byte:

// Iterate over all byte codes to build lookup table 
for fld in typeof<OpCodes>.GetFields() do 
    let code = fld.GetValue(null) :?> OpCode 
    printfn "%A (%d + %A)" code.Name code.Size code.OperandType 

Thuộc tính code.Value mang đến cho bạn eithre byte hoặc int16 giá trị của mã. Thuộc tính code.Size cho bạn biết đây là 1 hoặc 2 mã byte và thuộc tính OperandType chỉ định đối số nào tuân theo mã (số byte và ý nghĩa là explained on MSDN). Tôi không nhớ chính xác bạn cần xử lý những thứ như mã thông báo như thế nào tức là MethodInfo, nhưng tôi đoán bạn sẽ có thể hiểu được điều đó!

9

Các Mono Cecil thư viện - http://www.mono-project.com/Cecil nên làm những gì bạn cần, tôi biết rằng nó được sử dụng trong ít nhất một Net profiler

+4

'Cecil' thực sự được sử dụng trong [ILSpy] (https://github.com/icsharpcode/ILSpy). – pad

+0

Bạn có thể muốn xem bài đăng trên blog này http://plaureano.blogspot.com/2011/05/introduction-to-il-rewriting-with-cecil.html để biết thêm thông tin về việc sử dụng Cecil để hoàn thành những gì bạn ' đang cố gắng làm. –

2

Tôi đã thực hiện một số thao tác IL với dự án Mono Cecil. Nó khá dễ dàng.

5

Một giải pháp thay thế thú vị để sử dụng Cecil là khôi phục dự án AbsIL. Cecil cũng được viết và sử dụng tốt, nhưng nó có lẽ không phải là cách bạn tiếp cận vấn đề nếu bạn đang viết nó trong F #. AbsIL là một dự án bắt đầu cùng lúc với F # để cho phép OCaml và F # đọc và viết IL, nó đã được thực hiện như dự án F # và bây giờ chỉ là phần cuối của trình biên dịch F #. Tuy nhiên mã để cả đọc và viết IL vẫn còn đó và có thể trong lý thuyết được tách ra từ trình biên dịch F # và được đưa vào thư viện có thể sử dụng theo đúng nghĩa của nó. Việc tách mã AbsIL khỏi phần còn lại của trình biên dịch F # không hoàn toàn nhỏ, nhưng có thể nếu bạn có một chút thời gian rảnh rỗi và một số lượng xác định nhất định. Nếu bạn cảm thấy thực sự dũng cảm, bạn cũng có thể muốn xem xét việc biên dịch chéo cho OCaml.