当前位置:网站首页>ZUCC_编译语言原理与编译_实验03 编译器入门

ZUCC_编译语言原理与编译_实验03 编译器入门

2022-06-24 06:59:00 星星不想卷

编译语言原理与编译实验报告

课程名称编译语言原理与编译
实验项目编译器入门

实验目的

  • 了解语言的发展历史
  • 理解编译的主要阶段
  • 掌握基本的编译操作
  • 理解高级语言、语法树、 中间语言、机器语言等概念

实验内容

1、阅读课件、教材第1章,请说明下面的概念

名称概念
编译器将一种语言(通常为高级语言)翻译成另一种语言(通常为低级语言)的程序
解释器是将目标代码解释为具体平台的机器码的程序
汇编器是将汇编语言翻译成机器语言的程序
编译程序的逻辑过程/步骤编译器的结构在逻辑上主要分为前端和后端,其中每一步骤将源程序的一种表达方式转化为另一表达方式
前端编译器前端又可以分为词法分析、语法分析、语义分析和中间代码生成,词法分析主要是对源代码文件中的字符进行切割(分词),分成一个个符号并生成符号标记树。语法分析是对符号标记树中的标记进一步分析语法,并生成语法树,语义分析是对源代码上下文的整体检查,最后根据生成的正确语法树翻译成中间代码
后端编译器后端主要是生成机器语言,并进行相关的代码优化,编译器生成的机器语言根据硬件平台的不同而不同
是对源程序或者源程序的中间结果进行从头到尾的扫描依次,并且作出相应的处理,生成新的中间结果或者目标程序
中间语言在翻译过程中,会出现一个或多个易于生成且能轻松翻译为目标程序的语言,例如语法树
机器语言机器能直接识别的程序语言或指令代码,无需经过翻译,每一操作码在计算机内部都有相应的电路来完成它,或指不经翻译即可为机器直接理解和接受的程序语言或指令代码

2、编译命令参数使用

测试gcc编译器 -S -E -c 等参数使用(-E预编译 -S汇编代码 -c 目标代码)

测试代码

#include <stdio.h>

int main()
{
    
    int x;
    scanf("%d", &x);
    x=x+1;
    printf("Value of x:%d\n",x);
}

image-20220316084254861

预编译

image-20220316084329580

汇编代码

image-20220316084623680

目标代码

image-20220316084723243

https://godbolt.org/ 查看生成的汇编代码

image-20220316082840088

3、安装 WSL2

由于使用MacOS且已有Win11及Ubuntu虚拟机,故暂不安装

MacOS内gcc版本

image-20220316085426476

Ubuntu内gcc版本

image-20220316084031118

4、理解程序代码与抽象语法树的关系,理解如下的抽象语法树节点

g1.3

spl.ast

语句解释
复合语句由分隔符或括号将多个语句聚合在一起
赋值语句这里指用运算的值改变某个变量的内存状态的语句
输出语句这里指print函数
表达式解释
id指引用到的变量
num指实际运算时的数据
二元操作binop具体指±*/四个运算符
语句表达式序列 EseqExp这里起到了并列两个语句的作用
表达式列表 ExpList这里起到了并列两个表达式的作用

5、查看具体语法树与 DotNet 中间语言IL 代码、JIT (即时编译)asm 代码的对应关系

在线访问 https://sharplab.io/ 查看下面的C#、F#程序,理解如下知识点

  • 理解源代码与具体语法树节点的对应关系

    将源代码的字符流进行词法分析生成符号流,再进行语法分析生成语法树,然后是语义分析生成新的语法树,最后生成中间代码。而具体语法树是一种中间代码,其中的结点对应了源代码中的一个个词素。

  • 关键字,标识符,方法,参数,操作符,操作数

    方法,参数,操作符,操作数这些词都称为词素,被映射为词法单元,它包含一个标识符和符号表标号,被当成一个个关键字。

参考题目4的图,画出 int x = 12 * 30;的抽象语法树

image-20220323201605763

中间语言IL

查看中间语言含义,理解运算栈,局部变量的表示

IL是.NET框架中中间语言(Intermediate Language)的缩写。使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但此时编译出来的程序代码并不是CPU能直接执行的机器代码,而是一种中间语言IL(Intermediate Language)的代码。

