user: 请从给定的汇编指令推导出C源代码:

```asm
<extract_image>:
  endbr64
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  add    $0xffffffffffffff80,%rsp
  mov    %rdi,%r12
  mov    %edx,%r13d
  mov    %ecx,%ebx
  mov    %r8d,%r14d
  mov    %r9,%rbp
  mov    %fs:0x28,%rdx
  mov    %rdx,0x78(%rsp)
  xor    %edx,%edx
  movq   $0x0,0x10(%rsp)
  movq   $0x0,0x18(%rsp)
  movq   $0x0,0x20(%rsp)
  movslq %esi,%rdx
  lea    -0x20000000(%rdi,%rdx,4),%rdi
  test   %ecx,%ecx
  jne    L60
  mov    %rdi,0x20(%rsp)
L53:
  movq   $0x0,0x28(%rsp)
  movslq %r13d,%rax
  lea    -0x20000000(%r12,%rax,4),%rdi
  test   %r14d,%r14d
  jne    L45
  mov    %rdi,0x28(%rsp)
L75:
  movq   $0x0,0x30(%rsp)
  movq   $0x0,0x38(%rsp)
  movq   $0x0,0x40(%rsp)
  movq   $0x0,0x48(%rsp)
  movq   $0x0,0x50(%rsp)
  movq   $0x0,0x58(%rsp)
  movq   $0x0,0x60(%rsp)
  movq   $0x0,0x68(%rsp)
  mov    0x28(%rsp),%rsi
  mov    $0x1,%ecx
  jmp    L26
L60:
  mov    $0x9000000,%ecx
  sub    %esi,%ecx
  lea    0xc(%rsp),%rdx
  lea    0x20(%rsp),%rsi
  call   <decompress@plt>
  jmp    L53
L45:
  mov    $0x9000000,%ecx
  sub    %r13d,%ecx
  lea    0x28(%rsp),%rsi
  mov    $0x0,%edx
  call   <decompress@plt>
  jmp    L75
L4:
  mov    0x20(%rsp),%rdi
  call   <free@plt>
  jmp    L16
L14:
  or     %edx,%eax
  or     %edi,%eax
  mov    %eax,0x30(%rsp)
L39:
  add    $0x1,%rcx
L26:
  mov    -0x4(%rsi,%rcx,4),%edx
  lea    0x0(,%rdx,8),%eax
  movzbl %al,%edi
  mov    %edx,%eax
  shl    $0x6,%eax
  and    $0xf800,%eax
  shl    $0x9,%edx
  and    $0xf80000,%edx
  cmp    $0x1,%rcx
  je     L14
  or     %edx,%eax
  or     %edi,%eax
  or     $0xff000000,%eax
  mov    %eax,0x2c(%rsp,%rcx,4)
  cmp    $0xf,%rcx
  jbe    L39
  lea    0x10(%rsp),%rcx
  lea    0x30(%rsp),%rdx
  mov    0xc(%rsp),%esi
  mov    0x20(%rsp),%rdi
  call   <deindex_4bpp@plt>
  mov    %eax,%r12d
  test   %ebx,%ebx
  jne    L4
L16:
  lea    0x18(%rsp),%rcx
  mov    $0x8,%edx
  mov    %r12d,%esi
  mov    0x10(%rsp),%rdi
  call   <detile@plt>
  mov    0x18(%rsp),%rax
  mov    %rax,0x0(%rbp)
  mov    0x10(%rsp),%rdi
  call   <free@plt>
  mov    0x78(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L50
  sub    $0xffffffffffffff80,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
L50:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
void extract_image(uint8_t *buffer, uint32_t imgAddr, uint32_t palAddr, int compImg, int compPal, uint32_t **out) {
  uint32_t destSize, srcSize, *pixels = NULL, *image = NULL;
  uint8_t *output = NULL, *offset = NULL;
  size_t i;
  offset = (uint8_t *)(buffer + (imgAddr - 0x8000000));
  srcSize = (1 << 24) - (imgAddr - 0x8000000);
  if (compImg) {
    decompress((const uint8_t *)offset, &output, &destSize, srcSize);
  } else {
    output = offset;
  }
  uint16_t *paletteGBA = NULL;
  uint8_t *paletteComp = (uint8_t *)((palAddr - 0x8000000) + buffer);
  srcSize = (1 << 24) - (palAddr - 0x8000000);
  if (compPal) {
    decompress((const uint8_t *)paletteComp, (uint8_t **)&paletteGBA, NULL, srcSize);
  } else {
    paletteGBA = (uint16_t *)paletteComp;
  }
  uint32_t paletteRGBA[16] = {};
  for (i = 0; i < 16; i++) {
    uint32_t r, g, b, a;
    r = ((paletteGBA[i] >> 0) & 0x1F) << (3);
    g = ((paletteGBA[i] >> 5) & 0x1F) << (3 + 8);
    b = ((paletteGBA[i] >> 10) & 0x1F) << (3 + 16);
    a = (i ? 0xFF : 0x0) << 24;
    paletteRGBA[i] = r | g | b | a;
  }
  int length = deindex_4bpp(output, destSize, paletteRGBA, &pixels);
  if (compImg)
    free(output);
  detile(pixels, length, 8, &image);
  *out = image;
  free(pixels);
}
```