Assemblage pour x86 Linux, 106 octets
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 $ - $$
C'est pour l'assembleur nasm. Construisez le binaire avec la ligne de commande:nasm -f bin -o a.out selfrep.asm && chmod +x a.out
Voici le même fichier qu'un vidage hexadécimal: 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
Comme demandé, le programme se copie dans un fichier séparé. (Le programme aurait pu être considérablement plus court s'il avait été autorisé à simplement écrire sur stdout et à laisser l'utilisateur rediriger vers un fichier.)
J'ai évité d'utiliser des astuces limites pour réduire la taille. Il doit s'agir d'un binaire ELF 32 bits entièrement conforme.
Modifié pour ajouter : dans la version ci-dessus, le fichier créé est juste un fichier ordinaire, mais il me semble que pour quelques octets (et un petit pli des règles), vous pouvez créer quelque chose d'un peu plus intéressant. Cette version ne fait que deux octets de plus, à 108 octets:
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 $ - $$
Nommez cette version asr
, pour "un auto-réplicateur":nasm -f bin -o asr asr.asm && chmod +x asr
Version de vidage hexadécimal pour les nasm-altérés:
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
Lorsque vous l'exécutez, il crée un fichier presque identique nommé bsr
, mais qui est lui-même exécutable. L'exécuter créera un autre fichier binaire nommé csr
. Etc.
(Notez que des choses ennuyeuses commencent à se produire après zsr
. J'ai envisagé de créer une version qui répercuterait le changement de nom sur atr
et ainsi de suite, mais je pense que la plupart des gens s'ennuieront bien avant cela, donc cela ne vaut probablement pas tous les octets supplémentaires. )