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

82 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
15 01 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 <<<<<<<<<<<<<

#### LIBRARY ####
                # INTENTION             INSTRUCTION         OPCODE          NOTE
# PutOut:       # ECX=obuf EDX=count 54 -- <0:err =0:ok EAX=stat ECX=? EDX=? EBX=1
31 DB 43        # ebx = 1 (stdout)      xor r/m32, r32; inc 31 /r           11 011 011
# .flush:       #                    57
8D 43 03        # eax = ebx + 3 (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 06           # jump .ret if <     60 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 >   66 jg rel8             7F cb
# .ret:                              66
C3              # return                ret                 C3

# To use input, reserve ESI and EBP. Set EBP=0 before first use. Byte -> [ESI], each call.
# TakeIn:       # ECX=ibuf EDX=count 67 -- <0:err =0:done >0:ok EAX=? EBX=0(if err)
46              # esi++                 inc r32             40+rd
4D              # ebp--                 dec r32             48+rd
7F 0D           # jump .ret if >     6B jg rel8             7F cb
31 DB           # ebx = 0 (stdin)       xor r/m32, r32      31 /r           11 011 011
8D 43 03        # eax = 3 (read)        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
89 CE           # esi = ecx             mov r/m32, r32      89 /r           11 001 110
89 C5           # ebp = eax             mov r/m32, r32      89 /r           11 000 101
# .ret:                              78
C3              # return                ret                 C3

# Exit-1:                            79
4B              # ebx--                 dec r32             48+rd
# Exit:         # EBX=stat --        7A
31 C0 40        # eax = 1 (exit)        xor r/m32, r32; inc 31 /r           11 000 000
CD 80           # syscall               int imm8            CD ib
# Exit+1:                            7F
43              # ebx++                 inc r32             40+rd
EB F8           # jump Exit          82 jmp rel8            EB cb

#      08048000 = Head
# ecx: 20000000 = ibuf = ilen
#      40000000 = obuf = olen
#      80000000 > seg
#  al: char
# ebx: acc
# ebp: num chars available in ibuf
# esi: input pointer (address in memory)
# edi: output pointer (file pos from 0)

#### COMPILER ###

# CopyHeader:   #                    82 <-- Entry point for this and compiled programs
31 ED           # ebp = 0               xor r/m32, r32      31 /r           11 101 101
31 C9           # ecx = 0               xor r/m32, r32      31 /r           11 001 001
B1 82           # ecx = len (header)    mov r8, imm8        B0+rb ib
BE 00 80 04 08  # esi = Head            mov r32, imm32      B8+rd id
BF 00 00 00 20  # edi = ibuf            mov r32, imm32      B8+rd id
51 57           # push ecx, edi         push r32            50+rd       S: len ibuf
01 FF           # edi = obuf (=edi+edi) add r/m32, r32      01 /r           11 111 111
F3 A4           # copy string           rep movs m8, m8     F3 A4
59 5F           # ecx = ibuf, edi = len pop r32             58+rd       S:
EB 24           # jump Record        9C jmp rel8            EB cb

# GetByte:      # ECX=ibuf --        9C
53              # push ebx              push r32            50+rd       S: acc
89 CA           # edx = ecx             mov r/m32, r32      89 /r           11 001 010
E8 C3 FF FF FF  # call TakeIn        A4 call rel32          E8 cb
7C D3           # jump Exit+1 if <   A6 jl rel8             7C cb
5B              # pop ebx               pop r32             58+rd       S:
7E 03           # jump Finish if <=  A9 jle rel8            7E cb
8A 06           # al = [esi]            mov r8, r/m8        8A /r           00 000 110
C3              # return                ret                 C3

# Finish:       # ECX=ibuf           AC
01 C9           # ecx = obuf (=ecx+ecx) add r/m32, r32      01 /r           11 001 001
8B 51 44        # edx = [ecx+44]        mov r32, r/m32      8B /r           01 010 001
E8 9E FF FF FF  # call PutOut        B6 call rel32          E8 cb
7C C7           # jump Exit+1 if <   B8 jl rel8             7C cb
EB BF           # jump Exit-1        BA jmp rel8            EB cb

# WORD:                              BA
39 7C 09 44     # cmp [2*ecx+44], edi   cmp r/m32, r32      39 /r   01 111 100  00 001 001
7D 04           # jump Clear if >=   C0 jge rel8            7D cb
# Record:                            C0
89 7C 09 44     # [2*ecx+44] = edi      mov r/m32, r32      89 /r   01 111 100  00 001 001
# Clear:        # null: 80000000     C4 
6B D9 04        # ebx = ecx * 4     imul r32, r/m32, imm8   6B /r ib        11 011 001

# CHAR:                              C7
E8 D0 FF FF FF  # call GetByte       CC call rel32          E8 cd

# Hash:
3C 23           # cmp al, '#'           cmp al, imm8        3C ib
7C 0B           # jump WhSpace if <  D0 jl rel8             7C cb
7F 13           # jump Op if >       D2 jg rel8             7F cb
# Comment:                           D2
E8 C5 FF FF FF  # call GetByte       D7 call rel32          E8 cd
3C 0A           # cmp al, '\n'          cmp al, imm8        3C ib
75 F7           # jump Comment if != DB jne rel8            75 cb
# WhSpace:                           DB
85 DB           # cmp ebx, 0            test r/m32, r32     85 /r           11 011 011
7C DB           # jump WORD if <     DF jl rel8             7C cb
88 1C 4F        # [2*ecx+edi] = bl      mov r/m8, r8        88 /r   00 011 100  01 001 111
47              # edi++                 inc r32             40+rd
EB D5           # jump WORD          E5 jmp rel8            EB cb

# Op:                                E5             ASCII summary: \t\n #+-0:A
3C 2D           # cmp al, '-'           cmp al, imm8        3C ib
74 25           # jump Minus if ==   E9 je rel8             74 cb
7C 15           # jump Plus if <     EB jl rel8             7C cb
3C 3A           # cmp al, ':'
74 0D           # jump Colon if ==   EF je rel8             74 cb
7C 02           # jump Digit if <    F1 jl rel8             7C cb
# Letter:
2C 07           # al -= 'A'-'0'-A       sub al, imm8        2C ib
# Digit:                             F3
2C 30           # al -= '0'             sub al, imm8        2C ib
C1 E3 04        # ebx <<= 4             shl r/m32, imm8     C1 /4 ib        11 100 011
00 C3           # bl += al              add r/m8, r8        00 /r           11 000 011
EB CB           # jump CHAR          FC jmp rel8            EB cb

# Colon:                             FC
89 DF           # edi = ebx             mov r/m32, r32      89 /r           11 011 111
EB BA           # jump WORD         100 jmp rel8            EB cb

# Plus:                             100
81 C3 00 80 04 08   # ebx += Head       add r/m32, imm32    81 /0 id        11 000 011
# Append:                           106
89 1C 4F        # [2*ecx+edi] = ebx     mov r/m32, r32      89 /r   00 011 100  01 001 111
83 C7 04        # edi += 4              add r/m32, imm8     83 /0 ib        11 000 111
EB AC           # jump WORD         10E jmp rel8            EB cb

# Minus:                            10E
83 EB 04        # ebx -= 4              sub r/m32, imm8     83 /5 ib        11 101 011
29 FB           # ebx -= edi            sub r/m32, r32      29 /r           11 111 011
EB F1           # jump Append       115 jmp rel8            EB cb