例如有如下代码:

private int add(int a, int b)
{
    
  int c;
  c = a + b;
  return c;
}

转化为IL语言有:

.method 
private hidebysig instance int32 'add'(int32 a,int32 b) cil managed
{
  // 代码大小       11 (0xb)
  .maxstack  2
  .locals init ([0] int32 c,[1] int32 CS$1$0000) //声明局部变量 c 
  IL_0000:  nop
  IL_0001:  ldarg.1     //将索引为 1 的参数加载到计算堆栈上。
  IL_0002:  ldarg.2
  IL_0003:  add         //将两个值相加并将结果推送到计算堆栈上。
  IL_0004:  stloc.0    //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。
  IL_0005:  ldloc.0    //将索引 0 处的局部变量加载到计算堆栈上。
  IL_0006:  stloc.1    //从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。
  IL_0007:  br.s       IL_0009   //无条件地将控制转移到目标指令 跳到IL_0009
  IL_0009:  ldloc.1    //将索引 1 处的局部变量加载到计算堆栈上。
  IL_000a:  ret        //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Form1::'add'

关键字:

  1. .locals:在IL 中,方法参数按照它们在参数列表中的位置依次被引用。如果方法是静态或共享方法,那么参数0则是参数列表中的第1个参数。而对实例方法来说,参数0则是指 向该方法所在类的实例的指针(Me或者this)。方法中的所有局部变量都在.locals标记的段落中以同样的方式声明。
  2. ldarg:装载成员的一个参数,而LDARGA指令则装载参数的地址。变量由它们在.locals节中的位置标识。这些指令装载位置4及以后位置使用不同的语法,但是索引号仍然出现在指令中。
  3. stloc:负责把堆栈最顶端的条目存入一个局部变量。存储指令指定变量的句法规则通常和它们对应的装载指令类似。
  4. ldloc:把一个局部变量装入堆栈,另外还有一条LDLOCA指令把一个局部变量的地址(而非变量的内容)装入堆栈。变量由它们在.locals节的位置标识。这些指令装载位置4及以后位置使用不同的语法,但是索引号会出现在指令中。
  5. br:IL分支指令(以BR开头)根据堆栈最顶端的条目中的内容跳到其他指令。Br.S无条件地将控制转移到目标指令(短格式)。
  6. ret:从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

汇编码 JIT Asm

理解汇编码与中间语言的关系

当目标语言为机器语言时,前端生成的中间代码经过优化成为后端的汇编生成打下基础。

理解代码优化的概念

所谓代码优化是指对程序代码进行等价(指不改变程序的运行结果)变换。程序代码可以是中间代码(如四元式代码),也可以是目标代码。等价的含义是使得变换后的代码运行结果与变换前代码运行结果相同。优化的含义是最终生成的目标代码短(运行时间更短、占用空间更小),时空效率优化。原则上,优化可以在编译的各个阶段进行,但最主要的一类是对中间代码进行优化,这类优化不依赖于具体的计算机。

//简单的C#程序
using System;
//Class declaration
class Test {
    //Method declaration
    static void Main() {
        //Statement 1
        int x = 12 * 30;
        //Statement 2
        Console.WriteLine (x);
        //End of method    
    }
}
.assembly _
{
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
        01 00 08 00 00 00 00 00
    )
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
        01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
        63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
    )
    .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Private.CoreLib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
        01 00 07 01 00 00 00 00
    )
    .permissionset reqmin = (
        2e 01 80 92 53 79 73 74 65 6d 2e 53 65 63 75 72
        69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e
        53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69
        6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73
        74 65 6d 2e 50 72 69 76 61 74 65 2e 43 6f 72 65
        4c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 36 2e 30
        2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d 6e 65
        75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b 65 79
        54 6f 6b 65 6e 3d 37 63 65 63 38 35 64 37 62 65
        61 37 37 39 38 65 15 01 54 02 10 53 6b 69 70 56
        65 72 69 66 69 63 61 74 69 6f 6e 01
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class private auto ansi beforefieldinit Test
    extends [System.Private.CoreLib]System.Object
{
    // Methods
    .method private hidebysig static 
        void Main () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 15 (0xf)
        .maxstack 1
        .locals init (
            [0] int32 x
        )

        IL_0000: nop
        IL_0001: ldc.i4 360
        IL_0006: stloc.0
        IL_0007: ldloc.0
        IL_0008: call void [System.Console]System.Console::WriteLine(int32)
        IL_000d: nop
        IL_000e: ret
    } // end of method Test::Main

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x206b
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method Test::.ctor

} // end of class Test
; Core CLR 6.0.121.56705 on x86

