Напишіть програму самовідтворення.


11

Напишіть просту програму, яка копіює себе при виконанні.

У вашій програмі має бути якийсь виконуваний файл у Windows, Linux та ін., Повинен генерувати новий виконуваний файл, ідентичний вашому оригінальному виконуваному файлу, із випадковим іменем та закривається.

Ваша програма не повинна передбачати читання чи копіювання файлів. Дозволяється лише запис файлів для створення нового виконуваного файлу.

(PS. Я був дуже збентежений, коли у Вікіпедії Self-replicating programпереспрямовує на Computer virusстаттю ...: / ...)

Виграє найменший розмір файлу. Вашою відповіддю може бути код програмування з належним ОС і компілятором, кодом складання або дамп-файлом виконуваного файлу.


6
Це, здається, відрізняється лише тривіально від існуючих проблем [quine]. Або я неправильно зрозумів?
dmckee --- кошеня колишнього модератора

1
@dmckee я побачив асемблер Куайн і самовідтворюється програму Hello World приймає копіювання, але я не міг знайти програму пише сам , а не її код .
JiminP

1
... але я хочу побачити, як це насправді працює! .. Я не знаю, як ідею можна поширити за допомогою двійкових кодів .., хоча я читав статтю Quine у ​​Вікіпедії. PS. жодні компілятори для реплікації та мови скриптів заборонені ...: /
JiminP

4
Будь-яку проблему можна зробити трохи важче і негарніше, додавши до неї більше обмежень. Я вважаю цю проблему тривіальним розширенням проблеми quine.
Олександру

1
Якщо виграє найменший розмір виконуваного файлу, чи не слід також враховувати код інтерпретатора як частину виконавчого розміру, щоб це було справедливим для користувачів скомпільованих мов?
Томас Дігнан

Відповіді:


4

Баш, 236

Довше, ніж суворо потрібно, але я ненавиджу довгі рядки. Новий рядок не є обов'язковим.

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

Насправді, це не те, чого я хотів, оскільки я написав "неправильне" запитання, і ваша відповідь - це чудова черга ...
JiminP

@JiminP: Як це не те, чого ти хотів? Я просто ще раз прочитав опис проблеми і не зрозумів.
JB

Ну ... те, що я хотів, - це виконуваний двійковий код. Як я визнав вище, оскільки моє запитання було не зовсім «правильним» ... вибачте за це.
JiminP

3
@JiminP Ну, так, слово "бінарний" взагалі не виникає у питанні. Я просто знайшов це в коментарях, але для такого обмеження він просто не скорочує. Ви можете відкрити нове запитання з усім консолідованим вкладом із коментарів. Я пропоную вам скористатися пісочницею, щоб регулярно допомогти вам випрасувати дрібні деталі. Але будьте обережні, двійкові відповіді, як правило, справді нудні.
JB

10

Збірка для x86 Linux, 106 байт

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

Це для ассемблера nasm. Побудуйте двійковий файл за допомогою командного рядка:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Ось такий самий файл, як і шістнадцятковий дамп: 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

За потребою програма копіює себе в окремий файл. (Програма могла бути значно коротшою, якби їй було дозволено просто записати в stdout і дозволити користувачеві перенаправляти файл.)

Я уникав використовувати будь-які прикордонні трюки для зменшення розміру. Це має бути повністю сумісний 32-розрядний бінарний ELF.

Відредаговано, щоб додати : У наведеній версії створений файл - це просто звичайний файл, але мені здається, що за пару байтів (і крихітний вигин правил) ви можете створити щось трохи цікавіше. Ця версія на два байти більше, на 108 байт:

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

Назвіть цю версію asrдля "самовідтворювача":nasm -f bin -o asr asr.asm && chmod +x asr

Шістнадцятковий дамп-версія для людей з обмеженими можливостями: 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

Коли ви запускаєте його, він створює майже ідентичний файл з ім'ям bsr, але той, який сам виконується. Запустивши його, створимо ще один двійковий файл з назвою csr. І так далі.

(Зауважте, що набридливі речі починають відбуватися після zsr. Я розглядав можливість створення версії, яка б каскадувала зміну імені atrтощо), але, думаю, більшість людей заздалегідь набридне, тому, мабуть, не варто зайвих байтів. )


+1 за відповідь на збірку! Ви бачили виклик монтажному квіту ?
MD XF

2

Ось доказ концепції (neololfed), який показує, як служби компіляції в .NET можуть використовуватися для компіляції вихідного коду на ходу для отримання ідентичного виводу. Перша копія не ідентична оригіналу, але наступні копії з наступних циклів точно збігаються з випадковими іменами файлів:

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

Демонстраційний вихід у командному рядку:

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

Пакетна

Версія 1 (30 байт)

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

Я переміг! :)


посилання% 0 викликає зчитування з файлу, що порушує правила. Крім того, моя бінарна версія ще коротша. :-)
peter ferrie

1

Файл DOS COM - 50 байт

Створює файл, у X.COMякому Xзамінюється цифрою поточного часу. Файли COM просто завантажуються в пам'ять при зміщенні 100hсегменту даних (CS і DS встановлені однаково), тому ми можемо просто записати цю пам'ять у файл.

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.

джерело насма

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

Файл DOS .COM, 29 байт

'@' Замінюється випадковим чином непарною літерою у першій половині + частиною алфавіту (A, C, E, G тощо). Вихідні файли становлять 255 або 256 байт. Початкові регістри реального DOS (на відміну від налагоджувача) - це 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

Файл DOS COM - 36 байт

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 

Ім'я вихідного файлу вказується в командному рядку, усічене до формату 8.3, пробіли ОК (пробіли у назви файлів DOS є законними). Тестується за допомогою командного рядка WinXP.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.