asm编译器中的二进制表达式

时间:2013-06-11 19:17:39

标签: java jvm bytecode

我试图用逻辑和符号'&&'执行if语句。这是我想要做的事情:在asm中使用字节码的堆栈具有值0和1,我希望得到一个结果 '逻辑和'在我们的例子中它没有进入if语句。

我已经尝试过Opcodes.IFEQ和Opcodes.IFNE指令,但是没有用.Same跟'||'一样和'!'逻辑符号

有什么想法吗?

先谢谢。

2 个答案:

答案 0 :(得分:3)

&&||

的字节码模式

考虑像&&||这样的短路运算符实际上做了什么。你有一些条件分支。我们考虑一下&&。你有效评估的是:

if (left)
    if (right) <do something>
endIf

没有单个字节码指令可以描述此行为。您需要一些标签和条件分支指令:

.start
    <left expression>
    IFEQ .endIf // if left evaluates to zero (false), skip to end
    <right expression>
    IFEQ .endIf // if right evaluates to zero (false), skip to end
.ifTrue
    <body of 'if' block>
.endIf

||运算符的行为略有不同;在这种情况下,逻辑看起来像这样:

    if (left)
        goto .ifTrue
    if (!right)
        goto .endIf
.ifTrue
    <do something>
.endIf

注意当右操作数求值为true时,如何反转对右操作数的检查以避免额外的分支。这种行为可以在字节码中实现,如下所示:

    <left operand>
    IFNE .ifTrue  // if left evaluates true, skip right, enter 'if' body
    <right operand>
    IFEQ .endIf   // if right evaluates false, skip 'if' body
.ifTrue
    <do something>
.endIf

何时推送您的操作数

请注意,您的原始问题表明您已经在堆栈中拥有左右操作数;那会很糟糕。您应该只评估左操作数评估为true(非零)&&false(零)||后的右操作数 。如果右操作数导致副作用,过早地评估它会违反这些操作符的定义行为。

答案 1 :(得分:1)

有Opcodes.IAND和Opcodes.LAND。你没有提到堆栈上的值是int还是long,但我假设前者所以我认为Opcodes.IAND是你想要的。

同样,OR有Opcodes.IOR。对于NOT,javac似乎发出了IFNE和ICONST_1或ICONST_0指令,但是如果你知道值是1或0,那么你好像可以发出一个Opcodes.ICONST_1,然后是Opcodes.IXOR。

参见ASM用户指南的附录A,&#34;字节码说明&#34;,第136页:

http://download.forge.objectweb.org/asm/asm4-guide.pdf