Não consigo descobrir qual algoritmo foi usado no Unix V5 e V6 para o sum
comando.
A princípio, pensei que fosse uma simples soma de bytes módulo 2^16. No entanto, para uma string "1111111111\n" repetida 320 vezes, ela calcula uma soma de verificação de 28930 (usando o emulador PDP-11 de Julius Schmidt para JavaScript). Considerando que uma simples soma de bytes para ele é dois bytes menor:
$ python -c 'print(sum(bytearray(b"1111111111\n"*320)) & 0xFFFF)'
28928
Mais tarde, nas páginas man do MacOS , descobri que os comandos sum
e cksum
tinham um longo histórico de inconsistências. No entanto, mesmo as versões "históricas" do algoritmo fornecidas no MacOS não concordam com a soma de verificação do Unix V5. A correspondência mais próxima é o comando padrão sum
do UNIX System V (invocado no Mac como cksum -o 2
), que retorna a mesma soma de verificação para esta string, mas discorda para outras:
$ python -c 'print("1111111111\n"*320, end="")' | cksum -o 2
28930 7
Para ser mais específico, o cksum -o 2
e o Unix V5 sum
produzem saídas diferentes para a maioria dos arquivos binários no emulador (por exemplo, na pasta /bin
), embora concordem na maioria dos arquivos de texto.
Este é um comportamento genuíno ou um bug no emulador? Se for genuíno, qual é o algoritmo?
PS Aqui está o código fonte , se alguém puder ler o código assembly de 1974.
É uma soma mod 2^16, só que cada vez que estourar, um 1 será adicionado a ela. Além disso, os bytes serão estendidos antes de serem adicionados à soma. Aqui está um trecho "comentado" da montagem:
o mesmo colocado em um pequeno programa C (use como
./v5sum < file
):Isso porque o unix original v5
sum
assinará estender os caracteres e apenas os binários contêm bytes >= 0x80. Caso contrário, os algoritmos devem ser semelhantes e diferir apenas com arquivos muito grandes (onde a soma dos caracteres transbordará um int não assinado de 32 bits).