0

我尝试用 Java 计算 Sega Genesis rom 文件的校验和。为此,我想将从 C 中截取的代码移植到 Java 中:

static uint16 getchecksum(uint8 *rom, int length)
{
  int i;
  uint16 checksum = 0;

  for (i = 0; i < length; i += 2)
  {
    checksum += ((rom[i] << 8) + rom[i + 1]);
  }

  return checksum;
}

我了解代码的作用。它将所有 16 位数字相加(由两个 8 位数字组合而成)。但我不明白的是 uint16 的溢出发生了什么以及它如何转移到 Java 代码?

编辑:此代码似乎有效,谢谢:

int calculatedChecksum = 0;
int bufferi1=0;
int bufferi2=0;
bs = new BufferedInputStream(new FileInputStream(this.file));

bufferi1 = bs.read();
bufferi2 = bs.read();
while(bufferi1 != -1 && bufferi2 != -1){
    calculatedChecksum += (bufferi1*256 + bufferi2);
    calculatedChecksum = calculatedChecksum % 0x10000;
    bufferi1 = bs.read();
    bufferi2 = bs.read();
}
4

3 回答 3

1
static int checksum(final InputStream in) throws IOException {
  short v = 0;
  int c;
  while ((c = in.read()) >= 0) {
    v += (c << 8) | in.read();
  }
  return v & 0xffff;
}

这应该等效地工作;通过使用& 0xffff,我们可以将 in 中的值v视为一直无符号,因为算术溢出是相同的 wrt 位。

于 2012-08-28T23:31:35.377 回答
1

简单地说,溢出就丢失了。更正确的方法(恕我直言)是使用 uint32 进行求和,然后在低 16 位得到总和,在高 16 位得到溢出。

于 2012-08-28T22:46:18.657 回答
0

您想要添加模 2 16,您可以简单地手动拼出:

checksum = (checksum + ((rom[i] << 8) + rom[i + 1])) % 0x10000;
//                                                   ^^^^^^^^^
于 2012-08-29T05:56:47.503 回答