Search code examples
jvmbytecodejasmin

Logical NOT operation in JVM


I'm trying to mimic the behavior of a NOT gate using Jasmin. The behavior is as follows:

  • Pop an integer off the stack
  • if the integer is 0, push 1 back onto the stack
  • else push 0 back onto the stack

I've tried two different attempts at this but to no avail.

Attempt 1:

    ...(other code1)
    ifeq 3          ; if the top of stack is 0, jump 3 lines down to "i_const1"
    i_const0        ; top of stack was not 0, so we push 0
    goto 2          ; jump 2 lines down to first line of (other code2)
    i_const1
    ...(other code2)

Of course, the above example doesn't work because ifeq <offset> takes in a Label rather than a hard-coded integer as its offset. Is there a similar operation to ifeq that does accept integers as a parameter?

Attempt 2:

    ...
    ifeq Zero       ; top of stack is 0, so jump to Zero
    i_const0        ; top of stack was 1 or greater, so we push 0
    ...
    ... (some code in between)
    ...
    ifeq Zero       ; top of stack is 0, so jump to Zero
    i_const0        ; top of stack was 1 or greater, so we push 0
    ...
    Zero:
    i_const1        ; top of stack was 0, so push 1 to stack
    goto <???>      ; How do I know which "ifeq Zero" called this label?

The problem with this is that I've more than one place in my code making use of the NOT operation. I tried using ifeq with labels, but after I'm done how do I know which line to return to using goto? Is there a way to dynamically determine which "ifeq Zero" made the jump?

Any insight would be greatly appreciated.


Solution

  • Is there a similar operation to ifeq that does accept integers as a parameter?

    Yes, you can specify relative offsets using $ sign.
    BUT the relative offsets are counted in bytes, not in lines.

        ifeq $+7     ;  0: jump +7 bytecodes forward from this instruction
        iconst_0     ; +3
        goto $+4     ; +4
        iconst_1     ; +7
        # ...        ; +8
    

    Is there a way to dynamically determine which "ifeq Zero" made the jump?

    No. Use multiple different labels instead of single Zero.

    Well, there is actually a pair of bytecodes (jsr/ret) that support dynamic return address. But these bytecodes are deprecated and are not supported in Java 6+ class files.