Il kernel di Linux può caricare diversi formati binari:ELF è solo il più comune, sebbene anche il formato a.out sia abbastanza noto.
I formati binari supportati sono controllati da quali moduli binfmt vengono caricati o compilati nel kernel (si trovano nella sezione Filesystem della configurazione del kernel). C'è un binfmt_flat
per i binari in formato flat BFLT di uClinux che sono piuttosto minimi - possono anche essere compressi con zlib che ti permetteranno di rendere il tuo binario ancora più piccolo, quindi questa potrebbe essere una buona scelta.
Non sembra che nasm supporti nativamente questo formato, ma è abbastanza facile aggiungere manualmente l'intestazione necessaria come descrive Jim Lewis per ELF. C'è una descrizione del formato qui.
C'è qualche motivo per cui non vuoi usare "-f elf" invece di "-f bin"?
Penso che Linux non eseguirà un binario che non sia in formato ELF. Non riesco a trovare uno strumento che converta i binari piatti in ELF, ma puoi imbrogliare inserendo le informazioni ELF in foo.asm, usando la tecnica descritta qui :
Possiamo guardare le specifiche ELF, e/usr/include/linux/elf.h, e gli eseguibili creati dagli strumenti standard, per capire come dovrebbe essere il nostro eseguibile ELF vuoto. Ma, se sei un tipo impaziente, puoi semplicemente usare quello che ti ho fornito qui:
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 $ - $$
Questa immagine contiene un'intestazione ELF, che identifica il file come eseguibile Intel 386, senza alcuna tabella di intestazione di sezione e una tabella di intestazione del programma contenente una voce. Detta voce indica al caricatore del programma di caricare l'intero file in memoria (è un comportamento normale per un programma includere la sua intestazione ELF e la tabella di intestazione del programma nella sua immagine di memoria) a partire dall'indirizzo di memoria 0x08048000 (che è l'indirizzo predefinito per gli eseguibili da caricare) e per iniziare l'esecuzione il codice in _start, che appare subito dopo la tabella dell'intestazione del programma. Nessun segmento .data, nessun segmento.bss, nessun commento — nient'altro che lo stretto necessario.
Quindi, aggiungiamo il nostro programmino:
; tiny.asm org 0x08048000 ; ; (as above) ; _start: mov bl, 42 xor eax, eax inc eax int 0x80 filesize equ $ - $$
e provalo:
$ nasm -f bin -o a.out tiny.asm $ chmod +x a.out $ ./a.out ; echo $? 42