Bit shifting in internet checksums

筅森魡賤 提交于 2019-11-29 14:46:04

You are almost right.

The high 16 bits could have been 1 due to a carry.

For example, FFFF + FFFF => 1FFFE, or perhaps FFFF + 1 => 10000.

This is part of the definition of a one's complement sum. You take any overflow bits and add them back to the lower 16 bits. Adding them back could cause further overflow, so you repeat this until the upper bits end up all zero. So, conceptually it's this:

while (sum >> 16 != 0) {
    sum = (sum >> 16) + (sum & 0xffff);
}

However this loop will only ever execute at most twice, so an explicit loop is not necessary. After the first addition there may or may not be an overflow with a carry bit ending up in the upper 16 bits. In that case the upper 16 bits will be 0x0001 and you will have to do one more addition to add that carry bit back in.

Imagine the worst case where sum ends up as 0xffffffff after the initial while loop. Then the additions will proceed as follows:

sum = (0xffffffff >> 16) + (0xffffffff & 0xffff)
    = 0xffff + 0xffff
    = 0x1fffe

sum = (0x1fffe >> 16) + (0x1fffe & 0xffff)
    = 0x1 + 0xfffe
    = 0xffff

And there with two additions we are finished as the upper 16 bits are now clear. This is the worst case, so the loop can thus be unrolled to two additions.

(And then after all that you take the one's complement of the final sum, leading to the highly confusing name for this: the one's complement of the one's complement sum. It took me a long time to wrap my head around this the first time I implemented it—in particular that a one's complement sum does not involve the ~ complement operator.)

I thought that a ulong was 32 bits wide which means that:

sum = (sum >> 16) + (sum & 0xffff)
sum += (sum >> 16);

Adds the top sicteen bits and bottom sisteen bits together. And then the next line makes sum the result of the top sixteen bits; which could have a one in it due to a carry operation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!