Schreiben Sie ein selbstreplizierendes Programm.

11

Schreiben Sie ein einfaches Programm, das sich bei der Ausführung selbst kopiert.

Ihr Programm sollte eine Art ausführbare Datei unter Windows, Linux usw. sein, eine neue ausführbare Datei generieren, die mit Ihrer ursprünglichen ausführbaren Datei identisch ist, mit zufälligem Namen und beendet wird.

Ihr Programm sollte keinerlei Dateien lesen oder kopieren. Es ist nur das Schreiben von Dateien zum Generieren einer neuen ausführbaren Datei zulässig.

(PS. Es war mir ziemlich peinlich, als ich bei Wikipedia Self-replicating programzum Computer virusArtikel weiterleitete ...: / ...)

Die kleinste ausführbare Dateigröße gewinnt. Ihre Antwort kann ein Programmiercode mit dem richtigen Betriebssystem und Compiler, Assemblycode oder HEX-Dump einer ausführbaren Datei sein.

JiminP
quelle
6
Dies scheint sich nur geringfügig von den bestehenden Herausforderungen zu unterscheiden. Oder habe ich falsch verstanden?
dmckee --- Ex-Moderator Kätzchen
1
@dmckee Ich habe gesehen, wie Assembly Language Quine und Self das Hello World-Programm replizierten , das Kopieren akzeptierte, aber ich konnte nicht finden, dass das Programm selbst schreibt , nicht den Code .
JiminP
1
... aber ich möchte sehen, wie es tatsächlich funktioniert! .. Ich weiß nicht, wie die Idee mit Binärcodes erweitert werden kann .. obwohl ich Quine-Artikel bei Wikipedia gelesen habe. PS. Es sind keine Compiler zum Replizieren und keine Skriptsprachen erlaubt ...: /
JiminP
4
Jedes Problem kann etwas schwieriger und hässlicher gemacht werden, indem weitere Einschränkungen hinzugefügt werden. Ich finde dieses Problem eine triviale Erweiterung des Quine-Problems.
Alexandru
1
Wenn die kleinste ausführbare Größe gewinnt, sollten wir dann nicht auch den Interpretercode als Teil der ausführbaren Größe berücksichtigen, damit dies für Benutzer kompilierter Sprachen fair ist?
Thomas Dignan

Antworten:

4

Bash, 236

Länger als unbedingt nötig, aber ich hasse lange Schlangen. Die nachfolgende Newline ist nicht optional.

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 $$
JB
quelle
Eigentlich ist es jedoch nicht das, was ich wollte, da ich eine "falsche" Frage geschrieben habe und Ihre Antwort eine großartige Frage ist ...
JiminP
@JiminP: Wie ist es nicht was du wolltest? Ich habe die Problembeschreibung nur noch zweimal gelesen und verstehe sie nicht.
JB
Nun ... was ich wollte, war ein ausführbarer Binärcode. Wie ich oben zugegeben habe, da meine Frage nicht ganz "richtig" war ... Entschuldigung.
JiminP
3
@JiminP Ja, das Wort "binär" kommt in der Frage überhaupt nicht vor. Ich habe es gerade in den Kommentaren gefunden, aber für eine solche Einschränkung schneidet es einfach nicht. Sie können eine neue Frage mit allen konsolidierten Eingaben aus den Kommentaren öffnen. Ich schlage vor, Sie haben den Sandkasten benutzt, um sicherzustellen, dass die Stammgäste Ihnen helfen, die kleinen Details auszubügeln. Aber Vorsicht, binäre Antworten sind in der Regel sehr langweilig.
JB
10

Assembly für x86 Linux, 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     $ - $$

Dies ist für den Nasm-Assembler. Erstellen Sie die Binärdatei mit der Befehlszeile:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Hier ist dieselbe Datei wie ein Hex-Dump: 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

Wie gewünscht kopiert sich das Programm in eine separate Datei. (Das Programm hätte erheblich kürzer sein können, wenn es nur in stdout schreiben und den Benutzer in eine Datei umleiten lassen hätte.)

Ich habe es vermieden, Borderline-Tricks zu verwenden, um die Größe zu reduzieren. Dies sollte eine vollständig konforme 32-Bit-ELF-Binärdatei sein.

Bearbeitet, um hinzuzufügen : In der obigen Version ist die erstellte Datei nur eine einfache Datei, aber mir fällt ein, dass Sie für ein paar Bytes (und eine winzige Biegung der Regeln) etwas Interessanteres erstellen können. Diese Version ist mit 108 Bytes nur zwei Bytes länger:

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     $ - $$

Nennen Sie diese Version asrfür "einen Selbstreplikator":nasm -f bin -o asr asr.asm && chmod +x asr

Hex Dump Version für Nasm-Beeinträchtigte: 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

Wenn Sie es ausführen, wird eine fast identische Datei mit dem Namen erstellt bsr, die jedoch selbst ausführbar ist. Wenn Sie es ausführen, wird eine weitere Binärdatei mit dem Namen erstellt csr. Und so weiter.

(Beachten Sie, dass nachher nervige Dinge passieren zsr. Ich habe überlegt, eine Version zu erstellen, die die Namensänderung kaskadiert atrund so weiter, aber ich denke, die meisten Leute werden sich vorher gut langweilen, daher ist es wahrscheinlich nicht alle zusätzlichen Bytes wert. )

Brot-Box
quelle
+1 für Montage Antwort! Haben Sie die Herausforderung der Montagequine gesehen ?
MD XF
2

Hier ist ein Proof-of-Concept (ungolfed), der zeigt, wie die Kompilierungsdienste in .NET verwendet werden können, um den Quellcode im laufenden Betrieb zu kompilieren und eine identische Ausgabe zu generieren. Die erste Kopie ist nicht identisch mit dem Original, aber nachfolgende Kopien aus nachfolgenden Läufen sind genau identisch mit zufälligen Dateinamen:

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);
        }
    }
}

Demonstrationsausgabe über die Befehlszeile:

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>
mellamokb
quelle
2

Stapel

Version 1 (30 Bytes)

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

Ich gewinne! :) :)

st0le
quelle
Die% 0-Referenz bewirkt einen Lesevorgang aus der Datei, der gegen die Regeln verstößt. Außerdem ist meine Binärversion noch kürzer. :-)
Peter Ferrie
1

DOS COM-Datei - 50 Bytes

Erstellt eine Datei, X.COMin Xder die Ziffer der aktuellen Zeit ersetzt wird. COM-Dateien werden einfach am Offset 100hdes Datensegments in den Speicher geladen (CS und DS sind gleich eingestellt), sodass wir diesen Speicher einfach in eine Datei schreiben können.

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.

Nasm Quelle

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 $-$$
Geoff Reedy
quelle
1

DOS .COM Datei, 29 Bytes

Das '@' wird zufällig durch einen ungeraden Buchstaben in der ersten Hälfte + Teil des Alphabets (A, C, E, G usw.) ersetzt. Ausgabedateien sind entweder 255 oder 256 Byte. Anfangsregister unter echtem DOS (im Gegensatz zu einem Debugger) sind 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
Peter Ferrie
quelle
0

DOS COM-Datei - 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 

Der Name der Ausgabedatei wird in der Befehlszeile angegeben und auf das 8.3-Format gekürzt. Leerzeichen sind OK (Leerzeichen in DOS-Dateinamen sind zulässig). Getestet mit der WinXP-Eingabeaufforderung.

Skizz
quelle