All control instructions test either `int`s or `reference`s. If you want to do a branch based on a comparison between two `float`s, `long`s, or `double`s, you have to use a separate instruction to turn the non-`int` comparison into an `int` comparison. The instructions to do this are summarized in Table 5.2. These instructions leave 1, 0, or 1 on the stack if the first operand is greater than, equal to, or less than the second. This value is easily compared with zero as an `int`, using the `ifeq, ifne, iflt`, `ifgt`, `ifle`, or `ifge` instructions. For example, comparing `double` values: getstatic java/lang/Math/PI D ; Get a good approximation of pi ldc2_w 3.1416D ; Get a worse approximation of pi dcmpg ; Compare the two numbers ; This leaves 1 on the stack, ; since pi < 3.1416 iflt approxTooHigh ; Goes to approxTooHigh, since ; 1 < 0 ##### Table 5.2. Comparison operations Mnemonic | Stack | Effect | `dcmpg` | double1 double2 | If double1 == double2, leave 0 on the stack. If double1 < double1, leave 1. If double1 > double1, leave 1. If either is `NaN`, leave 1. | `dcmpl` | double1 double2 | Same as `dcmpg`, except leave 1 if either is `NaN`. | `fcmpg` | float1 float2 | If float1 `==` float2, leave 0 on the stack. If float1 < float2, leave 1. If float1 > float2, leave 1. If either is `NaN`, leave 1. | `fcmpl` | float1 float2 | Same as `fcmpg`,"except leave 1 if either is `NaN`. | `lcmp` | long1 long2 | If long1 == long2, leave 0 on the stack. If long1 < long2, leave 1. If long1 > long2, leave 1. | Or for `long` values: ; Push the current time in milliseconds, a long value invokestatic java/lang/System/currentTimeMillis()J aload_0 ; Push a Document getfield Document/lastUpdatedTime J ; Get the last time this ; document was updated lsub ; Figure out the difference ldc 60000 ; Was it more than 60 seconds ago? lcmp ; Leaves 1 if more than 60 seconds ; 0 if exactly 60 seconds, and ; 1 if less than 60 seconds ifle makeBackup ; Make a backup if it was updated ; <= 60 seconds ago For the `float` and `double` comparisons, there are two almost identical operations for each: `fcmpg`/`fcmpl` and `dcmpg`/`dcmpl`. The difference is in the treatment of values that are `NaN` (not a number). Since `NaN` isn't really a number, it can't be compared to the other values. You choose the `g` variant or the `l` variant based on how you want your program to react if it encounters invalid numbers. If you want to see if `a > b` and you use `dcmpg`, then the test will succeed if either is `NaN`. If you use `dcmpl`, it will to fail. |