CIL is a stack-based language: most operands are put on the (imaginary) evaluation stack. This saves a lot of space in the instruction encoding, since those operands are implicit. For example, a method might have the following CIL content:
Code: Select all
{
ldc.i4.5 // 0x1B: Load constant 5
ldc.i4.1 // 0x17: Load constant 1
add // 0x58: Add
ret // 0x2A: Return
}
In CIL an opcode consists of one or two bytes. If the first byte is one of the reserved values, then a second byte follows. This is mostly used to encode a short and a long variant of the same instruction. There is also space for one or more explicit operands. For example:
Code: Select all
// Push pre-defined constant
ldc.i4.1 // 0x17
// Push 8-bit constant
ldc.i4.s 0xAB // 0x1F 0xAB
// Push 32-bit constant
ldc.i4 0xDEADBEEF // 0x20 0xEF 0xBE 0xAD 0xDE
// Push method argument by pre-defined index
ldarg.0 // 0x02
// Push method argument by 8-bit index
ldarg.s 4 // 0x0E 0x04
// Push method argument by 16-bit index
ldarg 0x123 // 0xFE 0x09 0x23 0x01