# >>>>>>>>>>>>> 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

54 00 00 00     # 3C p_offset: file offset where segment begins
54 80 04 08     # 40 p_vaddr: virtual address of segment in memory (x86: 08048054)
00 00 00 00     # 44 p_paddr: physical address of segment, unspecified by 386 supplement
92 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 SEGMENT <<<<<<<<<<<<<

# String instructions, functions, buffered I/O
# 08048000 Head
# 08048100 ibuf
# 08048200 obuf
                # INTENTION             INSTRUCTION         OPCODE          NOTE
# Init:                              54
31 ED           # ebp = 0 (# bytes in)  xor r/m32, r32      31 /r           11 101 101
# Line:                              56
B0 2E           # al = '.'              mov r8, imm8        B0+rb ib
B9 20 00 00 00  # ecx = 20              mov r32, imm32      B8+rd id
BF 00 82 04 08  # edi = obuf            mov r32, imm32      B8+rd id
F3 AA           # write many            rep stos m8         F3 AA       Fill al @edi (ecx)
83 EF 20        # edi -= 20             sub r/m32, imm8     83 /5 ib        11 101 111
E8 3C 00 00 00  # call Word          6C call rel32          E8 cd
BF 20 82 04 08  # edi = obuf + 20       mov r32, imm32      B8+rd id
E8 32 00 00 00  # call Word          76 call rel32          E8 cd
B8 20 82 04 08  # eax = obuf + 20       mov r32, imm32      B8+rd id
89 C1           # ecx = obuf + 20       mov r/m32, r32      89 /r           11 000 001
29 CF           # edi -= ecx            sub r/m32, r32      29 /r           11 001 111
87 CF           # swap edi, ecx         xchg r/m32, r32     87 /r           11 001 111
29 CF           # edi -= ecx            sub r/m32, r32      29 /r           11 001 111
96              # swap eax, esi         xchg eax, r32       90+rd
F3 A4           # copy                  rep movs m8, m8     F3 A4       esi -> edi (ecx)
96              # swap eax, esi         xchg eax, r32       90+rd
C6 07 0A        # [edi] = '\n'          mov r/m8, imm8      C6 /0 ib        00 000 111
B9 00 82 04 08  # ecx = obuf (buf)      mov r32, imm8       B8+rd id
BA 21 00 00 00  # edx = 21 (count)      mov r32, imm32      B8+rd id
31 DB 43        # ebx = 1 (stdout)      xor r/m32, r32; inc 31 /r           11 011 011
# Flush:        #                    97
6B C3 04        # eax = 4 (write)   imul r32, r/m32, imm8   6B /r ib        11 000 011
CD 80           # syscall               int imm8            CD ib
85 C0           # cmp eax, 0            test r/m32, r32     85 /r           11 000 000
7C 40           # jump Error if <    A0 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
7F F1           # jump Flush if >    A6 jg rel8             7F cb   
EB AE           # jump Line          A8 jmp rel8            EB cb

# Word:         #                    A8
E8 11 00 00 00  # call GetByte       AD call rel32          E8 cd
80 3E 20        # cmp [esi], 20         cmp r/m8, imm8      80 /7 ib        00 111 110
7E F6           # jump Word if <=    B2 jle rel8            7E cb
# NonSpace:     #                    B2 [edi] <- word @esi (word ends in whitespace)
A4              # [edi++] = [esi++]     movs m8, m8         A4
E8 07 00 00 00  # call GetByte1      B8 call rel32          E8 cd
80 3E 20        # cmp [esi], 20         cmp r/m8, imm8      80 /7 ib        00 111 110
7F F5           # jump NonSpace if > BD jg rel8             7F cb
C3              # return                ret                 C3

# GetByte:      #                    BE
46              # esi++                 inc r32             40+rd
# GetByte1:     #                    BF
4D              # ebp--                 dec r32             48+rd
7F 1D           # jump Ret if >      C2 jg rel8             7F cb
B8 03 00 00 00  # eax = 3 (read)        mov r32, imm32      B8+rb ib
31 DB           # ebx = 0 (stdin)       xor r/m32, r32      31 /r           11 011 011
B9 00 81 04 08  # ecx = ibuf            mov r32, imm32      B8+rd id
BA 01 00 00 00  # edx = count           mov r32, imm32      B8+rd id
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 <    D9 jl rel8             7C cb
7E 06           # jump Exit if <=    DB jle rel8            7E cb
89 CE           # esi = ecx             mov r/m32, r32      89 /r           11 001 110
89 C5           # ebp = eax          DF mov r/m32, r32      89 /r           11 000 101
C3              # return                ret                 C3

# Error:        #                    E0
43              # ebx++                 inc r32             40+rd
# Exit:         # ebx: status        E1
31 C0 40        # eax = 1 (exit)        xor r/m32, r32; inc 31 /r           11 000 000
CD 80           # syscall            E6 int imm8            CD ib