8

Let's say you're writing a Java (or subset-of-Java) compiler and you want to generate bytecode for a unary not expression, !E. You're past type checking so you know E has type boolean, i.e. it will push a 1 or a 0 on to the operand stack.

One way to do it is something like (in Jasmin syntax):

E
ifeq truelabel
iconst_0
goto stoplabel
truelabel:
iconst_1
stoplabel:

i.e. if there's a 0 on the stack push 1, else push 0. Another way to do it, taking advantage of the fact that a boolean is just an int with value 1 or 0, is to say !E = (E + 1) % 2 and generate

E
iconst_1
iadd
iconst_2
irem

Is there an advantage to using one over the other? Or something else entirely?

4

3 に答える 3

5

私はかつてJavaデコンパイラーを書き込もうとしたので、javacが生成したコードを知っていました。私が覚えているように、!E = E ? false : truejavac 1.1が使用されている間にjavac1.0.xが使用され!E = E ^ 1ました(ビット単位のXOR)。

于 2012-10-14T21:51:20.280 に答える
4

バイトコードレベルで当てはまるのは、次の定義には当てはまりません。

true == 1

バイナリレベル(およびそのほとんど言語に依存しない)では、ブール値は通常、次のように定義されます。

false == 0
true != 0

javacコンパイラも明らかにこの定義に従います(私が見たjavacバイトコードのすべてのチェックは常にゼロに対してチェックし、1に対してはチェックしません)。

そして、ブール値にこの定義を使用するのは理にかなっています。代わりに1をtrueとして扱うだけで、Cもこのように定義し(trueは単なる1ではなく!= 0)、アセンブリコードではこの規則も一般的に使用されます。したがって、javaもこの定義を使用することで、特別な変換なしでjavaブール値を他のコードに取得/渡すことができます。

最初のコード例(ifeqを使用)がブール値のnot-operatorを正しく実装する唯一の方法だと思います。ブール値が厳密に0/1として表されていない場合、^ 1メソッド(xor with 1)は失敗します。その他のint値を指定すると、式が正しく機能しなくなります。

于 2012-10-15T11:17:52.407 に答える
0

モジュラス演算は非常に遅くなる可能性があると聞きました。ソースはありませんが、分割するよりも追加する方が簡単であることを考えると、それは理にかなっています。繰り返しになりますが、プログラムカウンターをジャンプしすぎることが問題になる場合があります。その場合、if/elseアプローチはうまく機能しません。

そうは言っても、ニールE ^ 1が最速だと思いますが、それはただの予感です。あなたがしなければならないのは、1つの論理回路に番号を渡すことだけです、そしてあなたは完了です!一握りではなく、たった1つの操作。

于 2012-10-14T22:00:02.367 に答える