以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 Dot NET,C#,ASP,VB 』  (http://bbs.xml.org.cn/list.asp?boardid=43)
----  C#快餐-2  (http://bbs.xml.org.cn/dispbbs.asp?boardid=43&rootid=&id=11716)


--  作者:admin
--  发布时间:11/9/2004 2:25:00 AM

--  C#快餐-2


发信人: walts (休息一会), 信区: DotNET        
标  题: C#快餐-2
发信站: BBS 水木清华站 (Thu Jul 26 01:10:18 2001)

Lesson 2. Hacker's introduction to MSIL.

   First of all I am not a hacker. I may even get a PhD in Physics in a few  
weeks. But what can I do? I really wanted to learn Microsoft Intermediate   
Language (MSIL) programming and  the documentation, putting it politely, is a  
bit limited. So, I took this tool called ildasm, and started disassembling my  
C# code. Whatever is said in this chapter is my empirical knowledge. That is
why I called it hacking.

  So why do we want to learn MSIL programming? First of all, because it will  
look cool on your resume. Second, because we want to understand a little  
better how the Common Language Runtime works. Let me ask you a question:  
Where does term boxing come from. Is there such a keyword in C#? What about  
VB.Net? Why the hell do we call value to object conversion boxing?  
Because this is what MSIL does. Look at your favorite *.Net program which has  
value to object conversion and you will find a keyword box.  So, let's study  
MSIL.The simplest MSIL program is the one which does not do anything and has  
no data.

.assembly hello{}
.class hello{
    .method static public void main() il managed{
         .entrypoint
        ret
        }
}

MSIL  supports OO programming, so we can have a class  hello with public  
method main. The entrypoint of the program needs to be manually specified.  
So, it doesn't really matter whether the method is called main or Dad. The  
only thing that matters here is that .entrypoint is specified inside a method.
MSIL programs are compiled with ilasm compiler. Since we are writing a  
managed assembly code, we have to make sure that no variables are allocated  
in memory when the program goes out of scope. Here is a more complicated  
program that again does not do anything but has some data.

.assembly hello{}
.class hello{
    .method static public void main() il managed{
        .entrypoint
        .local( string V_0)
         ldstr "hi there"
        stloc.0
        ret
        }
}
This program has a statement .local(string V_0),which declares a single  
local variable of type string. This declaration allows the compiler to  
allocate "hi there" on the local stack. . Because of that, stloc.0 can  
find "hi there" and pop it from the stack. Since you are working in a  
managed environment,

you cannot leave data in memory before quitting the program. Memory leaks a
re not allowed. So every single variable which you have allocated in memory  
has to be popped  from the registers. Every program also needs to start with
a declaration of the assembly it belongs to. In our case, we choose the  
assembly name to be the same as the class name. Let's see a bit more  
complicated example which still doesn't do anything useful.
//allocating and deallocating multiple variables on the stack

.assembly hello{}
.class hello{
.method static public void main() il managed{
.maxstack 2
.entrypoint
.local( string V_0, string V_1) //we have two local variables now
ldstr "hi there" //push this string on stack
ldstr "bye here" //push second string on stack
stloc.0 //pop first string  from the stack and store it in  the local variab
le 0.
//you do not need to worry about dealocating local variables - it is done by
the runtime.
stloc.0 //pop the second string from the stack and store it in the same loca
l variable ("hi there" is overwritten)
ret
}
}

There is a new element in this program: .maxstack declaration. We use .
maxstack to declare the maximal number of variables we plan to have on stack  
at any given time. The default value is 1, so we can always omit this  
declaration when  we use a single register.

Here is a hello world program written in MSIL

//compile with ilasm
.assembly hello {}
.method static public void main() il managed {
.entrypoint
ldstr "Hello MS IL!"
call void [mscorlib]System.Console::WriteLine(class System.String)
ret
}

