;; scarf.asm -- a tiny ELF that prints out the word scarf and cleanly exits ;; Offset each line is in final executable is written at end of line in curly braces ;; To build: ;; > nasm -f bin -o scarf scarf.asm BITS 32 org 0x80000000 ehdr: db 0x7F, "ELF" ; e_ident[0-3] offset: {0-3} _start: mov cl, 0x41 ; mov %ecx, address takes 5 bytes but I'll do it in 4 by writing 0x41 to register and ror so its value becomes 0x80000020, the offset to the string -- e_ident[4-5] (file class, data encoding) {4-5} ror ecx, 1 ; e_ident[6-7] (file version, start of padding) {6-7} mov al, 0x4 ; e_ident[8-9] (padding) {8-9} mov dl, 0x6 ; e_ident[10-11] (padding) {0xa-0xb} int 0x80 ; e_ident[12-13] (padding) {0xc-0xd} mov eax, esp ; put a value into eax that is a valid pointer -- e_ident[14-15] (padding) {0xe-0xf} dw 2 ; will be interpreted as add al, [eax] -- e_type[0-1] {0x10-0x11} dw 3 ; will be interpreted as add eax, [eax] -- e_machine[0-1] {0x12-0x13} xchg eax,ebx ; makes eax equal to 0, ebx seems to be 0x0 at this point -- e_version[0] {0x14} inc eax ; makes eax equal to 1 -- e_version[1] {0x15} int 0x80 ; exit system call -- e_version[3-4] {0x16-0x17} dd _start ; e_entry[0-3] {0x18-0x1b} dd phdr - $$ ; e_phoff[0-3] {0x1c-0x1f} msg: db "scarf", 0xa, 0x0, 0x0 ; e_shoff[0-3], e_flags[0-4] (e_shnum is 0 so e_shoff is ignored) {0x20-0x27} dw ehdrsize ; e_ehsize[0-1] {0x28-0x29} dw phdrsize ; e_phentsize[0-1] {0x2a-0x2b} phdr: dd 1 ; e_phnum[0-1] ; p_type[0-3] {0x2c-0x2d} ; e_shentsize[0-1] {0x2e-0x2f} dd 0 ; e_shnum[0-1] ; p_offset[0-3] {0x30-0x31} ; e_shstrndx[0-1] {0x32-0x33} ehdrsize equ $ - ehdr ; assembler directive (0 bytes in executable) dd $$ ; p_vaddr[0-3] {0x34-0x37} dd $$ ; p_paddr[0-3] {0x38-0x3b} dd filesize ; p_filesz[0-3] {0x3c-0x3f} dd filesize ; p_memsz[0-3] {0x40-0x43} dd 5 ; p_flags[0-3] {0x44-0x47} dd 0x1000 ; p_align[0-3] {0x48-0x4b} phdrsize equ $ - phdr ; assembler directive (0 bytes in executable) filesize equ $ - $$ ; assembler directive (0 bytes in executable)