# >>>>>>>>>>>>> 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 FE 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 <<<<<<<<<<<<< # DMQ compiler (build executable in memory then write it) # ecx: 08048000 = Head # 2 * Head = ibuf # 4 * Head = obuf # 80000000 > seg # al: char (there are short instructions like CMP al, imm8) # ebx: acc # esi: input pointer (address in memory) # ebp: num chars available in ibuf # edi: output pointer (output file byte count) # edx: ediMax (edx is parameter count in syscall write) # INTENTION INSTRUCTION OPCODE NOTE # CopyHeader: 31 ED # ebp = 0 xor r/m32, r32 31 /r 11 101 101 31 D2 # edx = 0 xor r/m32, r32 31 /r 11 010 010 BE 00 80 04 08 # esi = Head mov r32, imm32 B8+rd id 8D 3C B2 # edi = 4*esi+edx lea r32, m 8D /r 00 111 100 10 110 010 8D 4A 54 # ecx = 54 (count) lea r32, m 8D /r 01 001 010 56 51 # push esi, ecx push r32 50+rd S: Head 54 F3 A4 # copy bytes rep movs m8, m8 F3 A4 5F 59 # edi = 54, ecx = Head pop r32 58+rd S: # NUMBER: 69 39 FA # cmp edx, edi cmp r/m32, r32 39 /r 11 111 010 0F 4C D7 # mov edx, edi if < cmovl r32, r/m32 0F 4C /r 11 010 111 BB 00 00 00 80 # ebx = 80000000 mov r32, imm32 B8+rd id # BYTE: 73 E8 47 00 00 00 # call GetByte 78 call rel32 E8 cd # Hash: 3C 23 # cmp al, '#' cmp al, imm8 3C ib 75 09 # jump WHSPACE if != 7C jne rel8 75 cb # Comment: 7C E8 3E 00 00 00 # call GetByte 81 call rel32 E8 cd 3C 0A # cmp al, '\n' cmp al, imm8 3C ib 75 F7 # jump Comment if != 85 jne rel8 75 cb # WHSPACE: 85 ASCII summary: \t\n #+-0:A 3C 20 # cmp al, ' ' cmp al, imm8 3C ib 7F 0A # jump COLON if > 89 jg rel8 7F cb 85 DB # cmp ebx, 0 test r/m32, r32 85 /r 11 011 011 7C DC # jump NUMBER if < 8D jl rel8 7C cb 88 1C 8F # [4*ecx+edi] = bl mov r/m8, r8 88 /r 00 011 100 10 001 111 47 # edi++ inc r32 40+rd EB D6 # jump NUMBER 93 jmp rel8 EB cb # COLON: 93 3C 3A # cmp al, ':' cmp al, imm8 3C ib 75 04 # jump NUMERAL if != 97 jne rel8 75 cb 89 DF # edi = ebx mov r/m32, r32 89 /r 11 011 111 EB CE # jump NUMBER 9B jmp rel8 EB cb # NUMERAL: 9B 2C 30 # al -= '0' sub al, imm8 2C ib 7C 0D # jump PmBeg if < 9F jl rel8 7C cb 3C 0A # cmp al, A cmp al, imm8 3C ib 7C 02 # jump +2 if < jl rel8 7C cb 2C 07 # al -= 'A' - '0' - A 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 C7 # jump BYTE AC jmp rel8 EB cb # PmBeg: AC 83 C7 04 # edi += 4 add r/m32, imm8 83 /0 ib 11 000 111 3C FB # cmp al, '+' - '0' cmp al, imm8 3C ib 75 04 # jump Minus if != B3 jne rel8 75 cb # Plus: 01 CB # ebx += ecx (Head) add r/m32, r32 01 /r 11 001 011 EB 02 # jump PmEnd B7 jmp rel8 EB cb # Minus: B7 29 FB # ebx -= edi sub r/m32, r32 29 /r 11 111 011 # PmEnd: B9 89 5C 8F FC # [4*ecx+edi-4] = ebx mov r/m32, r32 89 /r 01 011 100 10 001 111 EB AA # jump NUMBER BF jmp rel8 EB cb # GetByte: BF 46 # esi++ inc r32 40+rd 4D # ebp-- dec r32 48+rd 7F 1B # jump Ret if > C3 jg rel8 7F cb 53 52 # push ebx, edx push r32 50+rd S: acc ediMax 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 D1 E1 # ecx <<= 1 (ibuf) shl r/m32, 1 D1 /4 11 100 001 89 CA # edx = ecx (count) mov r/m32, r32 89 /r 11 001 010 CD 80 # syscall int imm8 CD ib 85 C0 # cmp eax, 0 test r/m32, r32 85 /r 11 000 000 7C 24 # jump EXIT+1 if < D4 jl rel8 7C cb 5A # pop edx pop r32 58+rd S: acc 7E 0A # jump WRITE if <= D7 jle rel8 7E cb 5B # pop ebx pop r32 58+rd S: 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 D1 E9 # Ret: # ecx >>= 1 (Head) DE shr r/m32, 1 D1 /5 11 101 001 8A 06 # al = [esi] mov r8, r/m8 8A /r 00 000 110 C3 # return ret C3 # WRITE: E1 D1 E1 # ecx <<= 1 (obuf) shl r/m32, 1 D1 /4 11 100 001 89 51 44 # [ecx+44] = edx (cnt) mov r/m32, r32 89 /r 01 010 001 43 # ebx = 1 (stdout) inc r32 40+rd # Flush: # E7 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 08 # jump EXIT+1 if < F0 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 > F6 jg rel8 7F cb 4B 4B # ebx = -1 dec r32 48+rd # EXIT+1: # F8 43 # ebx++ inc r32 40+rd 31 C0 40 # eax = 1 (exit) xor r/m32, r32; inc 31 /r 11 000 000 CD 80 # syscall FE int imm8 CD ib