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年のアセンブリコードを誰かが読めるなら、これが ソースコード です。
最初は、バイトモジュラス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をオーバーフローする)でのみ異なります。