So far we talked about .NET IL essentials and stack-oriented .NET IL code. It is time to learn object-oriented .NET IL(Intermediate Language).
.NET IL, or Intermediate Language, is a low-level, assembly language-like instruction set used by the .NET Framework. It acts as an intermediary between high-level programming languages (C#, VB.NET, etc.) and the underlying machine code, enabling portability across different operating systems.
Code written in .NET IL is typically compiled into platform-specific machine code using tools like ilasm.exe.
.assembly extern mscorlib {}
.assembly OOPIL {}
.module OOPIL.exe
.class Calculator extends [mscorlib]System.Object
{
.method public void .ctor()
{
ret
}
.method public float32 Sum(float32,float32)
{
ldarg.1
ldarg.2
add
ret
}
}
.class public Program extends [mscorlib]System.Object
{
.method public static void Main(string[] args)
{
.entrypoint
newobj instance void Calculator::.ctor()
ldc.r4 4.5
ldc.r4 45.67
call instance float32 Calculator::Sum(float32,float32)
call void [mscorlib]System.Console::WriteLine(float32)
call string [mscorlib]System.Console::ReadLine()
pop
ret
}
}
PS: Check out our repository for more complete examples.
.NET IL, or Intermediate Language, is a low-level, assembly language-like instruction set used by the .NET Framework.
It acts as an intermediary between high-level programming languages (C#, VB.NET, etc.) and the underlying machine code, enabling portability across different operating systems.
Code written in .NET IL is typically compiled into platform-specific machine code using tools like ilasm.exe.
Explanation of the Code
1. Assembly Declarations
.assembly extern mscorlib {}:
This line declares an external assembly named mscorlib.
mscorlib is the core assembly in the .NET Framework, containing essential types like System.Object, System.Console, and many others.
The empty curly braces {} indicate that we're not specifying any additional information about the assembly at this point.
.assembly OOPIL {}:
This line declares the current assembly (being compiled) as OOPIL.
Similar to mscorlib, the curly braces leave room for potential metadata like version or public key token in the future.
.module OOPIL.exe:
This line defines a module named OOPIL.exe within the OOPIL assembly.
A module typically corresponds to a single physical file containing compiled code.
2. Class Definitions
.class Calculator extends [mscorlib]System.Object:
This line defines a public class named Calculator that inherits from the System.Object class (from mscorlib).
Inheriting from System.Object provides basic functionalities like member equality testing and string representation.
3. Constructor Definition
.method public void .ctor():
This line defines a public constructor (method named .ctor) with no return type (void).
Constructors are special methods used to initialize objects when they are created.
The empty method body ret indicates that the constructor doesn't perform any specific initialization tasks in this case.
4. Method Definition (Sum):
.method public float32 Sum(float32,float32):
This line defines a public method named Sum that returns a 32-bit floating-point number (float32).
The method takes two arguments, both 32-bit floating-point numbers (float32).
ldarg.1:
This instruction loads the value of the first argument (index 1) onto the evaluation stack.
ldarg.2:
This instruction loads the value of the second argument (index 2) onto the evaluation stack, pushing two numbers onto the stack.
add:
This instruction pops the two top elements from the stack (the arguments), adds them, and pushes the result back onto the stack.
ret:
This instruction returns from the method, popping the result (the sum) from the stack and making it the return value of the Sum method.
5. Class Definition (Program)
.class public Program extends [mscorlib]System.Object:
This line defines a public class named Program that inherits from System.Object.
The Program class is often the entry point for a .NET application.
6. Main Method Definition
.method public static void Main(string[] args):
This line defines the Main method, which is the entry point for the application.
The Main method is declared as public (accessible from any code), static (doesn't require an object instance to be called), has a void return type, and takes an array of strings (string[]) as an argument (typically used for command-line arguments).
.entrypoint:
This instruction marks the Main method as the entry point for the application, indicating where program execution begins.
newobj instance void Calculator::.ctor():
This instruction creates a new instance of the Calculator class by calling its constructor (.ctor).
The result (the Calculator object) is pushed onto the evaluation stack.
ldc.r4 4.5:
This instruction pushes the literal floating-point value 4.5 onto the Stack and now it is available for our commands to be taken out of Stack.
The rest of the things are really simple. First, we need to call our method to calculate the values:
call instance float32 Calculator::Sum(float32,float32)
Then we use WriteLine() and ReadLine() methods.
call void [mscorlib]System.Console::WriteLine(float32)
call string [mscorlib]System.Console::ReadLine()
To Free up our stack we use pop instruction and ret instruction indicates that the method is done.
Conclusion
.NET IL is a really powerful tool that uses stack-oriented and Object-oriented approaches. Having such a deep knowledge will help you to understand the internals of your specific OOP languages like C#, F# and Visual Basic.