2016-03-29 - In IL: Instructions and the Stack
In IL
- Part 1 - Introduction
- Part 2 - Variables and Types
- Part 3 - Variables in Visual Basic .NET
- Part 4 - Instructions and the Stack
- Part 5 - Volume of a Cylinder (Operations)
- Part 6 - Branching Instructions
- Part 7 - Largest of Two Numbers (if-else)
- Part 8 - Largest of Three Numbers (If-ElseIf-Else)
- Part 9 - Switch instruction
- Part 10 - Grade Analyser (switch)
- Part 11 - Prize Calculator (switch-2)
- Part 12 - VB Grade Analyser (Select)
- Part 13 - Loop Instructions
- Part 14 - Print the Alphabet (while)
- Part 15 - Print the Alphabet (do while, for)
- Part 16 - Print the Alphabet (Do Until)
- Part 17 - Print the Alphabet (break, continue)
- Part 18 - Array Instructions
- Part 19 - Summing Arrays
- Part 20 - Other Instructions
- Part 21 - Assemblies
- Part 22 - Class Definitions
- Part 23 - C# Classes and Structs
- Part 24 - VB Classes, Modules and Structures
- Part 25 - Field Definitions
- Part 26 - Field Declarations
So now that we’ve learned where local variables are stored it’s time to learn what we can do with them. In most high level languages you write a series of symbols which indicate what you want to happen with each symbol implying the action they represent. In IL you have a series of instruction and their arguments with the name of each instruction implying the action it will perform. Before we get to instructions though we need to understand stacks.
A Stack is a data structure that can be imagined as a pile of things. You can “push” things onto the top of the pile or “pop” things off of the top of the pile. Depending on the implementation you may also be able to look at things on the top of the pile without removing them. In IL every method has an Evaluation Stack. Most instructions pop things from this stack, push things onto this stack, or both. The stack is used to store temporary values similar to how registers work in some computer processors.
There are a bunch of instructions in IL so I will start by summarizing some of the common ones.
nop (No OPeration)
Used to fill up space for various uses. Such as allowing instructions to be patched in later.
Instruction | Description | Binary Format |
---|---|---|
nop | Does nothing | 0x00 |
ldc (LoaD Constant)
Pushes a value, determined by the instruction or its argument, onto the stack.
Instruction | Description | Binary Format |
---|---|---|
ldc.i4.m1 | Loads –1 onto the stack as a 4-byte integer | 0x15 |
ldc.i4.X | Loads X onto the stack as a 4-byte integer where X is 0-8 | 0x16 - 0x1E |
ldc.i4.s <num> | Loads “short” 1-byte integer <num> onto the stack as a 4-byte integer | 0x1F <int8> |
ldc.i4 <num> | Loads 4-byte integer <num> onto the stack | 0x20 <int32> |
ldc.i8 <num> | Loads 8-byte integer <num> onto the stack | 0x21 <int64> |
ldc.r4 <num> | Loads 4-byte floating-point value <num> onto the stack | 0x22 <float32> |
ldc.r8 <num> | Loads 8-byte floating-point value <num> onto the stack | 0x23 <float64> |
ldstr (LoaD STRing)
Pushes a reference to a string onto the stack
Instruction | Description | Binary Format |
---|---|---|
ldstr <string> | Loads a reference to <string> onto the stack | 0x72 <T> |
<T> represents a metadata token. These are 4-byte values that indicate a location where the actual data is stored in the file containing the code.
ldloc (LoaD LOCal variable)
Push the value of a local variable onto the stack.
Instruction | Description | Binary Format |
---|---|---|
ldcloc.X | Loads the value of local variable X onto the stack where X is 0-3 | 0x06 - 0x09 |
ldcloc.s <index> | Loads the value of local variable with “short” index <index> onto the stack | 0x11 <uint8> |
ldcloc <index> | Loads the value of local variable with index <index> onto the stack | 0xFE 0x0C <uint16> |
conv (CONVersion)
Pops a value off of the stack, converts it to the type based on the specific instruction used and pushes the result onto the stack.
Instruction | Description | Binary Format |
---|---|---|
conv.i1 | Converts the value on the stack to a 1-byte integer | 0x67 |
conv.i2 | Converts the value on the stack to a 2-byte integer | 0x68 |
conv.i4 | Converts the value on the stack to a 4-byte integer | 0x69 |
conv.i8 | Converts the value on the stack to a 8-byte integer | 0x6A |
conv.r4 | Converts the value on the stack to a 4-byte floating-point value | 0x6B |
conv.r8 | Converts the value on the stack to a 8-byte floating-point value | 0x6C |
conv.u4 | Converts the value on the stack to a 4-byte unsigned integer | 0x6D |
conv.u8 | Converts the value on the stack to a 8-byte unsigned integer | 0x6E |
conv.u2 | Converts the value on the stack to a 2-byte unsigned integer | 0xD1 |
conv.u1 | Converts the value on the stack to a 1-byte unsigned integer | 0xD2 |
box
Pops a value-type value off of the stack, boxes it as the specified reference type and pushes the result onto the stack.
Instruction | Description | Binary Format |
---|---|---|
box <type> | Boxes the value on the stack as the specified <type> | 0x8C <T> |
stloc (SeT LOCal variable)
Pops a value off of the stack and sets it as the value of a local variable.
Instruction | Description | Binary Format |
---|---|---|
stloc.X | Sets the value of local variable X with a value from the stack where X is 0-3 | 0x0A - 0x0D |
stloc.s <index> | Sets the value of local variable with “short” index <index> with a value from the stack | 0x13 <uint8> |
stloc <index> | Sets the value of local variable with index <index> with a value from the stack | 0xFE 0x0E <uint16> |
add (ADDition), sub (SUBtraction), mul (MULtiplication), div (DIVision)
Pops two values off of the stack and pushes the result of the specified action onto the stack. How the action is performed and the type returned depends on the types of the values.
Instruction | Description | Binary Format |
---|---|---|
add | Adds the first value popped off of the stack to the second value popped off of the stack and pushes the result onto the stack | 0x58 |
sub | Subtracts the first value popped off of the stack from the second value popped off of the stack and pushes the result onto the stack | 0x59 |
mul | Multiplies the second value popped off of the stack by the first value popped off of the stack and pushes the result onto the stack | 0x5A |
div | Divides the second value popped off of the stack by the first value popped off of the stack and pushes the result onto the stack | 0x5B |
call
Used to call a method based on the argument to the instruction. The method pops its parameters off of the stack, if any, and pushes its return value onto the stack, if it has one.
Instruction | Description | Binary Format |
---|---|---|
call <method> | Calls the <method> method | 0x28 <T> |
ret (RETurn)
Returns from a method. Uses the value on the stack as the return value. The stack should be empty except for this value. If the method doesn't return a value then the stack should be completely empty.
Instruction | Description | Binary Format |
---|---|---|
ret | Returns from a method | 0x2A |
Next time we will see some of these instructions in action.
Comments: