Introduction
IL assembly (also called CIL assembly, MSIL or just IL) is the text form of the Common Intermediate Language, the instruction set that .NET compilers such as the C#, F# and Visual Basic compilers produce. A compiled .NET program or library (.dll or .exe) holds binary metadata and a binary stream of these instructions; a .il file holds the same information as readable text. ildasm (the IL Disassembler) writes such a file from an assembly, ilasm (the IL Assembler) turns one back into an assembly, and Mono has its own pair, monodis and ilasm. The language is called ILAsm in the standard ECMA-335 (Partition II), which describes the syntax; the ilasm of .NET accepts more than the standard describes.
A file is a sequence of declarations: the assembly and the assemblies it references, the module, classes and value types, their fields, methods, properties and events, custom attributes, data, and manifest resources. Everything starts with a dot (.class, .method, .field), words such as public and hidebysig are keywords in lower case, and a method body is a list of instructions, one opcode name each, with labels such as IL_0000: in front of the targets of branches. It is plain text in UTF-8 (a byte order mark is allowed) or UTF-16 little-endian with a byte order mark; line ends do not matter, because only the characters between the tokens count. These pages describe the language as ilasm reads it: file structure, lexical structure, types, classes, methods, control flow, the instruction set, fields and data, custom attributes, marshalling, assemblies and modules, the preprocessor, the dialects, the versions and the tools.
// the smallest program: ECMA-335 II.4.1, with string for System.String
.assembly extern mscorlib {}
.assembly hello {}
.method static public void main() cil managed
{
.entrypoint
.maxstack 1
ldstr "Hello world!"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.class public auto ansi beforefieldinit Greeter
extends [mscorlib]System.Object
{
.field private string _name
.method public hidebysig specialname rtspecialname
instance void .ctor(string name) cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: stfld string Greeter::_name
IL_000d: ret
}
.method public hidebysig instance string Greet() cil managed
{
.maxstack 8
IL_0000: ldstr "Hello, "
IL_0005: ldarg.0
IL_0006: ldfld string Greeter::_name
IL_000b: call string [mscorlib]System.String::Concat(string, string)
IL_0010: ret
}
}
The kinds of file
| Extension | What it is | Page |
|---|---|---|
.il | CIL assembly text: the output of ildasm and monodis and the input of ilasm; its default source extension (the usage text of ilasm says “Default source file extension is .il”) | File structure |
.il | a Cadence SKILL program: the extension is also used by the SKILL language of Cadence Virtuoso, a Lisp-like language for chip design software | not described here |
| other names | ilasm reads whatever file name it is given; this site registers only .il, and the language names il, cil, msil, ilasm and ildasm colour a Markdown code block | Tooling |
How the viewer reads each file
A .il file is shown as coloured text. The scanner follows the lexer of ilasm: comments, directives, keywords, types, instructions (the 227-row table of explorer/formats/dotnet/cil.js, which the CIL opcode reference shares, and the twelve aliases of ilasm), labels, quoted names, strings, numbers, hex byte lists, type parameters such as !0 and !!0, and the preprocessor lines. It has no parser: what a name is (a type, a method, a field, a variable, a label or an assembly) is decided from the words around it.
| File | Shown as |
|---|---|
.il with a directive (.assembly, .class, .method and so on at the start of a line), an IL_0000: label, or the preprocessor lines of ilasm | CIL assembly source file, coloured |
.il that holds a procedure( or defun definition or another sign of SKILL | Cadence SKILL source file, without colour |
.il that is neither | the neutral name “Text file with an .il extension”, without colour |
The pages
- File structure and conventions – the top-level declarations, the header directives and the order ildasm writes them in
- Lexical structure – comments, names, numbers, strings, hex byte lists and the complete keyword table
- Types and signatures – built-in types, class references, arrays, pointers, modifiers, generics
- Classes, value types and interfaces – the
.classheader and every attribute, generics, layout, nesting - Methods, properties and events – the
.methodheader, attributes, body directives,.propertyand.event - Labels, branches and exception handling – labels, switch,
.trywith catch, filter, finally and fault - The instruction set – every instruction by group with its operand and stack effect
- Fields and data –
.field, initialisers and.data - Custom attributes and security –
.customin bytes and in the verbal form,.permissionand.permissionset - Marshalling and platform invoke –
pinvokeimpl,marshaland the export directives - Assemblies, modules and resources – the manifest directives
- Preprocessor and conveniences –
#define,#include,.typedefand the rest - ilasm, ildasm and Mono dialects – what differs between the standard, .NET and Mono
- Versions and history – the editions of the standard and the .NET additions
- Tooling – ilasm and ildasm options and the other tools
Not described
Known, not yet covered
- Reference: the sources were the ilasm grammar and lexer (dotnet/runtime,
asmparse.yandgrammar_after.cpp), the keyword tableil_kywd.h,opcode.def, the ildasm output code, the Mono ilasm scanner, tables and grammar, the transcription of ECMA-335 6th edition by stakx and the runtime’s addendum to the standard. The official PDF of the standard (ECMA-335, 6th edition, 574 pages, 4,982,145 bytes at ecma-international.org) was downloaded and its text extracted; the Markdown transcription was used for reading and the PDF text for checking the points the pages quote, but the two were not compared page by page. - Reference: the metadata blob formats (custom attribute blobs, signatures, marshalling descriptors) are described only as far as the text syntax needs; their binary layout is the subject of the .NET assembly pages.
- Viewer: directives that only Mono’s ilasm knows (
.os,.processor,.titleand the others listed on the dialects page) are read as plain words, because the viewer follows the ilasm of .NET. - Viewer: a
.ilfile of Cadence SKILL is recognised from a few markers (procedure(,defun,let((and some library calls) that come from knowledge of the language: no SKILL file was found on this Mac or downloaded to test them. - Viewer: the colouring follows the words, not a parse. A bare name with no cue (a class name written without
classorvaluetypewhere the grammar allows it, or the name of a type parameter in an unusual place) can be left plain.
Unknown
- Reference: none of the examples was run through ilasm: there is no .NET SDK on this Mac (
dotnetis not installed) and downloaded binaries were not run. The examples follow the grammar (asmparse.y) and the standard’s own examples, and the real files of the runtime’s tests were used to test the scanner.
Links
Software
- ILSpy – open-source .NET decompiler that shows the IL of any method (Windows, macOS, Linux)
- ilasm – the IL assembler of .NET; the source is in the runtime repository and builds ship as NuGet packages (Windows, macOS, Linux)
- ildasm – the IL disassembler of .NET (Windows, macOS, Linux)
- Mono – ships its own
ilasmandmonodis(Windows, macOS, Linux) - SharpLab – web page that shows the IL of C#, Visual Basic and F# code as you type
Developers
- Mono.Cecil – library that reads and writes assemblies and their IL (C#)
- System.Reflection.Emit – the .NET API that emits IL instructions (C#)
- dotnet/runtime ilasm – the grammar (
asmparse.y) and lexer that define what ilasm accepts (C++, yacc)
Reference
- ECMA-335 – the Common Language Infrastructure standard, with the ILAsm syntax in Partition II and the instruction set in Partition III
- ECMA-335 in Markdown – a transcription of the 6th edition of the standard
- ECMA-335 augments – the runtime’s list of changes and additions to the standard
- CIL opcode reference – every instruction with its encoding, stack effect and meaning (on this site)