zoukankan      html  css  js  c++  java
  • IL 汇编学习笔记(二)

    原文:http://www.codeproject.com/dotnet/ilassembly.asp

    条件语句


    先来看一个简单的跳转:

    br JumpOver // 或用 br.s 代替 br
    // 这里的其他代码会被跳过。。。
    //
    JumpOver:
        
    // 这里的代码将被执行

    br 的作用类似于高级语言的 goto 语句,如果你能确定 target 语句在 br 语句的 -128 到 127byte 范围内,则可以用 br.s 代替。因为 br.s 会使用 int8 而不是 int32 保存用于跳转的位移量。


    有条件的跳转语句

     //Branching.il
    .method static void main() cil managed
    {
        .maxstack 
    2
        .entrypoint
        
    //Takes First values from the User
        ldstr "Enter First Number"
        call 
    void [mscorlib]System.Console::WriteLine (string)
        
        call  
    string [mscorlib]System.Console::ReadLine ()
        call int32 [mscorlib]System.Int32::Parse(
    string)
        
        
    //Takes Second values from the User
        ldstr "Enter Second Number"
        call 
    void [mscorlib]System.Console::WriteLine (string)
        
        call  
    string [mscorlib]System.Console::ReadLine ()
        call int32 [mscorlib]System.Int32::Parse(
    string
        )
        
        ble Smaller
            ldstr 
    "Second Number is smaller than first."    
            call 
    void [mscorlib]System.Console::WriteLine (string)
        
        br Exit
        
    Smaller:
        ldstr 
    "First number is smaller than second."    
        call 
    void [mscorlib]System.Console::WriteLine (string)
    Exit:    
        ret
    }


    这里 ble 表示如果堆栈中第一个值小于等于第二个,则跳转。
    其他还有一些跳转条件:
        beq(==), bne(!=), bge(>=), bgt(>) ble(<=), blt(<)
        brfalse(栈顶元素为 0),
        brtrue(栈顶元素非 0)


    循环

    循环也是使用普通的分支语句来跳转,可以用一个 loop index 来判断循环的终止条件。
    例子:

    .method static void main() cil managed
    {
        
    // 定义两个局部变量
        .locals init (int32, int32)
        .maxstack 
    2
        .entrypoint
        ldc.i4 
    4    
        stloc.
    0 // 变量0 = 4,循环的上限,total 5
        ldc.i4 0
        stloc.
    1 // 变量1 = 0,计数器

    Start:
        
    // 判断计数器是否超出范围
        ldloc.1
        ldloc.
    0
        bgt Exit

        ldloc.
    1
        call 
    void
        
    // 打印出计数器的当前值
        [mscorlib]System.Console::WriteLine(int32)
        
        
    // 增加计数器
        ldc.i4 1
        ldloc.
    1
        add
        stloc.
    1
        br Start
        
    Exit:
        ret
    }

        
    用比较直观的方式翻译为 C# 代码,大致上相当于:
    (注:这个代码是为了便于和 IL 对照,实际并非最简单的写法)

    public static void Main()
    {
        
    int max, counter;
        max 
    = 4;
        counter 
    = 0;
        
    while (true)
        {
            
    if (counter > max)
                
    break;
            Console.WriteLine(counter);
            counter
    ++;
        }    
    }


    如何创建方法

    看代码:

    //Methods.il
    //Creating Methods

    .assembly 
    extern mscorlib {}

    .assembly Methods
    {
        .ver 
    1:0:1:0
    }
    .module Methods.exe

    .method 
    static void main() cil managed
    {
        .maxstack 
    2
        .entrypoint
        
        ldc.i4 
    10
        ldc.i4 
    20
        call int32 DoSum(int32, int32)
        call 
    void PrintSum(int32)
        ret
    }

    .method 
    public static int32 DoSum (int32 , int32 ) cil managed
    {
        .maxstack 
    2    
        
        ldarg.
    0
        ldarg.
    1
        add
        
        ret
    }
    .method 
    public static void PrintSum(int32) cil managed
    {
        .maxstack 
    2
        ldstr 
    "The Result is : "
        call 
    void [mscorlib]System.Console::Write(string)
        
        ldarg.
    0
        call 
    void [mscorlib]System.Console::Write(int32)
        
        ret
    }


    如何用引用的方式传参:

    .method static void main() cil managed
    {
        .maxstack 
    2
        .entrypoint
        .locals init (int32, int32)
        
        ldc.i4 
    10
        stloc.
    0
        ldc.i4 
    20
        stloc.
    1
        
        ldloca 
    0 // 加载变量0 的地址到 Evaluation Stack
        ldloc.1
        call 
    void DoSum(int32 &, int32 )
        ldloc.
    0
        
    // 再次加载变量0, 这次是值而不是地址
        call void [mscorlib]System.Console::WriteLine(int32)
        ret
    }
    .method 
    public static void DoSum (int32 &, int32 ) cil managed
    {
        .maxstack 
    2
        .locals init (int32)
        
    // 加载地址,并把值复制到局部变量
        ldarg.0
        ldind.i4 
    // 读取栈顶的地址,根据这个地址去读取一个 int 值,把值写到堆栈
        stloc.0  // 保存到局部变量
        ldloc.0
        
    // 做加法
        ldarg.1
        add
        stloc.
    0

        ldarg.
    0
        ldloc.
    0
        stind.i4 
    // 设定一个内存地址为整形值。op1: 地址,op2: 值
        
        ret
    }


    创建类和名称空间

    //Classes.il
    //Creating
    Classes
    .assembly 
    extern

    mscorlib {} .assembly Classes

    { .ver 
    1:0:1:0    }
    .module Classes.exe
    .
    namespace HangamaHouse

    {
        
    // ansi 表示该类中每一个字符串都要被转换为 ANSI 字符串。可选的其他值有:unicode, autochar
        
    // auto 表示运行时会在非托管的内存中,为该类的成员自动选择合适的内存布局(layout). 可选的其他值有:sequential(顺序布局),explicit(严格定义)。详细参考 msdn 里的 StructLayout 或 LayoutKind 枚举
        
    //
        
    // 不指定的情况下,auto 和 ansi 是默认值。
        .class public ansi auto Myclass extends [mscorlib]System.Object
        {
            .method 
    public static void main() cil managed
            {
                .maxstack 
    1
                .entrypoint
            
                ldstr 
    "Hello World From HangamaHouse.MyClass::main()"
                call 
    void [mscorlib]System.Console::WriteLine(string)
                
                ret
            
            }
        }    
    }

    在 ILAsm 中,类可以有如下的访问级别修饰符

    ILAsm Name

    Description

    C# Name

    Public

    visible to class, namespace and objects (all)

    public

    Private

    visible inside the class only

    private

    Family

    visible to class and derived classes only

    protected

    assembly

    visible within same assembly only

    internal

    familyandassem

    visible within derived classes of the same assembly

    N/A

    familyorassem

    visible to derived classes and those of the same assembly

    protectedinternal

    privatescope

    as that the private, but it can not be refereneced

    N/A


    对于类的方法和字段,可以有更多的修饰符,详见 MSDN.


    (To be continued)
  • 相关阅读:
    python 八进制数
    python hmac加盐
    python contextlib
    python hashlib
    python struct
    python namedtuple
    python datetime timezone 时区转化
    Android核心基础(手机卫士的一个知识点总结)
    TabHost结合RadioButton实现主页的导航效果
    Android SDK更新失败最新解决方案
  • 原文地址:https://www.cnblogs.com/RChen/p/366795.html
Copyright © 2011-2022 走看看