Java 没有将 0xFC 视为有符号整数?

Java not treating 0xFC as a signed integer?

就在我对 Java 如何将所有 Integers/Bytes 等视为 有符号 数字有了相当大的了解时,我又想到了另一个曲线球让我思考我是否真的理解这种治疗方法。

这是一段汇编代码,如果满足条件(确实满足),它应该跳转到一个地址。跳转之前的 PC 是 C838h 然后在条件检查之后它应该是:C838h + FCh (h = hex) 我认为它会被视为已签名所以 PC 会向后跳转:FCh = -4 in two's compliment negative number.但令我惊讶的是,java 将 FCh 添加到 PC 使其 不正确 跳转到 C934h 而不是返回 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)

我在 java 代码中对此进行了测试,结果确实是一样的:

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

为了解决这个问题,我必须在检查第一位是否为 1 后将 FCh 转换为一个字节,它是:11111100

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

简而言之,我想我的问题是我认为 java 会知道 FCh 是一个负数,但事实并非如此,除非我将它转换为一个字节。为什么?抱歉,我知道这个问题被问过很多次,而且我自己也经常问这个问题。

0xfc 是正数。如果你想要一个负数,那就写一个负数。 -0x4 就可以了。

但是如果你想将它应用到非常量数据,你需要告诉 Java 你希望它以某种方式进行符号扩展。
问题的核心是您有一个 32 位有符号整数,但您希望将其视为 8 位有符号整数。实现这一点的最简单方法就是像上面那样使用 byte

如果实在不想写byte,可以写(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);
    }
}

24源自int(32位)和byte(8位)大小的差异。