. NET compiler Technology Insider (1)

Source: Internet
Author: User
Tags abstract goto mscorlib numeric value variables static class variable thread
Compiling understanding of how the CLR works through MSIL
Author: Wednesday, April 2002 2:12 PM



As. NET minimum level of public base, the Microsoft intermediary language (MSIL or IL) for the general developer is very important significance. In addition to curiosity, a careful study of the application's Il gives you a clearer idea of how the common language runtime (CLR) performs advanced C # or vb.net code, which helps you find and solve some of the more subtle issues.

In this article, I will guide the reader through the IL, learn some key instructions about it, and do a little basic explanation of the CLR's operating mechanism. I'm not going to teach you to use IL programming, but to analyze some IL syntax and statements to give you a better understanding of IL.

ILDASM Introduction
Microsoft's Il removal utility Ildasm.exe (usually located in the \program Files\Microsoft.NET\FrameworkSDK\Bin directory) can be used to deconstruct. Net Assembly (assembly), Extract the Il code from the program according to your requirements. After invoking the use of a assembly, ILDASM gives a view of all the classes and namespaces in the Assembly, as shown in Figure A:

"Target=_blank>image001.gif

Figure A


ILDASM Browse Assembly

When you enter a member of a class or its method, ILDASM will show you the IL code for that member. If you've ever seen an assembler or J + + bytecode before, then IL may look a little familiar to you. On the other hand, if you understand only the abstract high-level programming language, IL looks more like gibberish.

Okay, now you know how to peek at Assembly's IL code, but what does all this mean? Before answering this question, let's first take a look at the relevant knowledge of the CLR.

Virtual CPU
For. NET programs, the. NET CLR is functionally like a virtual CPU, which executes IL code, manipulating data. The CLR and the real CPU are similar in that they do not manipulate variables in memory directly but use temporary copies of program variables, which the CLR stores on the stack. The behavior of copying a variable from memory to the stack is called a mount (loading), while the act of copying a variable from the stack back to memory is called storage (storing).

So the process of adding up two numbers should be this:

1. Load the 1th number and push it onto the stack.

2. Load the 2nd number and push it onto the stack.

3. Take these two numbers out of the stack and add them together.

4. Store the results in memory.

What is a stack?
The key to understanding IL is to know how the stack works. A stack is an abstract data structure whose operating mechanism is LIFO. When you push a new item onto the stack, any item already inside the stack will be pressed to the bottom of the stack. Similarly, moving an entry out of the stack will cause other entries in the stack to move to the top of the stack. Only the topmost entries in the stack are removed from the stack, and the order in which entries leave the stack is the same as the order in which they are pushed. You might as well recall the loading and unloading process of the vending machine.

The important IL statement
Now that you understand the basics of CLR operations, let's go on to discuss the code in front of you. How? Don't see any code? So please take a look at the IL code listed here.

Sidebar a:sample IL Listing


