Linuxové jádro může načíst několik různých binárních formátů – ELF je jen nejběžnější, ačkoli formát a.out je také docela dobře známý.
Podporované binární formáty jsou řízeny tím, které moduly binfmt se načítají nebo kompilují do jádra (jsou v části Souborový systém v konfiguraci jádra). Je tam binfmt_flat
pro uClinux BFLT binární soubory v plochém formátu, které jsou docela minimální - mohou být dokonce komprimovány zlib, což vám umožní udělat váš binární soubor ještě menší, takže by to mohla být dobrá volba.
Nezdá se, že by nasm tento formát nativně podporoval, ale je docela snadné přidat potřebné záhlaví ručně, jak popisuje Jim Lewis pro ELF. Zde je popis formátu.
Existuje nějaký důvod, proč nechcete používat "-f elf" místo "-f bin"?
Myslím, že Linux nespustí binární soubor, který není ve formátu ELF. Nemohu najít nástroj, který by konvertoval ploché binární soubory na ELF, ale můžete podvádět vložením informací ELF do foo.asm pomocí techniky popsané zde:
Můžeme se podívat na specifikaci ELF a/usr/include/linux/elf.h a spustitelné soubory vytvořené standardními nástroji, abychom zjistili, jak by měl náš spustitelný soubor emptyELF vypadat. Ale pokud jste netrpělivý typ, můžete použít ten, který jsem zde uvedl:
BITS 32 org 0x08048000 ehdr: ; Elf32_Ehdr db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident times 8 db 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 ehdrsize ; e_ehsize dw phdrsize ; e_phentsize dw 1 ; e_phnum dw 0 ; e_shentsize dw 0 ; e_shnum dw 0 ; e_shstrndx ehdrsize equ $ - ehdr phdr: ; Elf32_Phdr dd 1 ; p_type dd 0 ; p_offset dd $$ ; p_vaddr dd $$ ; p_paddr dd filesize ; p_filesz dd filesize ; p_memsz dd 5 ; p_flags dd 0x1000 ; p_align phdrsize equ $ - phdr _start: ; your program here filesize equ $ - $$
Tento obrázek obsahuje hlavičku ELF, která identifikuje soubor jako spustitelný soubor Intel 386, bez tabulky hlaviček sekce a tabulky hlavičky programu obsahující jednu položku. Uvedená položka dává zavaděči programu pokyn, aby načetl celý soubor do paměti (je to normální chování programu, když do obrazu paměti zahrne záhlaví ELF a tabulku záhlaví programu), počínaje adresou paměti 0x08048000 (což je výchozí adresa pro načítání spustitelných souborů) a zahájit provádění kód na _start, který se objeví hned za tabulkou programheader. Žádný segment .data, segment no.bss, žádný komentář – nic než to nejnutnější.
Přidejme tedy náš malý program:
; tiny.asm org 0x08048000 ; ; (as above) ; _start: mov bl, 42 xor eax, eax inc eax int 0x80 filesize equ $ - $$
a vyzkoušejte to:
$ nasm -f bin -o a.out tiny.asm $ chmod +x a.out $ ./a.out ; echo $? 42