翻译:关于Evaluation Stack

  由于没想到合适的 Evaluation Stack 对应的中文,索性就不给它中文名了。

Evaluation Stack 是基于 MSIL 应用程序(C#、F#、VB.NET 语言应用)的关键结构,它是应用程序 和 内存之间的桥梁。

它跟普通的栈有一些关键性的区别。

你的应用程序 可以通过 使用 Evaluation Stack ,去访问 函数参数、局部变量、临时对象等。

通常,函数参数和局部变量 是存在内存【栈】上的,但是你的函数 却不能直接访问这些信息。想访问这些数据,必须使用 load 命令,把它们从内存 移动到 Evaluation Stack 的 Slot(槽,4字节或8字节的单元)上;反过来,可以用(store命令)更新Evaluation Stack上的 局部变量或参数。

 

 

Evaluation Stack 是个栈,因此,也遵循 先进后出(LIFO)的原则。 当函数开始的时候,Evaluation Stack是空的。 随着函数的执行,会向Evaluation Stack里面增删元素。在函数退出前,除有返回值的情况外,Evaluation Stack必须是空。Jmp、Tail命令是这个规则的例外。如果函数退出时Evaluation Stack不为空,CLR会抛出InvalidProgramException 异常。

 

.maxstack 是用来限制 Evaluation Stack 大小的命令,是可选的。如果没有写,默认Evaluation Stack 提供8个Slot。.maxstack 用来确保应用如预期的执行。如果执行时,Evaluation Stack的长度 超过了.maxstack 指定的长度,则可能代表着 程序收到了潜在的逻辑问题 或者安全风险。不管如何,这种情况都值得提醒用户。

 

简言之,Evaluation Stack就是 函数 和 内存间的桥梁。

----------------------------------

以下不是翻译:

以一个简单的函数为例:

public int Add(int fact1, int fact2)
{
    return fact1 + fact2;
}

编译后的IL,可以看出函数的一般“套路”:对参数、返回值、局部变量的读写,就是在操作 Evaluation Stack。

// 方法
    .method public hidebysig 
        instance int32 Add (
            int32 fact1,
            int32 fact2
        ) cil managed 
    {
        // 方法起始 RVA 地址 0x30a4
        // 方法起始地址(相对于文件绝对值:0x12a4)
        // 代码长度 9 (0x9)
        .maxstack 2   //CC note:限定了 这个函数的 evaluation stack 大小是 2。函数执行过程中,,evaluation stack长度不能超过2。否则会有安全告警
        .locals init (
            [0] int32
        )

        // 0x12B0: 00
        IL_0000: nop
        // 0x12B1: 03
        IL_0001: ldarg.1 //CCNote:把第1个参数 加载到 evaluation stack
        // 0x12B2: 04
        IL_0002: ldarg.2 //CCNote:把第2个参数 加载到 evaluation stack
        // 0x12B3: 58
        IL_0003: add     //CCNote:从 evaluation stack 上 pop 出来2个元素,进行加法运算。再把结果 push 到  evaluation stack
        // 0x12B4: 0A
        IL_0004: stloc.0 //CCNote:从 evaluation stack 上 pop 出来1个元素,并把它存到 局部变量列表的 第0号 元素中。
        // 0x12B5: 2B 00
        IL_0005: br.s IL_0007

        // 0x12B7: 06
        IL_0007: ldloc.0 //CCNote:把 局部变量列表的 第0号元素 加载到 evaluation stack
        // 0x12B8: 2A
        IL_0008: ret //CCNote:return 命令, 从 被调函数的 evaluation stack中 Pop出来 顶上元素,然后 push到 调用方的 evaluation stack 中。
    } // 方法 HelloWorld::Add 结束

 

posted @ 2021-03-15 20:26  Snow~Forever  阅读(292)  评论(0编辑  收藏  举报