什么是 ActionScript 字节码 AVM2 中的 initscopedepth?为什么选择getlocal_0和



我查看了AVM2概述文档(第4.11章,第33页(,发现了以下关于init_scope_depth

init_scope_depth
init_scope_depth 字段定义可在方法中访问的相对于max_scope_depth的最小范围深度
max_scope_depth
max_scope_depth 字段定义可在方法中访问的最大范围深度。max_scope_depthinit_scope_depth之间的差异决定了本地作用域堆栈的大小。

我还在 ActionScript 3.0 圣经书中看到了一篇关于作用域链的引文,我认为这与init_scope_depth有关,并说:

作用域

链(如图 2-1 所示(是一个内部设备,用于在函数执行期间管理变量作用域。
引用变量时,Flash Player 将从调用的最新函数开始并检查变量声明。如果在最本地的作用域中找不到该值,它将向上移动一个级别到调用该函数的父函数并在那里进行检查。此过程一直持续到范围链一直检查到全局范围。

图2-1

如图所示,我们的范围顺序是从上到下

function scope -> parent function(s) scope (if any) -> instance of the class calling the function -> static instance of the class calling the function -> global scope

另请注意,作用域链可以具有更多级别,具体取决于类继承。

现在我的问题来了:

我一直在使用JPEXS Free Flash Decompiler和RABCDAsm,我在一个名为Data的包中有一个名为Global的类。该类不扩展任何其他类,但实现一个接口。在此类中,有普通方法和静态方法。我注意到静态方法initscopedepth设置为 3,普通方法initscopedepth设置为 4。(注意:这些值是由编译器设置的,如 AVM2 概述文档第 4.11 章中所述(。

我的猜测是初始范围是:

method -> instance of class -> static instance of class (static variables) -> global

但我不确定,想知道是否有人可以证实这一点。

这也引出了我的另一个问题。块code的所有方法,无论是正常方法还是静态方法,都以代码开头:

getlocal_0
pushscope

(注意:在这 2 条指令之后是该方法以任何指令开头的指令。 可能是因为,对于普通对象,它将this推送到作用域堆栈,而对于静态方法,它将类的静态实例推送到作用域堆栈上?如果是这样,为什么有必要这样做?

好吧,我相信经过更多的研究和思考,我已经找到了答案。这个谜题的关键是弄清楚另外两件事。

  1. 默认情况下,所有类都扩展了Object类,如本书中所述。
  2. 在方法输入时,作用域堆栈为空,并且有空间容纳max_scope_stack值,如 AVM2 概述的第 3.3.3 章所述。

因此,初始范围深度为:global -> Object class -> MyClass class (static instance)

因此,本例中的初始范围深度为 3。我注意到类外函数的初始作用域深度为 1(仅限全局作用域(。非静态方法的初始作用域深度为 4(它们也有 MyClass 对象(。

因为当我们输入方法时作用域堆栈是空的,并且因为寄存器 0 保存this对象(在静态方法的情况下是静态实例,或者如果您愿意,也可以保存类本身(,我们必须将此对象推送到作用域堆栈上,以便我们可以访问其作用域链上的所有变量和方法。我们当然有方法本身的范围,这使得最大范围深度为 4。

最新更新