1

我正在尝试用 java 编写一个 Chip8 模拟器,我遇到了一个关于readAllBytesJava 函数的问题Files。当我将用于测试的 ROM 中的字节加载到模拟器的“内存”数组中时,我尝试打印这些字节以查看它们是否正确进入内存。我曾经Integer.toHexString将这些字节视为十六进制值,并将它们与我使用十六进制编辑器加载的实际文件进行比较,但它给我的输出很奇怪:

文件的第一个字节:

00 e0 a3 4c

测试输出:

0 ffffffe0 ffffffa3 4c

代码:

public void loadToMem(byte[] program) {
    for(int i = 0; i < program.length; i++) {
        this.memory[i+512] = program[i];
        System.out.println(Integer.toHexString(this.memory[i+512]));
    }
    this.initializeComponents();
}

这些值只是Integer.toHexString给出的表示中的一个错误,并且这些值正在正确加载,还是它们真的被错误地加载了?为什么用 f 填充?

4

1 回答 1

2

byteJava 中的值是有符号的 8 位值。因为e0a3每个都设置了它们的高位(它们的值 >=80十六进制),所以它们代表负值。然后,当您将它们传递给 时Integer.toHexString,这些值将扩展为 32 位值。您看到的是这些负 8 位值的等效 32 位十六进制表示。这称为二进制补码表示,它最常用于表示计算机内存中的有符号整数值。

使用二进制补码,具有十六进制值的有符号 8 位(单字节)整数具有e0十进制值 -32。十进制 -32 的有符号 32 位整数表示形式为ffffffe0十六进制。当您将二进制补码正值扩展到更广泛的表示时,您使用0s 填充。当你扩展一个负的二进制补码值时,你用值填充ff。将二进制补码值扩展到任意数量的字节时,其工作方式相同。

我们中的大多数人可能同意你的看法,这是我们第一次看到负整数在计算机内存中是如何解释的“有点奇怪”。

这是一个对二的补码的更简单解释的链接

于 2021-02-13T23:33:07.760 回答