Viết chương trình tự sao chép.


11

Viết một chương trình đơn giản tự sao chép khi thực thi.

Chương trình của bạn phải là một số loại tệp thực thi trên Windows, Linux, v.v., sẽ tạo tệp thực thi mới, giống hệt với tệp thực thi ban đầu của bạn, với tên ngẫu nhiên và thoát.

Chương trình của bạn không nên liên quan đến bất kỳ loại đọc hoặc sao chép tập tin. Chỉ cho phép viết tập tin để tạo tập tin thực thi mới.

(PS. Tôi đã khá lúng túng khi ở Wikipedia, Self-replicating programchuyển hướng đến Computer virusbài viết ...: / ...)

Kích thước tập tin thực thi nhỏ nhất chiến thắng. Câu trả lời của bạn có thể là mã lập trình với hệ điều hành & trình biên dịch phù hợp, mã lắp ráp hoặc kết xuất HEX của tệp thực thi.


6
Điều này dường như chỉ thay đổi tầm thường so với các thách thức [quine] hiện có. Hay tôi đã hiểu lầm?
dmckee --- ex-moderator mèo con

1
@dmckee Tôi thấy hội thảo Ngôn ngữ hội thảoTự sao chép chương trình Hello World chấp nhận sao chép, nhưng tôi không thể tìm thấy chương trình tự viết , không phải của nó .
JiminP

1
... nhưng tôi muốn xem nó thực sự hoạt động như thế nào! .. Tôi không biết làm thế nào ý tưởng có thể được mở rộng bằng mã nhị phân .. mặc dù tôi đã đọc bài viết của Quine tại Wikipedia. Tái bút không có trình biên dịch để sao chép và không cho phép ngôn ngữ script ...: /
JiminP

4
Bất kỳ vấn đề nào cũng có thể trở nên khó hơn và xấu hơn bằng cách thêm nhiều ràng buộc hơn vào nó. Tôi thấy vấn đề này là một phần mở rộng tầm thường của vấn đề quine.
Alexandru

1
Nếu kích thước thực thi nhỏ nhất chiến thắng, chúng ta cũng không nên tính đến mã trình thông dịch như là một phần của kích thước thực thi để điều này công bằng với người dùng ngôn ngữ được biên dịch?
Thomas Dignan

Câu trả lời:


4

Bash, 236

Dài hơn cần thiết, nhưng tôi ghét dài dòng. Dòng mới theo dõi là không tùy chọn.

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

Trên thực tế, đó không phải là điều tôi muốn, tuy nhiên, vì tôi đã viết một câu hỏi "sai" và câu trả lời của bạn là một câu hỏi hay ...
JiminP

@JiminP: Làm thế nào nó không phải là những gì bạn muốn? Tôi chỉ đọc mô tả vấn đề hai lần nữa, và không hiểu.
JB

Chà ... những gì tôi muốn là một mã nhị phân thực thi. Như tôi đã thừa nhận ở trên, vì câu hỏi của tôi không hoàn toàn "đúng" ... xin lỗi vì điều đó.
JiminP

3
@JiminP Vâng, vâng, từ "nhị phân" hoàn toàn không xuất hiện trong câu hỏi. Tôi chỉ tìm thấy nó trong các ý kiến, nhưng đối với một hạn chế như vậy, nó chỉ không cắt nó. Bạn có thể mở một câu hỏi mới với tất cả các đầu vào hợp nhất từ ​​các bình luận. Tôi đề nghị bạn sử dụng hộp cát để đảm bảo các bộ điều chỉnh giúp bạn giải quyết các chi tiết nhỏ. Nhưng hãy cẩn thận, câu trả lời nhị phân có xu hướng thực sự nhàm chán.
JB

10

Hội cho x86 Linux, 106 byte

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

Đây là cho trình biên dịch hợp ngữ. Xây dựng nhị phân với dòng lệnh:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Đây là cùng một tệp như một kết xuất hex: 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

Theo yêu cầu, chương trình tự sao chép vào một tệp riêng biệt. (Chương trình có thể đã ngắn hơn đáng kể nếu nó được phép chỉ ghi vào thiết bị xuất chuẩn và cho phép người dùng chuyển hướng đến một tệp.)

Tôi tránh sử dụng bất kỳ thủ thuật biên giới để giảm kích thước. Đây phải là một nhị phân ELF 32 bit hoàn toàn phù hợp.

Chỉnh sửa để thêm : Trong phiên bản trên, tệp được tạo chỉ là một tệp đơn giản, nhưng đối với tôi, đối với một vài byte (và một chút quy tắc nhỏ), bạn có thể tạo ra thứ gì đó thú vị hơn một chút. Phiên bản này chỉ dài hơn hai byte, ở mức 108 byte:

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

Đặt tên cho phiên bản này là asr"tự sao chép":nasm -f bin -o asr asr.asm && chmod +x asr

Phiên bản kết xuất hex cho người khuyết tật: 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

Khi bạn chạy nó, nó tạo ra một tệp gần như giống hệt nhau bsr, nhưng một tệp có thể thực thi được. Chạy nó sẽ tạo một tệp nhị phân khác có têncsr . Và như thế.

(Lưu ý rằng những điều gây phiền nhiễu bắt đầu xảy ra sau đó zsr. Tôi đã cân nhắc việc tạo một phiên bản xếp tầng thay đổi tên atr, v.v., nhưng tôi nghĩ rằng hầu hết mọi người sẽ chán trước đó, vì vậy có lẽ nó không đáng giá cho tất cả các byte bổ sung. )


+1 cho câu trả lời lắp ráp! Bạn đã thấy thử thách quine lắp ráp ?
MD XF

2

Dưới đây là một bằng chứng khái niệm (chưa được xử lý) cho thấy cách các dịch vụ Biên dịch trong .NET có thể được sử dụng để biên dịch mã nguồn đang hoạt động để tạo ra một đầu ra giống hệt nhau. Bản sao đầu tiên không giống với bản gốc, nhưng các bản sao tiếp theo từ các lần chạy tiếp theo giống hệt với tên tệp ngẫu nhiên:

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

Đầu ra trình diễn trên dòng lệnh:

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

Lô hàng

Phiên bản 1 (30 byte)

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

Tôi thắng! :)


tham chiếu% 0 gây ra đọc từ tệp, vi phạm các quy tắc. Bên cạnh đó, phiên bản nhị phân của tôi thậm chí còn ngắn hơn. :-)
perr ferrie

1

Tệp COM DOS - 50 byte

Tạo một tệp X.COMtrong đó Xđược thay thế bằng chữ số của thời điểm hiện tại. Các tệp COM chỉ được tải vào bộ nhớ ở phần bù 100hcủa phân đoạn dữ liệu (CS và DS được đặt là giống nhau) vì vậy chúng ta chỉ cần ghi bộ nhớ này ra một tệp.

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.

nguồn 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

Tệp DOS .COM, 29 byte

'@' Được thay thế ngẫu nhiên bằng một chữ cái lẻ trong nửa đầu + một phần của bảng chữ cái (A, C, E, G, v.v.). Các tệp đầu ra là 255 hoặc 256 byte. Các thanh ghi ban đầu trong DOS thực (trái ngược với trình gỡ lỗi) là 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

Tệp COM DOS - 36 byte

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 

Tên tệp đầu ra được chỉ định trên dòng lệnh, được cắt ngắn thành định dạng 8.3, khoảng trắng OK (khoảng trắng trong tên tệp DOS là hợp pháp). Đã kiểm tra bằng dấu nhắc lệnh WinXP.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.