Test..ctor()
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: push eax
    L0004: mov [ebp-4], ecx
    L0007: cmp dword ptr [0xaccc190], 0
    L000e: je short L0015
    L0010: call 0x65694bc0
    L0015: mov ecx, [ebp-4]
    L0018: call System.Object..ctor()
    L001d: nop
    L001e: nop
    L001f: mov esp, ebp
    L0021: pop ebp
    L0022: ret

Test.Main()
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: push eax
    L0004: xor eax, eax
    L0006: mov [ebp-4], eax
    L0009: cmp dword ptr [0xaccc190], 0
    L0010: je short L0017
    L0012: call 0x65694bc0
    L0017: nop
    L0018: mov dword ptr [ebp-4], 0x168
    L001f: mov ecx, [ebp-4]
    L0022: call System.Console.WriteLine(Int32)
    L0027: nop
    L0028: nop
    L0029: mov esp, ebp
    L002b: pop ebp
    L002c: ret
//简单的 F# 程序,对比C#的语法树结构
let x = 12 * 30
printf "%d" x
.assembly _
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = (
        01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
    extends [System.Runtime]System.Object
{
} // end of class <Module>

.class public auto ansi abstract sealed _
    extends [System.Runtime]System.Object
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
        01 00 07 00 00 00 00 00
    )
    // Methods
    .method public specialname static 
        valuetype [System.Private.CoreLib]System.Int32 get_x () cil managed 
    {
        .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
            01 00 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 6 (0x6)
        .maxstack 8

        IL_0000: ldc.i4 360
        IL_0005: ret
    } // end of method _::get_x

    .method assembly specialname static 
        class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> [email protected] () cil managed 
    {
        // Method begins at RVA 0x2058
        // Code size 6 (0x6)
        .maxstack 8

        IL_0000: ldsfld class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> '<StartupCode$_>.$_'::[email protected]
        IL_0005: ret
    } // end of method _::[email protected]

    // Properties
    .property valuetype [System.Private.CoreLib]System.Int32 x()
    {
        .get valuetype [System.Private.CoreLib]System.Int32 _::get_x()
    }
    .property class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> [email protected]()
    {
        .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
            01 00 09 00 00 00 00 00
        )
        .get class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> _::[email protected]()
    }

} // end of class _

