внутри elf-файла находится просто море пустоты
Нашему взору представиться одна вода, то есть нули, "заботливо" вставленные тупым линкером. А что если… отказаться от услуг линкера и попробовать соорудить elf-файл голыми руками? Для этого, нам во-первых, потребуется подробное описание всех служебных структур elf'а (последний draft лежит здесь http://www.caldera.com/developers/gabi/), а, во-вторых, транслятор, умеющий генерировать двоичные файлы, например, NASM, входящий в большинство Linux-дистрибутивов, но к, сожалению, не в BSD. Во всяком случае, его всегда можно скачать с "родной" страницы проекта: http://nasm.sourceforge.net/.
Исполняемый elf-файл нуждается в двух структурах: elf-header'e, описывающим основные параметры файла (платформа, адрес точки входа и т. д.) и program header table, перечисляющего все сегменты. Как минимум должен быть один сегмент с правами на чтение, запись и исполнение. Наконец, чтобы elf заработал, требуется добавить "боевую начинку", то есть непосредственно сам ассемблерный код. Минимальный адрес, с которого в UNIX-системах может загружаться elf, равен 8048000h, поэтому нам понадобится директива ORG, задающая начальное смещение в файле.
Остается только изучить документацию и заполнить все служебные структуры соответствующим образом:
BITS 32
org 8048000h
ehdr: ; // Elf32_Ehdr
db 7Fh, "ELF", 1, 1, 1 ; // e_ident
times 9 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