All MSIL directives start with a period. Recall that all C# code is  
contained within a class. This translates on MSIL level at having all code  
inside assembly .hello .entrypoint and ret are equivalent to main(){  and }  
lsdtr loads string into a register and call to WriteLine picks it up from  
there. WriteLine does all the clean up before it displays "hello  msil",
we do not need to pop anything from the stack. We will get a runtime error  
if we do.

  Here is a program which illustrates how to store data into local varibles  
and how to overwrite them

.assembly hello{}
.assembly extern mscorlib {}
.class hello{
.method static public void main() il managed{
.maxstack 2
.entrypoint
.locals(string V_0, string V_1)
//we have two local variables now
ldstr "hi there" //push this string on stack
ldstr "bye here" //push second string on stack
stloc.0 //pop first string from the stack and store it in the local variable
0.
//you do not need to worry about dealocating local variables - it is done by
the runtime.
stloc.0 //pop the second string from the stack and store it in the same  
local variable ("bye there" is overwritten)
ldloc.0 //push the remaining local variable containing "bye there" into the  
register
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}

It is always a lot of fun to manipulate integers with Assembly language.

//print number 2
.assembly hello {}
.method public static void Main() il managed
{
.entrypoint
.locals(int32 V_0)
ldc.i4.2
stloc.0
ldloc.0
call void [mscorlib]System.Console::WriteLine(int32)
ret
}


The next program  adds two integers
//add two numbers 1 and 3
.assembly hello {}
.assembly extern mscorlib {}
.class public hello
{
    .method static public void main() {
         .entrypoint
        .maxstack 2
        .locals(int32 V_0, int32 V_1) //declare two local variables
        ldc.i4.1 //put number  1 on the stack
        ldc.i4.3 //put number 3 on the stack
         stloc.0 //pop 1 from the stack and store it in the local variable
         ldloc.0 //push local variable  with value 1 on the stack
         add //add takes care of the second value on the local stack
       //you should not try to deallocoate memory there. it is done by add
        //add works with the first variable on the stack and the value
         call void [mscorlib]System.Console::WriteLine(int32)
        ret
     }
}
    
    It is sometimes very useful to have an explicit conversion between a value
and an object. This is done with box directive. The example bellow outputs an
object value. So, we need to explicitly convert the data inside the  
register to  a boxed data.

.assembly hello{}
.method public static void Main() il managed
{
.entrypoint
ldc.i4.s 100 //put 100 on stack
box [mscorlib]System.Int32 //convert it to on object in place
call void [mscorlib]System.Console::WriteLine(object) //print the value of t
he object
ret
}

The example above was a bit contrived to keep it simple .  
Here is another example

.assembly hello{}
.method public static void Main() il managed
{
.entrypoint
.maxstack 2
.locals (int32 V_0)
ldstr "Please enter your age:"
call void [mscorlib]System.Console::WriteLine(string)
call string [mscorlib]System.Console::ReadLine()
call int32 [mscorlib]System.Int32::Parse(string)
stloc.0
ldstr "You are {0} years old "
ldloc.0
box [mscorlib]System.Int32 //convert int32 to an object on the stack
call void [mscorlib]System.Console::WriteLine(string, object)
ret
}

MSIL does not have System.Consol::WriteLine(sting,int32 ) method, therefore  
int32 needs to be converted to another type to allow output to the console.


Exercises:
Write a program that subtracts two integers.
Read an MSIL article by John Robbins at MSDN magazine.
Use ildasm to disassemble your .Net programs. Does compiling with /o+  
optimization option change MSIL code? Why?
Find a mistake in this page.
Write a really cool program and send it to me. Do not forget to put a lot of
comments.
Do you think there is an important topic that I should have covered in this  
lesson? Write to me about it.

--

A great poem is a fountain forever overflowing with the
 waters of wisdom and delight.
                           
                                          —— Shelley


※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.142.118]
上一篇
返回上一页
回到目录
回到页首
下一篇



W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
58.594ms