user: 这段汇编代码用C语言表示是什么样的？

```asm
<extract_image>:
  endbr64
  push   %r14
  mov    %r8d,%r14d
  push   %r13
  mov    %edx,%r13d
  push   %r12
  mov    %rdi,%r12
  push   %rbp
  mov    %r9,%rbp
  push   %rbx
  mov    %ecx,%ebx
  add    $0xffffffffffffff80,%rsp
  mov    %fs:0x28,%rdx
  mov    %rdx,0x78(%rsp)
  xor    %edx,%edx
  movslq %esi,%rdx
  movq   $0x0,0x10(%rsp)
  movq   $0x0,0x18(%rsp)
  lea    -0x20000000(%rdi,%rdx,4),%rdi
  movq   $0x0,0x20(%rsp)
  test   %ecx,%ecx
  jne    L109
  mov    %rdi,0x20(%rsp)
L46:
  movq   $0x0,0x28(%rsp)
  movslq %r13d,%rax
  lea    -0x20000000(%r12,%rax,4),%rdi
  test   %r14d,%r14d
  jne    L68
  mov    %rdi,0x28(%rsp)
L3:
  pxor   %xmm0,%xmm0
  xor    %r9d,%r9d
  lea    0x30(%rsp),%r8
  movaps %xmm0,0x30(%rsp)
  movaps %xmm0,0x40(%rsp)
  movaps %xmm0,0x50(%rsp)
  movaps %xmm0,0x60(%rsp)
  jmp    L66
  nopl   (%rax)
L26:
  or     $0xff000000,%eax
  mov    %eax,-0x4(%r8,%rsi,4)
  cmp    $0x10,%rsi
  je     L105
L48:
  mov    %rsi,%r9
L66:
  mov    (%rdi,%r9,4),%edx
  lea    0x1(%r9),%rsi
  mov    %edx,%eax
  mov    %edx,%ecx
  shl    $0x3,%edx
  shl    $0x6,%eax
  shl    $0x9,%ecx
  movzbl %dl,%edx
  and    $0xf800,%eax
  and    $0xf80000,%ecx
  or     %ecx,%eax
  or     %edx,%eax
  test   %r9,%r9
  jne    L26
  mov    %eax,0x30(%rsp)
  jmp    L48
  nopl   (%rax)
L105:
  mov    0xc(%rsp),%esi
  mov    0x20(%rsp),%rdi
  lea    0x10(%rsp),%rcx
  mov    %r8,%rdx
  call   <deindex_4bpp@plt>
  mov    %eax,%r12d
  test   %ebx,%ebx
  jne    L32
L5:
  mov    0x10(%rsp),%rdi
  lea    0x18(%rsp),%rcx
  mov    $0x8,%edx
  mov    %r12d,%esi
  call   <detile@plt>
  mov    0x18(%rsp),%rax
  mov    0x10(%rsp),%rdi
  mov    %rax,0x0(%rbp)
  call   <free@plt>
  mov    0x78(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L77
  sub    $0xffffffffffffff80,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
  nopl   0x0(%rax)
L109:
  mov    $0x9000000,%ecx
  lea    0xc(%rsp),%rdx
  sub    %esi,%ecx
  lea    0x20(%rsp),%rsi
  call   <decompress@plt>
  jmp    L46
  nopl   0x0(%rax,%rax,1)
L32:
  mov    0x20(%rsp),%rdi
  call   <free@plt>
  jmp    L5
  nopl   0x0(%rax)
L68:
  mov    $0x9000000,%ecx
  lea    0x28(%rsp),%rsi
  xor    %edx,%edx
  sub    %r13d,%ecx
  call   <decompress@plt>
  mov    0x28(%rsp),%rdi
  jmp    L3
L77:
  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);
}
```