.class private auto ansi abstract sealed '<StartupCode$_>.$_'
    extends [System.Runtime]System.Object
{
    // Fields
    .field assembly static initonly class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> [email protected]
    .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableState) = (
        01 00 00 00 00 00 00 00
    )
    .field assembly static int32 [email protected]
    .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableState) = (
        01 00 00 00 00 00 00 00
    )
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
        01 00 00 00
    )
    .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = (
        01 00 00 00
    )

    // Methods
    .method private specialname rtspecialname static 
        void .cctor () cil managed 
    {
        // Method begins at RVA 0x2060
        // Code size 42 (0x2a)
        .maxstack 8

        IL_0000: ldstr "%d"
        IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, valuetype [System.Private.CoreLib]System.Int32>::.ctor(class [System.Private.CoreLib]System.String)
        IL_000a: stsfld class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> '<StartupCode$_>.$_'::[email protected]
        IL_000f: call class [netstandard]System.IO.TextWriter [netstandard]System.Console::get_Out()
        IL_0014: call class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit> _::[email protected]()
        IL_0019: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatToTextWriter<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>(class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [System.Private.CoreLib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
        IL_001e: ldc.i4 360
        IL_0023: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<valuetype [System.Private.CoreLib]System.Int32, class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
        IL_0028: pop
        IL_0029: ret
    } // end of method $_::.cctor

} // end of class <StartupCode$_>.$_

无JIT Asm

//简单的 F# 程序,带递归    
let rec fact n = 
if n = 0 then 1 else n * fact (n - 1)
.assembly _
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, int32, int32) = (
        01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
    extends [System.Runtime]System.Object
{
} // end of class <Module>

.class public auto ansi abstract sealed _
    extends [System.Runtime]System.Object
{
    .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = (
        01 00 07 00 00 00 00 00
    )
    // Methods
    .method public static 
        valuetype [System.Private.CoreLib]System.Int32 fact (
            valuetype [System.Private.CoreLib]System.Int32 n
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 16 (0x10)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: brtrue.s IL_0005

        IL_0003: ldc.i4.1
        IL_0004: ret

        IL_0005: ldarg.0
        IL_0006: ldarg.0
        IL_0007: ldc.i4.1
        IL_0008: sub
        IL_0009: call valuetype [System.Private.CoreLib]System.Int32 _::fact(valuetype [System.Private.CoreLib]System.Int32)
        IL_000e: mul
        IL_000f: ret
    } // end of method _::fact

} // end of class _

.class private auto ansi abstract sealed '<StartupCode$_>.$_'
    extends [System.Runtime]System.Object
{
} // end of class <StartupCode$_>.$_
; Core CLR 6.0.121.56705 on x86

_.fact(System.Int32)
    L0000: push esi
    L0001: mov esi, ecx
    L0003: test esi, esi
    L0005: jne short L000e
    L0007: mov eax, 1
    L000c: pop esi
    L000d: ret
    L000e: lea ecx, [esi-1]
    L0011: call dword ptr [0xad8c68c]
    L0017: imul eax, esi
    L001a: pop esi
    L001b: ret

//较复杂的 C# 程序
using System;
public class Fibonacci {
    public static long Fib(int m) {
        if (m == 0) return 1;
        else if (m == 1) return 1;
        else return Fib(m - 1) + Fib(m - 2);
    }
    
    public static void
        Main(string[] args) {
        int m = Convert.ToInt32(args[0]);
        System.Console.WriteLine(Fib(m) + "\n");
    }
}
.assembly _
{
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
        01 00 08 00 00 00 00 00
    )
    .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
        01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
        63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
    )
    .custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Private.CoreLib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
        01 00 07 01 00 00 00 00
    )
    .permissionset reqmin = (
        2e 01 80 92 53 79 73 74 65 6d 2e 53 65 63 75 72
        69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e
        53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69
        6f 6e 41 74 74 72 69 62 75 74 65 2c 20 53 79 73
        74 65 6d 2e 50 72 69 76 61 74 65 2e 43 6f 72 65
        4c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 36 2e 30
        2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d 6e 65
        75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b 65 79
        54 6f 6b 65 6e 3d 37 63 65 63 38 35 64 37 62 65
        61 37 37 39 38 65 15 01 54 02 10 53 6b 69 70 56
        65 72 69 66 69 63 61 74 69 6f 6e 01
    )
    .hash algorithm 0x00008004 // SHA1
    .ver 0:0:0:0
}

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit Fibonacci
    extends [System.Private.CoreLib]System.Object
{
    // Methods
    .method public hidebysig static 
        int64 Fib (
            int32 m
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 49 (0x31)
        .maxstack 3
        .locals init (
            [0] bool,
            [1] int64,
            [2] bool
        )

        IL_0000: nop
        IL_0001: ldarg.0
        IL_0002: ldc.i4.0
        IL_0003: ceq
        IL_0005: stloc.0
        // sequence point: hidden
        IL_0006: ldloc.0
        IL_0007: brfalse.s IL_000e

        IL_0009: ldc.i4.1
        IL_000a: conv.i8
        IL_000b: stloc.1
        IL_000c: br.s IL_002f

        IL_000e: ldarg.0
        IL_000f: ldc.i4.1
        IL_0010: ceq
        IL_0012: stloc.2
        // sequence point: hidden
        IL_0013: ldloc.2
        IL_0014: brfalse.s IL_001b

        IL_0016: ldc.i4.1
        IL_0017: conv.i8
        IL_0018: stloc.1
        IL_0019: br.s IL_002f

        IL_001b: ldarg.0
        IL_001c: ldc.i4.1
        IL_001d: sub
        IL_001e: call int64 Fibonacci::Fib(int32)
        IL_0023: ldarg.0
        IL_0024: ldc.i4.2
        IL_0025: sub
        IL_0026: call int64 Fibonacci::Fib(int32)
        IL_002b: add
        IL_002c: stloc.1
        IL_002d: br.s IL_002f

        IL_002f: ldloc.1
        IL_0030: ret
    } // end of method Fibonacci::Fib

    .method public hidebysig static 
        void Main (
            string[] args
        ) cil managed 
    {
        // Method begins at RVA 0x2090
        // Code size 41 (0x29)
        .maxstack 2
        .locals init (
            [0] int32 m,
            [1] int64
        )

        IL_0000: nop
        IL_0001: ldarg.0
        IL_0002: ldc.i4.0
        IL_0003: ldelem.ref
        IL_0004: call int32 [System.Private.CoreLib]System.Convert::ToInt32(string)
        IL_0009: stloc.0
        IL_000a: ldloc.0
        IL_000b: call int64 Fibonacci::Fib(int32)
        IL_0010: stloc.1
        IL_0011: ldloca.s 1
        IL_0013: call instance string [System.Private.CoreLib]System.Int64::ToString()
        IL_0018: ldstr "\n"
        IL_001d: call string [System.Private.CoreLib]System.String::Concat(string, string)
        IL_0022: call void [System.Console]System.Console::WriteLine(string)
        IL_0027: nop
        IL_0028: ret
    } // end of method Fibonacci::Main

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x20c5
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method Fibonacci::.ctor

} // end of class Fibonacci
; Core CLR 6.0.121.56705 on x86

