我正在尝试理解一个简单代码的操作码。
代码是:
<?php
$a = TRUE;
$b = FALSE;
if($a && $b) {
echo 'done';
}
上述代码的操作码是:
php -dvld.active=1 test.php
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = 3, Position 2 = 4
Branch analysis from position: 3
Jump found. Position 1 = 5, Position 2 = 7
Branch analysis from position: 5
Jump found. Position 1 = 7
Branch analysis from position: 7
Return found
Branch analysis from position: 7
Branch analysis from position: 4
filename: /home/starlays/learning/test.php
function name: (null)
number of ops: 8
compiled vars: !0 = $a, !1 = $b
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > ASSIGN !0, true
5 1 ASSIGN !1, false
7 2 > JMPZ_EX ~2 !0, ->4
3 > BOOL ~2 !1
4 > > JMPZ ~2, ->7
8 5 > ECHO 'done'
9 6 > JMP ->7
10 7 > > RETURN 1
branch: # 0; line: 3- 7; sop: 0; eop: 2; out1: 3; out2: 4
branch: # 3; line: 7- 7; sop: 3; eop: 3; out1: 4
branch: # 4; line: 7- 7; sop: 4; eop: 4; out1: 5; out2: 7
branch: # 5; line: 8- 9; sop: 5; eop: 6; out1: 7
branch: # 7; line: 10- 10; sop: 7; eop: 7
path #1: 0, 3, 4, 5, 7,
path #2: 0, 3, 4, 7,
path #3: 0, 4, 5, 7,
path #4: 0, 4, 7,
我试图了解第7行发生了什么,评估是如何完成的?在评估的if表达式中输入了多少个值?它输入3个值,或者输入值为$ a和值为$ b的2个值,之后是否计算if括号中的表达式?
我已经阅读了JMPZ_EX的手册,我已经理解了操作码中发生了什么,直到第2步之后有点混乱,我很难理解什么是确切的步骤php正在做。
我需要理解的另一件事是操作码中的所有分支是什么,最后将使用哪些分支?
答案 0 :(得分:2)
除非你精通ASM,否则我认为理解正在发生的事情的最简单方法是通过在PHP中读取(几乎)1:1表示来查看相同的代码:
if(!$a) goto end;
if(!$b) goto end;
echo 'done';
end: return 0;
中间表示基于对实际子句的否定,以跳过if
块中包含的代码。
如果你想真正理解PHP如何将其输入转换为这个操作码数组,你必须先学习PHP内部,但不要在学习the dragon book之前,特别是关于中间表示的部分,这是编译管道。
其余的操作码是“背景噪音”,中间值,或者甚至是一条没有意义的指令9 6 > JMP ->7
,这些指令可能只是存在,可能是因为将精力投入制作PHP解析器是没有意义的为ZendVM运行最优化的操作码数组。
答案 1 :(得分:2)
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > ASSIGN !0, true
5 1 ASSIGN !1, false
7 2 > JMPZ_EX ~2 !0, ->4
3 > BOOL ~2 !1
4 > > JMPZ ~2, ->7
8 5 > ECHO 'done'
9 6 > JMP ->7
10 7 > > RETURN 1
使用行号#
0 assigns true to !0, !0 is just the internal representation of $A
1 assigns true to !1, !1 is $B
JMPZ意味着如果值为0则跳转到代码。我不确定JMPZ_EX的具体差异看起来它允许返回布尔结果。
所以:
2 JMPZ_EX, Jump to #4 (->4) if !0 ($A) is 0 (FALSE) and assign the result to ~2
3 BOOL !1 return ~2. ~2 is now equal to the BOOLean value of !1 ($B)
4 JMPZ ~2, Jump to #7 if ~2 is zero
5 ECHO, our echo statement. If any of the JMPZ had jumped, this part would be skipped.
6 JMP -7, jumps to #7
7 RETURN, ends the function call
一些注意事项: