Escreva um programa de replicação automática.


11

Escreva um programa simples que se copie quando executado.

Seu programa deve ser algum tipo de arquivo executável no Windows, Linux, etc., deve gerar um novo arquivo executável, que é idêntico ao seu arquivo executável original, com nome aleatório e é encerrado.

Seu programa não deve envolver nenhum tipo de leitura ou cópia de arquivo. Somente gravação de arquivo para gerar novo arquivo executável é permitida.

(PS. Fiquei bastante envergonhado quando na Wikipedia, Self-replicating programredireciona para o Computer virusartigo ...: / ...)

O menor tamanho de arquivo executável vence. Sua resposta pode ser um código de programação com SO e compilador adequados, código de montagem ou despejo HEX de um arquivo executável.


6
Isso parece variar apenas trivialmente dos desafios existentes. Ou eu entendi errado?
dmckee --- gatinho ex-moderador

1
@dmckee Vi o programa Hello World em linguagem Assembly e auto-replicante aceitando copiar, mas não consegui encontrar o programa que escreve por si só , não pelo código .
JiminP

1
... mas quero ver como ele realmente funciona! ... não sei como a idéia pode ser estendida com códigos binários .. mesmo que eu tenha lido o artigo de Quine na Wikipedia. PS. nenhum compilador para replicação e nenhuma linguagem de script é permitida ...: /
JiminP

4
Qualquer problema pode ser um pouco mais difícil e mais feio, adicionando mais restrições a ele. Acho esse problema uma extensão trivial do problema do quine.
Alexandru

1
Se o menor tamanho de executável vencer, também não deveríamos levar em consideração o código do interpretador como parte do tamanho do executável para que isso seja justo para os usuários de linguagens compiladas?
Thomas Dignan

Respostas:


4

Bash, 236

Mais do que o estritamente necessário, mas eu odeio longas filas. A nova linha à direita não é opcional.

b=\\ q=\' r=\> d=\$
s='exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q'
t='echo t=$q$t$q; echo $s; echo $t; chmod 777 $$'
exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q
echo t=$q$t$q; echo $s; echo $t; chmod 777 $$

Na verdade, não é o que eu queria, no entanto, desde que eu escrevi uma pergunta "errada" e sua resposta é um grande Quine ...
JiminP

@JiminP: Como não é o que você queria? Acabei de ler a descrição do problema novamente e não entendi.
JB

Bem ... o que eu queria era um código binário executável. Como eu admiti acima, já que minha pergunta não era 'certa' ... desculpe por isso.
JiminP 28/09

3
@JiminP Bem, sim, a palavra "binário" não aparece na pergunta. Acabei de encontrá-lo nos comentários, mas para tal restrição, simplesmente não é suficiente. Você pode abrir uma nova pergunta com todas as informações consolidadas dos comentários. Sugiro que você use a sandbox para garantir que os frequentadores o ajudem a resolver os pequenos detalhes. Mas cuidado, respostas binárias tendem a ser muito chatas.
JB

10

Montagem para Linux x86, 106 bytes

BITS 32
                org     0x2E620000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname           equ     $ - 2
                db      'out', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      5                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 666q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

Isto é para o montador nasm. Crie o binário com a linha de comando:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Aqui está o mesmo arquivo que um dump hexadecimal: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 62 2E 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 62 2E 6F 75 74 00 6A 00 00 00 6A 00 00 00 05 00 00 00 00 10 00 00 B0 05 BB 36 00 62 2E B1 41 66 BA B6 01 CD 80 8D 51 29 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

Conforme solicitado, o programa se copia para um arquivo separado. (O programa poderia ter sido significativamente mais curto se tivesse sido permitido apenas gravar no stdout e permitir que o usuário redirecionasse para um arquivo.)

Evitei usar truques limítrofes para reduzir o tamanho. Este deve ser um binário ELF de 32 bits totalmente compatível.

Editado para adicionar : Na versão acima, o arquivo criado é apenas um arquivo simples, mas me ocorre que, por alguns bytes (e uma pequena parte das regras), você pode criar algo um pouco mais interessante. Esta versão possui apenas dois bytes a 108 bytes:

BITS 32
                org     0x00010000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname:          db      'asr', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      7                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                inc     byte [ebx]
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 777q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

Nomeie esta versão asr, para "um auto-replicador":nasm -f bin -o asr asr.asm && chmod +x asr

Versão de dump hexadecimal para pessoas com deficiência nasm: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 01 00 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 01 00 61 73 72 00 6C 00 00 00 6C 00 00 00 07 00 00 00 00 10 00 00 B0 05 BB 38 00 01 00 FE 03 B1 41 66 BA FF 01 CD 80 8D 51 2B 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

Quando você o executa, ele cria um arquivo quase idêntico chamado bsr, mas que é ele próprio executável. A execução criará outro arquivo binário chamado csr. E assim por diante.

(Observe que coisas irritantes começam a acontecer depois zsr. Pensei em criar uma versão que mudaria em cascata para o nome atre assim por diante, mas acho que a maioria das pessoas ficará entediada antes disso, então provavelmente não vale todos os bytes extras. )


