Write a simple program that copies itself when executed.
Your program should be some kind of executable file on Windows, Linux, etc.., should generate new executable file, which is identical to your original executable file, with random name, and quits.
Your program shouldn't involve any kind of file reading or copying. Only file writing for generating new executable file is permitted.
(PS. I was quite embarrassed when at Wikipedia, Self-replicating program
redirects to Computer virus
article... :/...)
Smallest executable file size wins. Your answer may be a programming code with proper OS & compiler, assembly code, or HEX dump of a executable file.
-
6\$\begingroup\$ This seems to vary only trivially from the existing [quine] challenges. Or have I misunderstood? \$\endgroup\$dmckee --- ex-moderator kitten– dmckee --- ex-moderator kitten2011年06月22日 06:06:12 +00:00Commented Jun 22, 2011 at 6:06
-
1\$\begingroup\$ @dmckee I saw Assembly Language Quine and Self replicating Hello World program accepting copying, but I couldn't find program writes itself, not its code. \$\endgroup\$JiminP– JiminP2011年06月22日 06:19:43 +00:00Commented Jun 22, 2011 at 6:19
-
1\$\begingroup\$ ... but I want to see how it actually works!.. I don't know how the idea can be extended with binary codes.. even though I read Quine article at Wikipedia. PS. no compilers for replicating and no script languages are allowed... :/ \$\endgroup\$JiminP– JiminP2011年06月22日 06:26:04 +00:00Commented Jun 22, 2011 at 6:26
-
4\$\begingroup\$ Any problem can be made slightly harder and uglier by adding more constraints to it. I find this problem a trivial extension of the quine problem. \$\endgroup\$Alexandru– Alexandru2011年06月22日 10:22:40 +00:00Commented Jun 22, 2011 at 10:22
-
1\$\begingroup\$ If smallest executable size wins, shouldn't we also factor in the interpreter code as part of the executable size for this to be fair to users of compiled languages? \$\endgroup\$Thomas Dignan– Thomas Dignan2011年12月18日 19:16:04 +00:00Commented Dec 18, 2011 at 19:16
7 Answers 7
Assembly for 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 $ - $$
This is for the nasm assembler. Build the binary with the command line: nasm -f bin -o a.out selfrep.asm && chmod +x a.out
Here's the same file as a 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
As requested, the program copies itself to a separate file. (The program could have been significantly shorter if it had been allowed to just write to stdout and let the user redirect to a file.)
I avoided using any borderline tricks to reduce the size. This should be a fully conformant 32-bit ELF binary.
Edited to add: In the above version the created file is just a plain file, but it occurs to me that for a couple of bytes (and a tiny bend of the rules), you can create something a little more interesting. This version is only two bytes longer, at 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 $ - $$
Name this version asr
, for "a self-replicator": nasm -f bin -o asr asr.asm && chmod +x asr
Hex dump version for the nasm-impaired:
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
When you run it, it creates an almost-identical file named bsr
, but one that is itself executable. Running it will create another binary file named csr
. And so on.
(Note that annoying things start to happen after zsr
. I considered making a version that would cascade the name change to atr
and so on, but I think most people will get bored well before then, so it probably isn't worth all the extra bytes.)
-
\$\begingroup\$ +1 for assembly answer! Have you seen the assembly quine challenge? \$\endgroup\$MD XF– MD XF2017年05月25日 01:48:56 +00:00Commented May 25, 2017 at 1:48
Bash, 236
Longer than strictly necessary, but I hate long lines. The trailing newline is non-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 $$
-
\$\begingroup\$ Actually, it's not what I wanted, however, since I wrote a "wrong" question and your answer is a great quine... \$\endgroup\$JiminP– JiminP2011年09月27日 06:29:43 +00:00Commented Sep 27, 2011 at 6:29
-
\$\begingroup\$ @JiminP: How is it not what you wanted? I just read the problem description twice again, and fail to understand. \$\endgroup\$J B– J B2011年09月27日 20:54:22 +00:00Commented Sep 27, 2011 at 20:54
-
\$\begingroup\$ Well... what I wanted was an executable binary code. As I admitted above, since my question was not quite 'right'... sorry for that. \$\endgroup\$JiminP– JiminP2011年09月28日 00:16:06 +00:00Commented Sep 28, 2011 at 0:16
-
3\$\begingroup\$ @JiminP Well, yeah, the word "binary" doesn't appear at all in the question. I just found it in the comments, but for such a restriction, it just doesn't cut it. You could open a new question with all the consolidated input from the comments. I suggest you used the sandbox to ensure the regulars help you iron out the little details. But beware, binary answers tend to be real boring. \$\endgroup\$J B– J B2011年09月28日 04:37:03 +00:00Commented Sep 28, 2011 at 4:37
Here is a proof-of-concept (ungolfed) that shows how the Compilation services in .NET might be used to compile the source code on-the-fly to generate an identical output. The first copy is not identical to the original, but subsequent copies from subsequent runs are exactly identical with random file names:
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);
}
}
}
Demonstration output on command-line:
C:\projects\codegolf2947円2947円\bin\Debug>2947
Hello world!
C:\projects\codegolf2947円2947円\bin\Debug>dir
Volume in drive C has no label.
Volume Serial Number is 361D-4479
Directory of C:\projects\codegolf2947円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\codegolf2947円2947円\bin\Debug>8425
Hello world!
C:\projects\codegolf2947円2947円\bin\Debug>dir
Volume in drive C has no label.
Volume Serial Number is 361D-4479
Directory of C:\projects\codegolf2947円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\codegolf2947円2947円\bin\Debug>7538
Hello world!
C:\projects\codegolf2947円2947円\bin\Debug>dir
Volume in drive C has no label.
Volume Serial Number is 361D-4479
Directory of C:\projects\codegolf2947円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\codegolf2947円2947円\bin\Debug>
Batch
Version 1 (30 bytes)
type%0>%random%.bat&type%0>con
I win! :)
-
\$\begingroup\$ the %0 reference causes a read from the file, which violates the rules. Besides, my binary version is even shorter. :-) \$\endgroup\$peter ferrie– peter ferrie2017年11月26日 05:38:34 +00:00Commented Nov 26, 2017 at 5:38
DOS COM file - 50 bytes
Creates a file X.COM
where X
is replaced with the ones digit of the current time. COM files are simply loaded into memory at offset 100h
of the data segment (CS and DS are set to be the same) so we can simply write this memory out to a file.
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 source
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 $-$$
DOS .COM file, 29 bytes
The '@' is replaced randomly by an odd letter in the first half+ part of the alphabet (A, C, E, G, etc). Output files are either 255 or 256 bytes. Initial registers in real DOS (as opposed to a debugger) are that 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
DOS COM File - 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
Output file name is specified on the command line, truncated to 8.3 format, spaces OK (spaces in DOS filenames are legal). Tested using WinXP command prompt.