2016-04-30 68 views
1

上下文: 我的老师将Darwin-OP框架从C++移植到Java,允许像我这样的学生使用它,而无需掌握C++。达尔文有两个控制器:主控制器运行Linux并运行java代码,并且与控制所有传感器/伺服器/传感器等的子控制器(微控制器)的串行连接。这段代码如何验证校验和?

达尔文使用motion.bin在其中存储256页的列表的文件。每页是512(8 * 64)字节,由7个步骤(每个64字节)加页面标题(也是64字节)组成。每个步骤都包含伺服所需的位置(介于0-4095之间的值)。因此,为达尔文移动他的胳膊,他会经历(< 7)的步骤数量,直到他完成最后一步。

在页眉中有一个字节的校验和。 Java代码包含在校验和计算和验证两种方法:

private static boolean VerifyChecksum(PAGE page) { 
    byte checksum = (byte)0x00; 
    byte[] pagebytes = page.GetBytes(); 
    for (int i = 0; i < pagebytes.length; i++) { 
     checksum += pagebytes[i]; 
    } 
    if (checksum != (byte)0xFF) { 
     return false; 
    } 
    return true; 
} 

private static void SetChecksum(PAGE page) { 
    byte checksum = (byte)0x00; 
    byte[] pagebytes = page.GetBytes(); 
    page.header.checksum = (byte)0x00; 
    for (int i = 0; i < pagebytes.length; i++) { 
     checksum += pagebytes[i]; 
    } 
    page.header.checksum = (byte)((byte)0xFF - checksum); 
} 

主要问题:有人可以解释校验是如何验证?我不明白为什么它会检查checksum != (byte)0xFF。为什么不直接比较计算的checksumpage.header.checksum

奖励问题:为什么首先检查文件的完整性? .bin文件中的页面是否会被破坏?

回答

2

要计算校验和,您执行文件中所有字节的XOR,然后返回0xFF减去该值。
传入校验和方法的文件是校验和位置中带有0x00的最终文件。

sum = 0xFF - XOR(file) 

对于二进制,除了是一样的XOR,因此线checksum += pagebytes[i];

你教授的验证方法,将异或整个文件。也就是说,校验和方法的原始参数,以及作为校验和方法输出的附加字节。

因此,预期的结果则是:

XOR(file, sum) 
= XOR(file) + sum 
= XOR(file) + 0xFF - XOR(file) 
= 0xFF 
+0

必须是一种常见的做法的范围内,因为它是不评论...谢谢:) – user1534664

+0

我理解XOR(文件)必须为0x00才能变为0xFF。但是,我不明白的是你如何知道校验和事先是0x00。为什么即使您不打算在验证中使用它,甚至还会将校验和存储在page.header中? – user1534664

+0

@ user1534664而不是提取它并重新校验和比较,你的教授只是利用了一点小技巧。它仍在使用而没有提取,因为如果该值不在标题中,该技巧将不起作用。 –

0

假设标题是页面的一部分。然后计算所有字节x的总和,并存储255-x作为校验和。验证时,计算y + 255 - x必须等于255.如果是,则x和y是相同的数字。

注意,所有的计算都进行模256,因此x和y总是在0到255