+1 para resposta de montagem! Você já viu o desafio da assembléia ?
MD XF

2

A seguir, uma prova de conceito (não destruída) que mostra como os serviços de Compilação no .NET podem ser usados ​​para compilar o código-fonte em tempo real para gerar uma saída idêntica. A primeira cópia não é idêntica ao original, mas as cópias subsequentes das execuções subsequentes são exatamente idênticas aos nomes de arquivos aleatórios:

using System;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace _2947
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world!");

            var s = @"
using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace _2947
{{
    class Program
    {{
        static void Main(string[] args)
        {{
            Console.WriteLine({1}Hello world!{1});

            var s = @{1}{0}{1};
            s = string.Format(s, s, '{1}');

            string exeName = Environment.CurrentDirectory + @{1}\{1} + new Random().Next(1000, 9999) + {1}.exe{1};

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add({1}System.dll{1});

            var c = CSharpCodeProvider.CreateProvider({1}cs{1});
            var cr = c.CompileAssemblyFromSource(cp, s);
        }}
    }}
}}
";
            s = string.Format(s, s, '"');

            string exeName = Environment.CurrentDirectory + @"\" + new Random().Next(1000, 9999) + ".exe";

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add("System.dll");

            var c = CSharpCodeProvider.CreateProvider("cs");
            var cr = c.CompileAssemblyFromSource(cp, s);
        }
    }
}

Saída de demonstração na linha de comando:

C:\projects\codegolf\2947\2947\bin\Debug>2947
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 8425.exe
               4 File(s)         39,760 bytes
               2 Dir(s)   6,486,368,256 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>8425
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               5 File(s)         46,416 bytes
               2 Dir(s)   6,486,360,064 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>7538
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 4127.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               6 File(s)         53,072 bytes
               2 Dir(s)   6,486,351,872 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>

2

Lote

Versão 1 (30 bytes)

type%0>%random%.bat&type%0>con

Eu ganhei! :)


a referência% 0 causa uma leitura do arquivo, o que viola as regras. Além disso, minha versão binária é ainda mais curta. :-)
peter ferrie

1

Arquivo COM DOS - 50 bytes

Cria um arquivo X.COMonde Xé substituído pelo dígito das unidades da hora atual. Os arquivos COM são simplesmente carregados na memória no deslocamento 100hdo segmento de dados (o CS e o DS estão configurados para serem os mesmos), para que possamos simplesmente gravar essa memória em um arquivo.

0000000: b402 cd1a 80e6 0f80 ce30 8836 2c01 31c9  .........0.6,.1.
0000010: ba2c 01b4 3ccd 21c6 062c 0178 89c3 b440  .,..<.!..,.x...@
0000020: ba00 01b9 3200 cd21 b44c cd21 782e 636f  ....2..!.L.!x.co
0000030: 6d00                                     m.

fonte nasm

org 100h ; this is a COM file
mov ah,02h ; fn=get time
int 1ah ; rtc interrupt
; convert to ascii - dh gets ones digit of seconds
and dh,0fh
or dh,30h
mov [fname],dh ; move time into filename
xor cx,cx ; clear attributes
mov dx,fname ; load filename
mov ah,3ch ; fn=create file
int 21h ; dos interrupt
mov byte [fname],'x' ; reset filename
mov bx,ax ; set filehandle
mov ah,40h ; fn=write to file
mov dx,100h ; offset is the loaded binary
mov cx,len ; length of write
int 21h ; dos iterrupt
mov ah,4ch ; fn=exit
int 21h ; dos interrupt
fname: db 'x.com',0
len equ $-$$

1

Arquivo .COM do DOS, 29 bytes

O '@' é substituído aleatoriamente por uma letra ímpar na primeira metade + parte do alfabeto (A, C, E, G, etc). Os arquivos de saída são 255 ou 256 bytes. Registradores iniciais no DOS real (em oposição a um depurador) são AX = 0000, CX = 00FF, SI = 0100.

40       INC  AX         ;"@"
2E       CS:             ;"."
43       INC  BX         ;"C"
4F       DEC  DI         ;"O"
4D       DEC  BP         ;"M"
00 20    ADD  [BX+SI],AH ;"\0" and dummy parm
E4 40    IN   AL,40
24 0F    AND  AL,0F
0C 41    OR   AL,41
88 04    MOV  [SI],AL
B4 3C    MOV  AH,3C
41       INC  CX
89 F2    MOV  DX,SI
CD 21    INT  21
93       XCHG BX,AX
B4 40    MOV  AH,40
49       DEC  CX
CD 21    INT  21
C3       RET

0

Arquivo COM DOS - 36 bytes

56 BE 80 00 AD FE C8 A2 10 01 7E 17 89 F2 88 74
02 B4 3C 33 C9 CD 21 72 0A 8B D8 B4 40 5A B9 24
00 CD 21 C3 

O nome do arquivo de saída é especificado na linha de comando, truncado para o formato 8.3, espaços OK (os espaços nos nomes de arquivos do DOS são legais). Testado usando o prompt de comando WinXP.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.