web-dev-qa-db-ja.com

バージョン5Unixではどのチェックサムアルゴリズムが使用されていますか?

UnixV5およびV6でsumコマンドにどのアルゴリズムが使用されたかわかりません。

最初は、バイトモジュラス2 ^ 16の単純な合計だと思いました。ただし、文字列「1111111111\n」が320回繰り返されると、28930のチェックサムが計算されます( Julius SchmidtのPDP-11エミュレーターを使用 JavaScriptの場合)。そのための単純なバイトの合計は2バイト小さいのに対し:

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

後で、 MacOSのマニュアルページ から、sumコマンドとcksumコマンドには長い矛盾の歴史があることがわかりました。ただし、MacOSで提供されている「歴史的な」アルゴリズムバージョンでさえ、UnixV5のチェックサムに同意していません。最も近い一致は、UNIX SystemVのデフォルトのsumコマンド(Macではcksum -o 2のように呼び出されます)です。これは、この文字列に対して同じチェックサムを返しますが、他の文字列については一致しません。

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

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

これは本物の動作ですか、それともエミュレータのバグですか?それが本物である場合、それはどのアルゴリズムですか?

P.S. 1974年のアセンブリコードを誰かが読めるなら、これが ソースコード です。

4
Andriy Makukha

最初は、バイトモジュラス2 ^ 16の単純な合計だと思いました

これはsummod 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プログラムに入れます(./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 -o2とUnixV5の合計は、ほとんどのテキストファイルに同意しますが、エミュレーター内のほとんどのバイナリファイル(たとえば、フォルダー/ bin)に対して異なる出力を生成します。

これは、元のunix v5 sumが文字を符号拡張し、バイナリのみにバイト> = 0x80が含まれるためです。それ以外の場合、アルゴリズムは類似しており、非常に大きなファイル(文字の合計が32ビットのunsigned intをオーバーフローする)でのみ異なります。

4
palupicu