请注意,每句后面都跟着 pop,意思就是我刚才进行判断的表达式这个栈,我完全不要了,这个表达式是一次性使用的。
link [esp], [ebp+1]: link 指令是我自己起的名字,在 php 中就是 =&,设置引用,我们不用设置这个引用,我们只需要把变量的名填上就行了过去就行了。
/**
* 引用
* @param int $offset link [esp], [ebp+{$offset}] 中的 $offset
*/
protected function _link($offset)
{
$this->ast[$this->astp] = $this->v[$offset - 1];
}
这里的 v 就是一个储存 Variable 对象的变量。ebp 的含义大家都知道吧,ebp+1 就是第 1 个局部变量,记为 $v0(你愿意记成 $v1 我也没有意见)。
[ebp] = 0, [ebp-1] = -1, [ebp-2] 为输入变量个数,这个在最开始定义过了
同理,你可以完成所有的线性代码了。
对全篇所有的 jnz 分析,我发现 4 类
“逻辑或”短路
三元运算符
if 语句
另一种三元运算符的写法
这几种形式主要看是不是 stmts 为空,看看是不是紧跟着一个 pop,看 if 跳出之后栈是否平衡。
三元运算符

逻辑或短路

这里讲一部分代码
// 普通 if 语句
$this->_pop();
$cond = $this->ast[$this->astp];
// 备份 AST
$ast = $this->ast;
$astp = $this->astp;
$astbp = $this->astbp;
$stackMap = $this->stackMap;
// 解析 stmts 块
$this->decompile(array_slice($item['args']['stmts'], 1));
$stmts = array_slice($this->ast, $astp + 1, $this->astp - $astp);
// 恢复 AST
$this->ast = $ast;
$this->astp = $astp;
$this->astbp = $astbp;
$this->stackMap = $stackMap;
// 解析 else 块
$this->decompile(array_slice($item['args']['else'], 1));
$else = array_slice($this->ast, $astp + 1, $this->astp - $astp);
// 如果栈差1、只有一条表达式,就换成三元运算符
$is_ternary = ($this->astp - $this->astbp == 1 && count($stmts) == 1 && count($else) == 1
&& $stmts[0] instanceof Expr && $else[0] instanceof Expr);
$this->ast = $ast;
$this->astp = $astp;
$this->astbp = $astbp;
$this->stackMap = $stackMap;
// 构造 AST
if ($is_ternary) {
$this->ast[$this->astp] = new Ternary($cond, $stmts[0], $else[0]);
} else {
$this->ast[$this->astp] = new If_($cond);
if ($stmts) {
$this->ast[$this->astp]->stmts = $stmts;
}
if ($else) {
$this->ast[$this->astp]->else = new Else_($else);
}
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-67089-6.html