. method private instance void Listen () cil managed
{
Code size 169 (0XA9)
. maxstack 4
. Locals init ([0] unsigned int8[] buff,
[1] class [System]system.net.sockets.networkstream Chatstream,
[2] class [System]system.net.sockets.tcpclient remoteclient,
[3] String strhandle,
[4] class Chat.chatserver/textrelayer ' handler ',
[5] class [Mscorlib]system.threading.thread t)
Il_0000:nop
Il_0001:nop
. try
{
IL_0002:BR il_0091
il_0007:ldarg.0
IL_0008:LDFLD class [System]system.net.sockets.tcplistener Chat.chatserver::listener
Il_000d:callvirt instance class [System]system.net.sockets.tcpclient [System]system.net.sockets.tcplistener:: AcceptTcpClient ()
Il_0012:stloc.2
Il_0013:ldloc.2
Il_0014:callvirt instance class [System]system.net.sockets.networkstream [System]system.net.sockets.tcpclient:: GetStream ()
Il_0019:stloc.1
IL_001A:LDC.I4.S 26
Il_001c:newarr [Mscorlib]system.byte
il_0021:stloc.0
Il_0022:ldloc.1
il_0023:ldloc.0
il_0024:ldc.i4.0
IL_0025:LDC.I4.S 24
Il_0027:callvirt instance int32 [System]system.net.sockets.networkstream::read (unsigned int8[],
Int32,
Int32)
Il_002c:pop
Il_002d:call class [Mscorlib]system.text.encoding [Mscorlib]system.text.encoding::get_ascii ()
il_0032:ldloc.0
Il_0033:callvirt instance string [mscorlib]system.text.encoding::getstring (unsigned int8[])
Il_0038:stloc.3
il_0039:ldarg.0
IL_003A:LDFLD class Chat.chatserver/incomingchatrequest Chat.chatserver::requestconnect
IL_003F:LDLOCA.S Strhandle
Il_0041:callvirt instance bool Chat.chatserver/incomingchatrequest::invoke (string&)
IL_0046:BRTRUE.S il_0051
Il_0048:ldloc.2
Il_0049:callvirt instance void [System]system.net.sockets.tcpclient::close ()
Il_004e:nop
IL_004F:BR.S il_008f
Il_0051:nop
IL_0052:LDLOCA.S Strhandle
il_0054:ldarg.0
Il_0055:ldflda class Chat.chatserver/incomingtext Chat.chatserver::relaytext
IL_005A:LDLOCA.S Chatstream
il_005c:newobj instance void Chat.chatserver/textrelayer::.ctor (String&,
Class Chat.chatserver/incomingtext&,
Class [system]system.net.sockets.networkstream&)
Il_0061:stloc.s ' Handler '
Il_0063:ldloc.s ' Handler '
Il_0065:dup
il_0066:ldvirtftn instance void Chat.chatserver/textrelayer::handlechat ()
il_006c:newobj instance void [Mscorlib]system.threading.threadstart::.ctor (object,
native int)
il_0071:newobj instance void [Mscorlib]system.threading.thread::.ctor (class [Mscorlib]system.threading.threadstart )
Il_0076:stloc.s T
il_0078:ldarg.0
IL_0079:LDFLD class [System]system.collections.specialized.listdictionary chat.chatserver::chatthreads
Il_007e:ldloc.3
Il_007f:ldloc.s T
Il_0081:callvirt instance void [System]system.collections.specialized.listdictionary::add (object,
Object
Il_0086:nop
Il_0087:ldloc.s T
Il_0089:callvirt instance void [Mscorlib]system.threading.thread::start ()
Il_008e:nop
Il_008f:nop
Il_0090:nop
il_0091:ldc.i4.1
Il_0092:brtrue il_0007
IL_0097:LEAVE.S IL_00A6
}//end. Try
Finally
{
Il_0099:nop
Il_009a:ldstr "Listener Thread aborted."
Il_009f:call void [Mscorlib]system.console::writeline (String)
Il_00a4:nop
Il_00a5:endfinally
}//End Handler
Il_00a6:nop
Il_00a7:nop
Il_00a8:ret
}//End of method Chatserver::listen





The first thing you see is the IL declaration of the current method, which includes the name of the method, the return type, the argument list, and other cosmetic keywords attached to the method (static/shared, public, virtual, and so on). The object Builder is assigned a special name:. ctor.

In IL, method parameters are referenced in sequence by their position in the argument list. If the method is static or shared, parameter 0 is the 1th parameter in the argument list. For an instance method, parameter 0 is a pointer to an instance of the class in which the method is located (me or this). All local variables in the method are declared in the same way in the. Locals marked paragraphs.

After declaring all the local variables, the actual body of the program begins. Each il instruction, or opcode, can start with a il_ tag as a line of code, depending on your preferences. We're going to get some more important IL instructions next.

Variable usage
An instruction that begins with the LD loads the variable from memory onto the stack for its operation. There are several loading instructions, and each load instruction operates on a particular type of variable. Here are some of these load instructions:

LDC loads a numeric constant onto the stack. This instruction has two modifiers. The first is the type identifier and the second is the actual numeric value.
Ldloc loads a local variable onto the stack. There is also a ldloca instruction that loads the address of a local variable (not the contents of the variable) onto the stack. Variables are identified by their location in the. Locals section. These instructions load position 4 and later use different syntax, but the index number appears in the instruction.
Ldarg a parameter to the load member, and the ldarga instruction loads the address of the parameter. Variables are identified by their position in the. Locals section. These instructions load position 4 and later use different syntax, but the index number still appears in the instruction.
Ldelem the array elements onto the stack and is usually used before other load statements that represent the index.
Ldlen the length of an array onto the stack.
LDFLD and Ldsfld Load class fields (member variables) and static class fields onto the stack. The domain is recognized by a full name.
Each load instruction has a corresponding storage instruction, which begins with St and is responsible for storing an entry in memory. For example, STLOC is responsible for depositing the topmost item in a stack into a local variable. The rules for storing directives that specify variables are usually similar to their corresponding loading instructions.

Compare operations
If you can't compare two values and make a decision based on their comparison, many problems will not be solved in any programming language. Il has a set of comparison operators that start with a C letter and compare the values in the stack. Typically, if the comparison is true, push 1 into the stack or push 0.

Most of these directives are easily differentiated by their names. For example, ceq compares two values for equality, while CGT determines whether the topmost value of the stack is larger than the second top. CLT are similar to CGT, but perform less than comparison operations.

Goto
Typically, after comparing two values, some actions are implemented based on the results of the comparison. The IL branch instruction (beginning with a br) jumps to another instruction based on the contents of the topmost entry in the stack. Brtrue and brfalse eject the topmost entry on the stack, and then skip to the specified line of code, depending on whether the item is true (1) or False (0). If no command jump is performed, proceed to the next instruction. There is also an unconditional branch operator BR, which always jumps to the specified line of code.

You will find that the branching operation is like an if statement in the source code and an explicit goto operation. The branch commands in IL also have peers with advanced process control structures, such as: If, case, while, for, and so on.

Create new objects and invoke other code
Call and Callvirt directives invoke other methods and functions. Call usually indicates that the method being invoked is static or shared, while callvirt is used for instance methods. In both directions, the name of the method is included in the instruction. Any arguments sent to the method are ejected from the stack and loaded before the method is called.

Because creating a new object requires calling the constructor, the object creation of IL is similar to other method calls. The parameter is first loaded onto the stack and then executes the newobj instruction, which invokes the object's constructor and puts the object's index back on the stack. The instruction must have an object's name.

The above is the approximate il syntax operation. In addition to satisfying your inner curiosity, I hope you can get enough information from my exposition to understand the true meaning of IL code.





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.