Write a self-replicating program.
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.)
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 $$
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\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>