// File: /workspace/github_c_makefile_star2_O1/mikeakohn[P]print_pe/build/../src/optional_header.c
// Function: optional_header_print
int optional_header_print(struct optional_header_t *optional_header)
{
  int t;

  printf("---------------------------------------------\n");
  printf("Image Optional Header\n");
  printf("---------------------------------------------\n");

  const char *magic;

  switch (optional_header->Magic)
  {
    case 0x10b: magic = "PE32 32 Bit Exe"; break;
    case 0x20b: magic = "PE32+ 64 Bit Exe"; break;
    case 0x107: magic = "ROM"; break;
    default: magic = "Unknown"; break;
  }

  printf("             Magic: 0x%04x (%s)\n", optional_header->Magic, magic);

  printf("MajorLinkerVersion: %d\n", optional_header->MajorLinkerVersion);
  printf("MinorLinkerVersion: %d\n", optional_header->MinorLinkerVersion);
  printf("        SizeOfCode: %d\n", optional_header->SizeOfCode);
  printf("SizeOfInitilzdData: %d\n", optional_header->SizeOfInitializedData);
  printf("SizeOfUnintlzdData: %d\n", optional_header->SizeOfUninitializedData);
  printf("  AddrOfEntryPoint: %d\n", optional_header->AddressOfEntryPoint);
  printf("        BaseOfCode: %d\n", optional_header->BaseOfCode);
  printf("        BaseOfData: %d\n", optional_header->BaseOfData);
  printf("         ImageBase: 0x%" PRIx64 "\n", optional_header->ImageBase);
  printf("  SectionAlignment: %d\n", optional_header->SectionAlignment);
  printf("     FileAlignment: %d\n", optional_header->FileAlignment);
  printf("    MajorOSVersion: %d\n", optional_header->MajorOperatingSystemVersion);
  printf("    MinorOSVersion: %d\n", optional_header->MinorOperatingSystemVersion);
  printf(" MajorImageVersion: %d\n", optional_header->MajorImageVersion);
  printf(" MinorImageVersion: %d\n", optional_header->MinorImageVersion);
  printf(" MajorSubsystemVer: %d\n", optional_header->MajorSubsystemVersion);
  printf(" MinorSubsystemVer: %d\n", optional_header->MinorSubsystemVersion);
  printf("         Reserved1: %d\n", optional_header->Reserved1);
  printf("       SizeOfImage: %d\n", optional_header->SizeOfImage);
  printf("     SizeOfHeaders: %d\n", optional_header->SizeOfHeaders);
  printf("          CheckSum: %d\n", optional_header->CheckSum);

  const char *subsystem;

  switch (optional_header->Subsystem)
  {
    case 1: subsystem = "Native"; break;
    case 2: subsystem = "GUI"; break;
    case 3: subsystem = "Console"; break;
    case 5: subsystem = "OS2 GUI"; break;
    case 7: subsystem = "Posix Console"; break;
    case 9: subsystem = "Windows CE GUI"; break;
    case 10: subsystem = "EFI App"; break;
    case 11: subsystem = "EFI Boot Service Driver"; break;
    case 12: subsystem = "EFI Runtime Driver"; break;
    case 13: subsystem = "EFI ROM"; break;
    case 14: subsystem = "Xbox"; break;
    case 15: subsystem = "Windows Boot Application"; break;
    default: subsystem = "Unknown"; break;
  }

  printf("         Subsystem: %d (%s)\n", optional_header->Subsystem, subsystem);
  printf("DllCharacteristics: 0x%04x", optional_header->DllCharacteristics);

  if ((optional_header->DllCharacteristics & 1) != 0)
  {
    printf(" (Reserved_1)");
  }

  if ((optional_header->DllCharacteristics & 2) != 0)
  {
    printf(" (Reserved_2)");
  }

  if ((optional_header->DllCharacteristics & 4) != 0)
  {
    printf(" (Reserved_4)");
  }

  if ((optional_header->DllCharacteristics & 8) != 0)
  {
    printf(" (Reserved_8)");
  }

  if ((optional_header->DllCharacteristics & 0x40) != 0)
  {
    printf(" (Dyanamic Base)");
  }

  if ((optional_header->DllCharacteristics & 0x80) != 0)
  {
    printf(" (Force Integrity)");
  }

  if ((optional_header->DllCharacteristics & 0x100) != 0)
  {
    printf(" (NX Compatiblity)");
  }

  if ((optional_header->DllCharacteristics & 0x200) != 0)
  {
    printf(" (No Isolation)");
  }

  if ((optional_header->DllCharacteristics & 0x400) != 0)
  {
    printf(" (No Structure Exception Handling)");
  }

  if ((optional_header->DllCharacteristics & 0x800) != 0)
  {
    printf(" (No Bind)");
  }

  if ((optional_header->DllCharacteristics & 0x2000) != 0)
  {
    printf(" (WDM Driver)");
  }

  if ((optional_header->DllCharacteristics & 0x8000) != 0)
  {
    printf(" (Terminal Server Aware)");
  }

  printf("\n");

  printf("SizeOfStackReserve: %" PRId64 "\n", optional_header->SizeOfStackReserve);
  printf(" SizeOfStackCommit: %" PRId64 "\n", optional_header->SizeOfStackCommit);
  printf(" SizeOfHeapReserve: %" PRId64 "\n", optional_header->SizeOfHeapReserve);
  printf("  SizeOfHeapCommit: %" PRId64 "\n", optional_header->SizeOfHeapCommit);
  printf("       LoaderFlags: %d\n", optional_header->LoaderFlags);
  printf("  NumOfRvaAndSizes: %d\n", optional_header->NumberOfRvaAndSizes);
  printf("\n");

  if (optional_header->DataDirectoryCount != 0)
  {
    printf("   Directory Description             VirtualAddr  Size\n");

    for (t = 0; t < optional_header->DataDirectoryCount; t++)
    {
      const char *desc;

      if (t < sizeof(dir_entries) / sizeof(char *))
      {
        desc = dir_entries[t];
      }
        else
      {
        desc = "";
      }

      printf("%2d %-33s 0x%08x   0x%08x (%d)\n", t, desc,
        optional_header->directory_entry[t].virtual_address,
        optional_header->directory_entry[t].size,
        optional_header->directory_entry[t].size);
    }

    if (t != 0) { printf("\n"); }
  }

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
leaq 0x27e4(%rip), %r14      # 0x8241
movq %r14, %rdi
callq 0x3060
leaq 0x425b(%rip), %rdi      # 0x9cc7
callq 0x3060
movq %r14, %rdi
callq 0x3060
movzwl (%rbx), %esi
cmpl $0x107, %esi            # imm = 0x107
je 0x5aa6
cmpl $0x10b, %esi            # imm = 0x10B
je 0x5a9d
cmpl $0x20b, %esi            # imm = 0x20B
jne 0x5aaf
leaq 0x3dba(%rip), %rdx      # 0x9855
jmp 0x5ab6
leaq 0x3da1(%rip), %rdx      # 0x9845
jmp 0x5ab6
leaq 0x4038(%rip), %rdx      # 0x9ae5
jmp 0x5ab6
leaq 0x31ea(%rip), %rdx      # 0x8ca0
leaq 0x3da9(%rip), %rdi      # 0x9866
xorl %eax, %eax
callq 0x3090
movzbl 0x2(%rbx), %esi
leaq 0x3db8(%rip), %rdi      # 0x9887
xorl %eax, %eax
callq 0x3090
movzbl 0x3(%rbx), %esi
leaq 0x3dbe(%rip), %rdi      # 0x989f
xorl %eax, %eax
callq 0x3090
movl 0x4(%rbx), %esi
leaq 0x3dc5(%rip), %rdi      # 0x98b7
xorl %eax, %eax
callq 0x3090
movl 0x8(%rbx), %esi
leaq 0x3dcc(%rip), %rdi      # 0x98cf
xorl %eax, %eax
callq 0x3090
movl 0xc(%rbx), %esi
leaq 0x3dd3(%rip), %rdi      # 0x98e7
xorl %eax, %eax
callq 0x3090
movl 0x10(%rbx), %esi
leaq 0x3dda(%rip), %rdi      # 0x98ff
xorl %eax, %eax
callq 0x3090
movl 0x14(%rbx), %esi
leaq 0x3de1(%rip), %rdi      # 0x9917
xorl %eax, %eax
callq 0x3090
movl 0x18(%rbx), %esi
leaq 0x3de8(%rip), %rdi      # 0x992f
xorl %eax, %eax
callq 0x3090
movq 0x20(%rbx), %rsi
leaq 0x3dee(%rip), %rdi      # 0x9947
xorl %eax, %eax
callq 0x3090
movl 0x28(%rbx), %esi
leaq 0x3df8(%rip), %rdi      # 0x9962
xorl %eax, %eax
callq 0x3090
movl 0x2c(%rbx), %esi
leaq 0x3dff(%rip), %rdi      # 0x997a
xorl %eax, %eax
callq 0x3090
movzwl 0x30(%rbx), %esi
leaq 0x3e05(%rip), %rdi      # 0x9992
xorl %eax, %eax
callq 0x3090
movzwl 0x32(%rbx), %esi
leaq 0x3e0b(%rip), %rdi      # 0x99aa
xorl %eax, %eax
callq 0x3090
movzwl 0x34(%rbx), %esi
leaq 0x3e11(%rip), %rdi      # 0x99c2
xorl %eax, %eax
callq 0x3090
movzwl 0x36(%rbx), %esi
leaq 0x3e17(%rip), %rdi      # 0x99da
xorl %eax, %eax
callq 0x3090
movzwl 0x38(%rbx), %esi
leaq 0x3e1d(%rip), %rdi      # 0x99f2
xorl %eax, %eax
callq 0x3090
movzwl 0x3a(%rbx), %esi
leaq 0x3e23(%rip), %rdi      # 0x9a0a
xorl %eax, %eax
callq 0x3090
movl 0x3c(%rbx), %esi
leaq 0x3e2a(%rip), %rdi      # 0x9a22
xorl %eax, %eax
callq 0x3090
movl 0x40(%rbx), %esi
leaq 0x3e31(%rip), %rdi      # 0x9a3a
xorl %eax, %eax
callq 0x3090
movl 0x44(%rbx), %esi
leaq 0x3e38(%rip), %rdi      # 0x9a52
xorl %eax, %eax
callq 0x3090
movl 0x48(%rbx), %esi
leaq 0x3e3f(%rip), %rdi      # 0x9a6a
xorl %eax, %eax
callq 0x3090
movzwl 0x4c(%rbx), %esi
leal -0x1(%rsi), %eax
cmpw $0xe, %ax
ja 0x5c52
movzwl %ax, %eax
leaq 0x40cb(%rip), %rcx      # 0x9d14
movslq (%rcx,%rax,4), %rdx
addq %rcx, %rdx
jmp 0x5c59
leaq 0x3047(%rip), %rdx      # 0x8ca0
leaq 0x3ea7(%rip), %rdi      # 0x9b07
xorl %eax, %eax
callq 0x3090
movzwl 0x4e(%rbx), %esi
leaq 0x3eb2(%rip), %rdi      # 0x9b24
xorl %eax, %eax
callq 0x3090
testb $0x1, 0x4e(%rbx)
je 0x5c8d
leaq 0x3eb9(%rip), %rdi      # 0x9b3f
xorl %eax, %eax
callq 0x3090
testb $0x2, 0x4e(%rbx)
je 0x5ca1
leaq 0x3eb3(%rip), %rdi      # 0x9b4d
xorl %eax, %eax
callq 0x3090
testb $0x4, 0x4e(%rbx)
je 0x5cb5
leaq 0x3ead(%rip), %rdi      # 0x9b5b
xorl %eax, %eax
callq 0x3090
testb $0x8, 0x4e(%rbx)
je 0x5cc9
leaq 0x3ea7(%rip), %rdi      # 0x9b69
xorl %eax, %eax
callq 0x3090
testb $0x40, 0x4e(%rbx)
je 0x5cdd
leaq 0x3ea1(%rip), %rdi      # 0x9b77
xorl %eax, %eax
callq 0x3090
testb $-0x80, 0x4e(%rbx)
je 0x5cf1
leaq 0x3e9e(%rip), %rdi      # 0x9b88
xorl %eax, %eax
callq 0x3090
testb $0x1, 0x4f(%rbx)
je 0x5d05
leaq 0x3e9d(%rip), %rdi      # 0x9b9b
xorl %eax, %eax
callq 0x3090
testb $0x2, 0x4f(%rbx)
je 0x5d19
leaq 0x3e9c(%rip), %rdi      # 0x9bae
xorl %eax, %eax
callq 0x3090
testb $0x4, 0x4f(%rbx)
je 0x5d2d
leaq 0x3e98(%rip), %rdi      # 0x9bbe
xorl %eax, %eax
callq 0x3090
testb $0x8, 0x4f(%rbx)
je 0x5d41
leaq 0x3ea7(%rip), %rdi      # 0x9be1
xorl %eax, %eax
callq 0x3090
testb $0x20, 0x4f(%rbx)
je 0x5d55
leaq 0x3e9e(%rip), %rdi      # 0x9bec
xorl %eax, %eax
callq 0x3090
cmpw $0x0, 0x4e(%rbx)
jns 0x5d6a
leaq 0x3e97(%rip), %rdi      # 0x9bfa
xorl %eax, %eax
callq 0x3090
movl $0xa, %edi
callq 0x3030
movq 0x50(%rbx), %rsi
leaq 0x3e94(%rip), %rdi      # 0x9c13
xorl %eax, %eax
callq 0x3090
movq 0x58(%rbx), %rsi
leaq 0x3e9b(%rip), %rdi      # 0x9c2c
xorl %eax, %eax
callq 0x3090
movq 0x60(%rbx), %rsi
leaq 0x3ea2(%rip), %rdi      # 0x9c45
xorl %eax, %eax
callq 0x3090
movq 0x68(%rbx), %rsi
leaq 0x3ea9(%rip), %rdi      # 0x9c5e
xorl %eax, %eax
callq 0x3090
movl 0x70(%rbx), %esi
leaq 0x3eb1(%rip), %rdi      # 0x9c77
xorl %eax, %eax
callq 0x3090
movl 0x74(%rbx), %esi
leaq 0x3eb8(%rip), %rdi      # 0x9c8f
xorl %eax, %eax
callq 0x3090
movl $0xa, %edi
callq 0x3030
cmpl $0x0, 0x78(%rbx)
je 0x5e61
leaq 0x3ee8(%rip), %rdi      # 0x9cdd
callq 0x3060
movl 0x78(%rbx), %ebp
testl %ebp, %ebp
jle 0x5e61
leaq 0x72b8(%rip), %r12      # 0xd0c0
leaq 0x230c(%rip), %r13      # 0x811b
leaq 0x3e91(%rip), %r14      # 0x9ca7
xorl %r15d, %r15d
movq %r13, %rdx
cmpq $0xe, %r15
ja 0x5e26
movq (%r12), %rdx
movl 0x7c(%rbx,%r15,8), %ecx
movl 0x80(%rbx,%r15,8), %r8d
movq %r14, %rdi
movl %r15d, %esi
movl %r8d, %r9d
xorl %eax, %eax
callq 0x3090
incq %r15
movslq 0x78(%rbx), %rax
addq $0x8, %r12
cmpq %rax, %r15
jl 0x5e19
testl %ebp, %ebp
jle 0x5e61
movl $0xa, %edi
callq 0x3030
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop