8

単純なコードのオペコードを理解しようとしています。

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

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

JMPZ_EXのマニュアルを読み ましたが、オペコードで何が起こっているのかを理解しました。その後のステップ2は少し混乱しており、phpが実行している正確なステップを理解するのは非常に困難です。

私が理解する必要があるもう一つのことは、オペコードのすべてのブランチは何ですか、そのすべてのブランチのどれが最後に使用されますか?

4

2 に答える 2

2

ASMに精通していない限り、何が起こっているのかを理解する最も簡単な方法は、PHPで(ほぼ)1:1の表現を読んで同じコードを調べることだと思います。

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

if中間表現は、ブロックに含まれているコードをジャンプするための実際の句の否定に基づいています。

PHPが入力をこのオペコード配列に変換する方法を本当に理解したい場合は、PHPの内部について学ぶ必要がありますが、ドラゴンブック、特にコンパイルパイプラインの一部である中間表現に関する部分を学ぶ前に学ぶ必要はありません。

残りのオペコードは、「バックグラウンドノイズ」、中間値、または意味をなさない1つの命令です。これは9 6 > JMP ->7、PHPパーサーに最適なオペコード配列を吐き出すことに力を注ぐことが意味をなさなかったためと考えられます。実行されるZendVM。

于 2012-07-23T15:46:37.450 に答える
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

いくつかのメモ:

  • この場合、JMPZ_EXは不要のようですが、さらに値を計算する際に値を使用する必要がある、より複雑なifステートメントで役立ちます。
  • 6 JMP -7は、elseブロックを可能にするためにおそらくそこにあります。これがifブロックの主要部分である場合、それを終了すると、elseブロックであったコードの部分を飛び越えることができます。
于 2012-07-23T16:08:12.033 に答える