# >>>>>>>>>>>>> ELF FILE HEADER <<<<<<<<<<<<<
                # All numbers (except in names) are in base sixteen (hexadecimal)
                # 00 <- number of bytes listed so far
7F 45 4C 46     # 04 e_ident[EI_MAG]: ELF magic number
01              # 05 e_ident[EI_CLASS]: 1: 32-bit, 2: 64-bit
   01           # 06 e_ident[EI_DATA]: 1: little-endian, 2: big-endian
      01        # 07 e_ident[EI_VERSION]: ELF header version; must be 1
         00     # 08 e_ident[EI_OSABI]: Target OS ABI; should be 0

00              # 09 e_ident[EI_ABIVERSION]: ABI version; 0 is ok for Linux
   00 00 00     # 0C e_ident[EI_PAD]: unused, should be 0
00 00 00 00     # 10

02 00           # 12 e_type: object file type; 2: executable
      03 00     # 14 e_machine: instruction set architecture; 3: x86, 3E: amd64
01 00 00 00     # 18 e_version: ELF identification version; must be 1

54 80 04 08     # 1C e_entry: memory address of entry point (where process starts)
34 00 00 00     # 20 e_phoff: file offset where program headers begin

00 00 00 00     # 24 e_shoff: file offset where section headers begin
00 00 00 00     # 28 e_flags: 0 for x86

34 00           # 2A e_ehsize: size of this header (34: 32-bit, 40: 64-bit)
      20 00     # 2C e_phentsize: size of each program header (20: 32-bit, 38: 64-bit)
01 00           # 2E e_phnum: #program headers
      28 00     # 30 e_shentsize: size of each section header (28: 32-bit, 40: 64-bit)

00 00           # 32 e_shnum: #section headers
      00 00     # 34 e_shstrndx: index of section header containing section names

# >>>>>>>>>>>>> ELF PROGRAM HEADER <<<<<<<<<<<<<

01 00 00 00     # 38 p_type: segment type; 1: loadable

00 00 00 00     # 3C p_offset: file offset where segment begins
00 80 04 08     # 40 p_vaddr: virtual address of segment in memory (x86: 08048000)
00 00 00 00     # 44 p_paddr: physical address of segment, unspecified by 386 supplement
94 00 00 00     # 48 p_filesz: size in bytes of the segment in the file image ############

00 80 FB 77     # 4C p_memsz: size in bytes of the segment in memory; p_filesz <= p_memsz
07 00 00 00     # 50 p_flags: segment-dependent flags (1: X, 2: W, 4: R)

00 10 00 00     # 54 p_align: 1000 for x86

# >>>>>>>>>>>>> PROGRAM <<<<<<<<<<<<<
# 08048000 Head (> Stack; see ABI supplement 386)
# 08048100 obuf
# "HELMO\n":    48 45 4C 4D 4F 0A
                # INTENTION             INSTRUCTION     OPCODE      ModR/M      SIB
C6 05 00 81 04 08 48 # [...] = 'H'      mov r/m8, imm8  C6 /0 ib    00 000 101
BF 02 81 04 08  # edi = obuf+2          mov r32, imm32  B8+rd id
C6 07 4C        # [edi] = 'L'           mov r/m8, imm8  C6 /0 ib    00 000 111
C6 47 01 4D     # [edi+1] = 'M'         mov r/m8, imm8  C6 /0 ib    01 000 111
C6 47 FF 45     # [edi-1] = 'E'         mov r/m8, imm8  C6 /0 ib    01 000 111
BB 01 00 00 00  # ebx = 1               mov r32, imm32  B8+rd id
C6 04 5F 4F     # [2*ebx+edi] = 'O'     mov r/m8, imm8  C6 /0 ib    00 000 100  01 011 111
C6 44 5F 01 0A  # [2*ebx+edi+1] = '\n'  mov r/m8, imm8  C6 /0 ib    01 000 100  01 011 111
# Write:        #                    79
8D 4F FE        # ecx = edi-2 (obuf)    lea r32, m      8D /r       01 001 111
8D 53 05        # edx = ebx+5 (6 count) lea r32, m      8D /r       01 010 011
# Flush:        #                    7F
8D 43 03        # eax = ebx+3 (4 write) lea r32, m      8D /r       01 000 011
CD 80           # syscall               int imm8        CD ib
85 C0           # cmp eax, 0            test r/m32, r32 85 /r       11 000 000
7C 07           # jump Error if <    88 jl rel8         7C cb
01 C1           # ecx += eax            add r/m32, r32  01 /r       11 000 001
29 C2           # edx -= eax            sub r/m32, r32  29 /r       11 000 010
75 F1           # jump Flush if !=   8E jne rel8        75 cb
# Exit:         #
4B              # ebx--                 dec r32         48+rd
# Error:        #                    8F
31 C0 40        # eax = 1 (exit)        xor r/m32, r32  31 /r       11 000 000
CD 80           # syscall            94 int imm8            CD ib