Fibonacci..ctor()
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: push eax
    L0004: mov [ebp-4], ecx
    L0007: cmp dword ptr [0xe12c190], 0
    L000e: je short L0015
    L0010: call 0x65694bc0
    L0015: mov ecx, [ebp-4]
    L0018: call System.Object..ctor()
    L001d: nop
    L001e: nop
    L001f: mov esp, ebp
    L0021: pop ebp
    L0022: ret

Fibonacci.Fib(Int32)
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: sub esp, 0x2c
    L0006: xor eax, eax
    L0008: mov [ebp-8], eax
    L000b: mov [ebp-0x10], eax
    L000e: mov [ebp-0xc], eax
    L0011: mov [ebp-0x14], eax
    L0014: mov [ebp-4], ecx
    L0017: cmp dword ptr [0xe12c190], 0
    L001e: je short L0025
    L0020: call 0x65694bc0
    L0025: nop
    L0026: cmp dword ptr [ebp-4], 0
    L002a: sete cl
    L002d: movzx ecx, cl
    L0030: mov [ebp-8], ecx
    L0033: cmp dword ptr [ebp-8], 0
    L0037: je short L0052
    L0039: mov dword ptr [ebp-0x28], 1
    L0040: mov ecx, [ebp-0x28]
    L0043: mov eax, [ebp-0x28]
    L0046: sar eax, 0x1f
    L0049: mov [ebp-0x10], ecx
    L004c: mov [ebp-0xc], eax
    L004f: nop
    L0050: jmp short L00b5
    L0052: cmp dword ptr [ebp-4], 1
    L0056: sete cl
    L0059: movzx ecx, cl
    L005c: mov [ebp-0x14], ecx
    L005f: cmp dword ptr [ebp-0x14], 0
    L0063: je short L007e
    L0065: mov dword ptr [ebp-0x2c], 1
    L006c: mov ecx, [ebp-0x2c]
    L006f: mov eax, [ebp-0x2c]
    L0072: sar eax, 0x1f
    L0075: mov [ebp-0x10], ecx
    L0078: mov [ebp-0xc], eax
    L007b: nop
    L007c: jmp short L00b5
    L007e: mov ecx, [ebp-4]
    L0081: dec ecx
    L0082: call dword ptr [0xe12c6c4]
    L0088: mov [ebp-0x1c], eax
    L008b: mov [ebp-0x18], edx
    L008e: mov ecx, [ebp-4]
    L0091: add ecx, 0xfffffffe
    L0094: call dword ptr [0xe12c6c4]
    L009a: mov [ebp-0x24], eax
    L009d: mov [ebp-0x20], edx
    L00a0: mov eax, [ebp-0x1c]
    L00a3: mov edx, [ebp-0x18]
    L00a6: add eax, [ebp-0x24]
    L00a9: adc edx, [ebp-0x20]
    L00ac: mov [ebp-0x10], eax
    L00af: mov [ebp-0xc], edx
    L00b2: nop
    L00b3: jmp short L00b5
    L00b5: mov eax, [ebp-0x10]
    L00b8: mov edx, [ebp-0xc]
    L00bb: mov esp, ebp
    L00bd: pop ebp
    L00be: ret

