# >>>>>>>>>>>>> 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
44 00 00 00     # 48 p_filesz: size in bytes of the segment in the file image ############

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

# Difference of two integers

                # INTENTION             INSTRUCTION         OPCODE          NOTE
B8 6C 00 00 00  # eax <- imm            mov r32, imm32      B8+rd id
2D 54 00 00 00  # eax <- eax - imm      sub eax, imm32      2D id
B9 00 00 00 09  # ecx <- obuf           mov r32, imm32      B8+rd id
BB 02 00 00 00  # ebx <- 2^4 (hex)      mov r32, imm32      B8+rd id
                # Write the numerals (base EBX) of number EAX into memory just before ECX.
                # Let ECX0 denote the value of ECX before the routine, and ECX1 after.
                # After the routine, EDI is the len of the string, and ECX0 = ECX1 + EDI.
31 FF           # edi <- 0 (count)      xor r/m32, r32      31 /r           11 111 111
# 6A Numeral:   # div r/m32: Unsigned divide EDX:EAX by r/m32, EAX = quot, EDX = rem
31 D2           # edx <- 0              xor r/m32, r32      31 /r           11 010 010
F7 F3           # divide by ebx         div r/m32           F7 /6           11 110 011
80 FA 09        # cmp dl, 9             cmp r/m8, imm8      80 /7 ib        11 111 010
7E 03           # jle over next inst    jle rel8            7E cb
80 C2 07        # dl += 'A' - A - '0'   add r/m8, imm8      80 /0 ib        11 000 010
80 C2 30        # dl += '0'             add r/m8, imm8      80 /0 ib        11 000 010
49              # ecx--                 dec r32             48+rd
47              # edi++                 inc r32             40+rd
88 11           # [ecx] <- dl           mov r/m8, r8        88 /r           00 010 001
85 C0           # cmp eax, 0            test r/m32, r32     85 /r           11 000 000
75 E9           # jump Numeral if !=    jnz rel8            75 cb

# 81 Write:
B8 04 00 00 00  # eax <- 4 (write)      mov r32, imm32      B8+rd id
BB 01 00 00 00  # ebx <- 1 (stdout)     mov r32, imm32      B8+rd id
89 FA           # edx <- edi (count)    mov r/m32, r32      89 /r           11 111 010
CD 80           # syscall               int 80              CD ib

# 8F Exit:
B8 01 00 00 00  # eax <- 1 (exit)       mov r32, imm32      B8+rd id
31 DB           # ebx <- 0 (status)     xor r/m32, r32      31 /r           11 011 011
CD 80           # syscall               int 80              CD ib

# 98 obuf: