2012-07-23 1 views
8

私は簡単なコードのオペコードを理解しようとしています。if文でPHPオペコードを理解する

コードは次のとおりです。

<?php 

$a = TRUE; 

$b = FALSE; 

if($a && $b) { 
    echo 'done'; 
} 

上記のコードのためのOPコードは次のとおりです。

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つの値を入力するか、2つの値に$ aの値と$ bの値を入力し、ifのカッコからの式を後で評価しますか?

私はJMPZ_EXのマニュアルを読んでいますが、少し前にステップ2までオペコードで何が起こっているのか理解しています。それはちょっと混乱しています。やって

私が理解しなければならないもう一つのことは、オペレーションコード内のすべてのブランチは何ですか?そのすべてのブランチのどれが最後に使用されますか?

+0

'&&'は短絡演算子です。 –

+0

@ KarolyHorvath私が知っている、私はphpが上記のオペレーションコードからやっているステップを理解する必要があります。 – Starlays

+0

私はちょうどあなたが既にそれがどのように振る舞うべきかを知っていると言っています... –

答えて

2

あなたはASMに堪能でない限り、私は何が起こっているかを理解するための最も簡単な方法は、その(ほぼ)1読み取ることにより、同じコードを見ていると思う:PHPでの1表現:

if(!$a) goto end; 
if(!$b) goto end; 
echo 'done'; 
end: return 0; 

中間表現をifブロックに含まれるコードを飛び越すために、実際の条項の否定に基づいています。

PHPが入力をこのオペコード配列に変換する方法を本当に理解したい場合は、the dragon bookを勉強する前ではなく、PHPの内部構造について学ぶ必要があります。特に、コンパイルパイプラインの一部である中間表現。

オペコードの残りの部分は、「バックグラウンドノイズ」、中間値、または意味を持たない1つの命令でもあります。PHPパーサーを吐き出させることに努力を払うのは意味をなさないのでおそらくおそらく存在するでしょう。9 6 > JMP ->7 ZendVMが実行される最も最適なオペコード配列。

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 

私はそれができますようにJMPZ_EXの具体的な違いは、それが見えるかわからない値が0の場合

0 assigns true to !0, !0 is just the internal representation of $A 
1 assigns true to !1, !1 is $B 

JMPZは、コードにジャンプすることを意味し#行番号で行きますブール結果の戻り値だから、

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 

いくつかの注意:

  • JMPZ_EX、この場合には不要ですが、あなたが値を使用する必要がある場合は、より複雑な文で有用であろうように思えさらなる値を計算する。
  • 6おそらくJMP -7がelseブロックを許可するでしょう。これがifブロックの主要部分であった場合、終了すると、elseブロックであったコード部分を飛び越えることができます。