Fibonacci.Main(System.String[])
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: sub esp, 0x24
    L0006: vxorps xmm4, xmm4, xmm4
    L000a: vmovdqu [ebp-0x24], xmm4
    L000f: vmovdqu [ebp-0x14], xmm4
    L0014: mov [ebp-4], ecx
    L0017: cmp dword ptr [0xe12c190], 0
    L001e: je short L0025
    L0020: call 0x65694bc0
    L0025: nop
    L0026: mov ecx, [ebp-4]
    L0029: xor eax, eax
    L002b: cmp eax, [ecx+4]
    L002e: jb short L0035
    L0030: call 0x65695fc0
    L0035: lea ecx, [ecx+eax*4+8]
    L0039: mov ecx, [ecx]
    L003b: call System.Convert.ToInt32(System.String)
    L0040: mov [ebp-0x14], eax
    L0043: mov ecx, [ebp-0x14]
    L0046: mov [ebp-8], ecx
    L0049: mov ecx, [ebp-8]
    L004c: call Fibonacci.Fib(Int32)
    L0051: mov [ebp-0x1c], eax
    L0054: mov [ebp-0x18], edx
    L0057: mov ecx, [ebp-0x1c]
    L005a: mov eax, [ebp-0x18]
    L005d: mov [ebp-0x10], ecx
    L0060: mov [ebp-0xc], eax
    L0063: lea ecx, [ebp-0x10]
    L0066: call System.Int64.ToString()
    L006b: mov [ebp-0x20], eax
    L006e: mov edx, [0x89c5238]
    L0074: mov ecx, [ebp-0x20]
    L0077: call System.String.Concat(System.String, System.String)
    L007c: mov [ebp-0x24], eax
    L007f: mov ecx, [ebp-0x24]
    L0082: call System.Console.WriteLine(System.String)
    L0087: nop
    L0088: nop
    L0089: mov esp, ebp
    L008b: pop ebp
    L008c: ret

6、下载LinqPad查看C#代码的具体语法树与抽象语法树 (自选)请说明具体语法树,与抽象语法树的区别

  1. 同一语言的每一个语法都会给出不同的具体语法树,但抽象语法树的结果应该是相同的
  2. 抽象语法树不关注语法生成它们的方式,专注于编程构造也就是运算符
  3. 抽象语法树使用运算符/操作作为根节点和内部节点,并使用操作数作为子节点。与具体语法树不同,抽象语法树不使用内部节点来表示语法规则。抽象语法树并不代表真实语法中的每个细节(这就是为什么它们被称为抽象) - 例如,省略了节点和括号等细节。与同一语言构造的解析树相比,抽象语法树是密集的。

image-20220323205129503

7、编译与反编译Java代码 (自选)

//自行安装 jdk 。。可以使用 javac, javap 代码如下:
//Fibonacci.java
public class Fibonacci {
    
    public static long fib(int m) {
    
        if (m == 0) {
    
            return 1;
        } else if (m == 1) {
    
            return 1;
        } else {
    
            return fib(m - 1) + fib(m - 2);
        }
    }
    public static void main(String[] args) {
    
        int m =Integer.parseInt(args[0]);
        System.out.println(fib(m) + "\n");
    }
}

注意:代码有修改

image-20220316154226507

image-20220316154539179

原网站

版权声明
本文为[星星不想卷]所创,转载请带上原文链接,感谢
https://blog.csdn.net/OwemShu/article/details/125377618