Search code examples
javaunsigned

Java not treating 0xFC as a signed integer?


Just when I though I had a fair grasp on how Java treats all Integers/Bytes etc.. as signed numbers, it hit me with another curve ball and got me thinking if I really understand this treatment after all.

This is a piece of assembly code that is supposed to jump to an address if a condition is met (which indeed is met). PC just before the jump is C838h and then after condition check it is supposed to be: C838h + FCh (h = hex) which I thought would be treated as signed so the PC would jump backwards: FCh = -4 in two's compliment negative number. But To my surprise, java ADDED FCh to the PC making it incorrectly jump to C934h instead of back to C834h.

C832: LD B,04              06 0004 (PC=C834)
C834: LD (HL), A           77 9800 (PC=C835)
C835: INC L:00             2C 0001 (PC=C836)
C836: JR NZ, n             20 00FC (PC=C934)

I tested this in a java code and indeed the result was the same:

int a = 0xC838;
int b = 0xFC;
int result = a + b;
System.out.printf("%04X\n", result); //prints C934 (incorrect)

To fix this I had to cast FCh into a byte after checking if the first bit is 1, which it is: 11111100

int a = 0xC838;
int b = (byte) 0xFC;
int result = a + b;
System.out.printf("%04X\n", result); //prints C834 (correct)

In short I guess my question is that I thought java would know that FCh is a negative number but that is not the case unless I cast it to a byte. Why? Sorry I know this question is asked many times and I seem to be asking it myself alot.


Solution

  • 0xfc is a positive number. If you want a negative number, then write a negative number. -0x4 would do just fine.

    But if you want to apply this to non-constant data, you'll need to tell Java that you want it sign-extended in some way.
    The core of the problem is that you have a 32-bit signed integer, but you want it treated like an 8-bit signed integer. The easiest way to achieve that would be to just use byte as you did above.

    If you really don't want to write byte, you can write (0xfc << 24) >> 24:

    class Main
    {
        public static void main(String[] args)
        {
            int a = 0xC838;
            int b = (0xfc << 24) >> 24;
            int result = a + b;
            System.out.printf("%04X\n", result);
        }
    }
    

    (The 24 derives from the difference of the sizes of int (32 bits) and byte (8 bits)).