Browse DevX
Sign up for e-mail newsletters from DevX


Down to the Metal: Managed Code Under the Hood (Part III) : Page 4

It's not until you get to the IL level that you see exactly how Microsoft made it possible for many languages to compile to the same runtime. In this last part of the IL Assembler series, you'll see how to write object-oriented IL code, declare fields, methods and properties and how to create object instances and access their members.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Creating Methods
The sample Sphere class exposes one CalcVolume method for calculating the volume of the sphere:

.method family hidebysig instance float64 CalcVolume() cil managed { .maxstack 2 ldarg.0 ldfld float64 Sphere.Sphere::radius ldarg.0 ldfld float64 Sphere.Sphere::radius mul ldarg.0 ldfld float64 Sphere.Sphere::radius mul ldc.r8 3.1415926535897931 mul ret }

The CalcVolume method has the access modifier family, which is about the same as protected in C#. The directive instance tells the runtime that this method can be called only on an instance of the Sphere class—that this method is not static. Note that to load the field value you always need to have the reference to the object (the this pointer, or Me in VB.NET) on the evaluation stack; therefore, there is a ldarg.0 before each ldfld (load field) statement to place the Sphere reference on the stack.

Defining Properties
In Intermediate Language assembler, you always implement properties as two separate methods: a get_ method and a set_ method:

.property instance float64 Radius() { .custom instance void [System.Xml]System.Xml.Serialization. XmlElementAttribute::.ctor(string) = ( 01 00 01 52 00 00 ) //"R" .get instance float64 Sphere.Sphere::get_Radius() .set instance void Sphere.Sphere::set_Radius(float64) }

The preceding code defines a property named Radius. You can see that it contains the two directives for the property accessors which map the get and set actions to two different methods. The code also adds an attribute to the property. I'll explain that later, in the "Adding Attributes" section of this article. First, have a look at the two accessor methods of the property:

.method public hidebysig specialname instance float64 get_Radius() cil managed { .maxstack 1 ldarg.0 ldfld float64 Sphere.Sphere::radius ret } .method public hidebysig specialname instance void set_Radius(float64) cil managed { .maxstack 2 ldarg.0 ldarg.1 stfld float64 Sphere.Sphere::radius ret }

The get_Radius and set_Radius methods are no different from any other normal IL method. The only things that connect them to the property are the .get and .set directives in the property declaration.

Adding Attributes
You add attributes to elements in Intermediate Language Assembler by using a .custom directive right at the beginning of a code block. This is similar to the process for adding other directives such as .entrypoint, .locals init, or .maxstack.

.custom instance void [System.Xml]System.Xml.Serialization. XmlElementAttribute::.ctor(string) = ( 01 00 01 52 00 00 )

In the preceding code the .custom directive adds custom metadata to the element. In this case it's adding an instance of a XmlElementAttribute with a constructor argument of type string that has the value "R." The argument for the constructor has to have a special encoding with specific initializing and terminating bytes. You can find more info on this in the "Partition II Metadata" reference document described at the end of this article.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date