The smallest self-replicating program I found in a bunch of languages.
fn main(){print!("{}",include_str!(file!()))}file!(): This is a builtin macro that yields the path of the current source file as a string literal at compile time.
include_str!(...): This macro takes a file path (known at compile time) and injects the file contents as a &'static str into the compiled binary. So include_str!(file!()) becomes a string containing the full source code of the program itself. I don't consider this cheating since no external file is involved and this is a rust-ism.
print!("{}", ...): Finally it prints that string to stdout, emitting its own source code.
Putting it all together: The compiled program contains its own source code as a baked-in string and outputs it when run. In computer folklore, this creature is called a quine. The Rust ecosystem makes it surprisingly straightforward by giving it compile-time introspection tools.
Crash-after-write variant (15 bytes of .text):
bits 64
section .text
global _start
_start:
push 1
pop rdi
mov eax, edi
mov esi, _start
push byte end - _start
pop rdx
syscall
end:Clean exit variant (21 bytes of .text):
bits 64
section .text
global _start
_start:
push 1
pop rdi
mov eax, edi
mov esi, _start
push byte end - _start
pop rdx
syscall
xor edi, edi
mov al, 60
syscall
end:rdx = end - _start computes the size (in bytes) of the whole program in memory, rsi = _start points to the beginning of its own code, and write(1, _start, end - _start) uses the write syscall to dump its own bytes to stdout. The top version omits exit(0) so it falls through into padding after the write and typically crashes (15 bytes of .text). The clean-exit variant adds 6 bytes for exit(0). Both versions use mov esi, _start (non-PIE absolute) and push byte end - _start (8-bit length), so they assume size < 128 bytes.
So when you assemble and run it:
nasm -felf64 q.asm -o q.o
ld q.o -o q
./q > dump
hexdump -C q
hexdump -C dump # identical to above
dump will contain exactly the same bytes as the executable’s text segment.
Again, some say that considering the bytecode size of the program is cheating. I don't think so since I could have written the bytecode by hand anyways with enough determination from the assembly I wrote. If you think this is cheating, I challenge you to do better.
I can’t prove these are the absolute smallest possible 64-bit NASM or rust quine/self-replicator, but hit me up if you've found better with no data section (for asm) or no dependencies for rust.