Author: Yuval Yarom (yval@memco.co.il)
Notes: The attached quine program is a self reproducing Sparc
executable. I have tested it under Solaris 2.4 and Solaris
2.6. I do
not know if it works on anything else. The output is the
contents of
the executable file. The program simply dumps its memory
image to the standard output. To
create it, I compiled the following foo.c to assembler, tweaked
with the
assembly code a bit (inlining calls to syscall, deleting unneeded
stuff,
etc.), compiled the assembly code, and loaded it (use 'ld foo.o
-dn -a
-e main'). After running ld, a.out contans too much data.
The first
run of such a.out produces quine.
Ed. note: I would classify this as a cheat, but it's a unique
idea.
#include <sys/syscall.h>
int end();
main() {
char *a = (char *)(((long)main)
& ~0xfff);
while (a < (char *)end)
syscall(SYS_write,1, a++, 1);
syscall(SYS_exit, 0);
}
end(){}
The executable
Another smaller executable
Language: Assembler (in fact, machine code)
Author: Bertram Felgenhauer
Note: These programs print their own binary
to stdout, reconstructed
from memory.
MS DOS specific.
===START===
.model tiny
.code
.startup
s: mov ah,40h
inc
bx
mov
cl,offset x-offset s
mov
dx,si
int
21h
ret
x:
end
====END====
begin 644 SELF.COM
*M$!#L0J+ULTAPP
end
Description: COM files are just too simple - memory images of themselves.
So we just write it to standard output. Assumes bx=0, ch=0,
si=0100
on startup (true for MS DOS)
===START===
; self-rep EXE file, boot strap.
; exe -> 75 bytes.
.model small
.code
& equ
offset
; our own EXE header, quite minimalistic
db
"MZ" ; 00 signature
dw
& e+32 ; 02 last 512-page
dw
1 ; 04 number of 512-pages
dw
0 ; 06 number of relocation entries
dw
2 ; 08 header size in paragraphs
dw
32 ; 0A min number of paragraphs in memory
dw
32 ; 0C max
dw
4 ; 0E initial SS
dw
512 ; 10 initial SP
dw
0 ; 12 checksum
dw
offset start
; 14 initial IP
dw
0 ; 16 initial CS
; 18 offset of relocation table
; 1A overlay number
; our main program; part of it is used as the header, too
start: push cs
pop
ds
inc
bx
mov
cl,20h
@l: mov ah,40h
cwd
int
21h ; 1st: write header; 2nd: write code segment
xor
cl,0Bh ; (offset e) xor 32; must have odd parity
jpe
@l
mov
ah,4Ch
int
21h ; exit program
e:
.stack 256
end start
====END====
begin 644 SELF.EXE
M35I+ $ " " ( $
" 8 #A]#L2"T0)E-6DL 0
( ( @
> 0 ( !@ .'T.Q(+1 F<TA@/$+>O:T3,TA
end