Unix バージョン 5 はどのチェックサムアルゴリズムを使用しますか?

Unix バージョン 5 はどのチェックサムアルゴリズムを使用しますか?

Unix V5とV6のsumコマンドがどのアルゴリズムを使用しているのかわかりません。

最初は2^16モジュロバイトの単純な和だと思いました。ただし、320回繰り返される文字列 "1111111111\n"の場合、計算されるチェックサムは次のようになります。28930(使用Julius SchmidtのPDP-11エミュレータJavaScriptの場合)。そして、単純バイト合計は2バイト少ないです。

$ python -c 'print(sum(bytearray(b"1111111111\n"*320)) & 0xFFFF)'
28928

後で、MacOS のマニュアルページsum、長い間コマンドにcksum矛盾があることがわかりました。ただし、MacOSで利用可能なアルゴリズムの「過去」バージョンもUnix V5チェックサムと一致しません。最も近い一致はsumUNIX System Vの基本コマンド(Macで呼び出されるなどcksum -o 2)で、この文字列に対して同じチェックサムを返しますが、他のコマンドとは一致しません。

$ python -c 'print("1111111111\n"*320, end="")' | cksum -o 2
28930 7

具体的には、cksum -o 2Unix V5とUnix V5はほとんどのテキストファイルでは一貫性がありますが、sumエミュレータ(フォルダ内など)でほとんどのバイナリファイルに対して異なる出力を生成します。/bin

これは実際の動作ですか、それともエミュレータのバグですか?本当なら、アルゴリズムは何ですか?

PS:これソースコード誰もが1974年にアセンブリコードを読むことができれば。

答え1

最初は2^16モジュロバイトの単純な和だと思いました。

合計モードは2^16で、オーバーフローするたびに1ずつ増加します。さらに、バイトは合計に追加される前に符号拡張されます。以下はアセンブリの「コメント」の断片です。

# r2 is the pointer into the data
# r0 is the length of the data
# r5 is the sum
2:
        movb    (r2)+,r4    # r4 = sign_extend(*r2++)
        add     r4,r5       # r5 += r4
        adc     r5          # if(r5 overflowed) r5++
        sob     r0,2b       # if(--r0) goto 2 above

同じ内容を小さなCプログラムに入れる(asを使用./v5sum < file):

#include <stdio.h>
int main(void){
        int c, s = 0;
        while((c = getchar()) != EOF){
                s += c & 0x80 ? c | 0xff00 : c; // alternative: s += (unsigned short)(signed char)c
                if(s & 0x10000){ s++; s &= 0xffff; };
        }
        printf("%d\n", s);
        return 0;
}

具体的には、cksum -o 2とUnix V5のsumはほとんどのテキストファイルで一貫していますが、エミュレータ(/ binフォルダなど)のほとんどのバイナリに対して異なる出力を生成します。

これは、元のUnix v5のsum符号拡張文字とバイナリファイルにのみ0x80より大きいバイトが含まれているためです。そうでない場合、アルゴリズムは似ている必要があり、非常に大きなファイルでのみ異なります(文字合計は32ビット符号なし整数をオーバーフローします)。

関連情報