user: 请显示与下面列出的汇编代码相匹配的C语言实现:

```asm
<decompress_lz>:
  endbr64
  push   %r15
  mov    %rdi,%r15
  push   %r14
  mov    %rdx,%r14
  push   %r13
  mov    %rsi,%r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x48,%rsp
  mov    (%rsi),%edi
  mov    %fs:0x28,%rax
  mov    %rax,0x38(%rsp)
  xor    %eax,%eax
  lea    0x24(%rsp),%r12
  lea    0x30(%rsp),%rbp
  call   <le32toh@plt>
  movl   $0x0,0x24(%rsp)
  mov    %rax,0x8(%rsp)
  lea    -0x1(%r15),%rax
  mov    %rax,0x28(%rsp)
  lea    0x4(%r13),%rax
  mov    %rax,0x30(%rsp)
  movl   $0x0,0x14(%rsp)
L166:
  mov    %r12,%rsi
  mov    %rbp,%rdi
  call   <next@plt>
  test   %eax,%eax
  je     L22
L131:
  mov    0x30(%rsp),%rdx
  mov    %rdx,%rax
  sub    %r13,%rax
  sub    $0x4,%rax
  cmp    %r14,%rax
  jae    L89
  mov    0x8(%rsp),%rcx
  mov    0x28(%rsp),%rax
  add    %r15,%rcx
  cmp    %rcx,%rax
  jae    L67
  lea    0x1(%rdx),%rcx
  mov    %r12,%rsi
  mov    %rbp,%rdi
  mov    %rcx,0x30(%rsp)
  lea    0x1(%rax),%rcx
  mov    %rcx,0x28(%rsp)
  movzbl (%rdx),%edx
  mov    %dl,0x1(%rax)
  call   <next@plt>
  test   %eax,%eax
  jne    L131
L22:
  mov    $0x1,%ebx
  jmp    L329
  xchg   %ax,%ax
L70:
  cmp    $0x1000002,%ebx
  jg     L282
  mov    %r12,%rsi
  mov    %rbp,%rdi
  call   <next@plt>
  test   %eax,%eax
  jne    L310
  mov    %r12,%rsi
  mov    %rbp,%rdi
  lea    -0x2(%rbx,%rbx,1),%ebx
  call   <next@plt>
  add    %eax,%ebx
L329:
  mov    %r12,%rsi
  mov    %rbp,%rdi
  add    %ebx,%ebx
  call   <next@plt>
  add    %eax,%ebx
  mov    0x30(%rsp),%rax
  sub    %r13,%rax
  sub    $0x4,%rax
  cmp    %r14,%rax
  jb     L70
  mov    $0xfffffff7,%eax
L230:
  mov    0x38(%rsp),%rdx
  sub    %fs:0x28,%rdx
  jne    L280
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L282:
  mov    $0xfffffff6,%eax
  jmp    L230
  nopw   0x0(%rax,%rax,1)
L310:
  cmp    $0x2,%ebx
  je     L10
  mov    0x30(%rsp),%rdx
  mov    %rdx,%rax
  sub    %r13,%rax
  sub    $0x4,%rax
  cmp    %r14,%rax
  jae    L27
  lea    0x1(%rdx),%rax
  sub    $0x3,%ebx
  mov    %rax,0x30(%rsp)
  movzbl (%rdx),%edx
  shl    $0x8,%ebx
  lea    (%rdx,%rbx,1),%ecx
  mov    %ecx,0x14(%rsp)
  cmp    $0xffffffff,%ecx
  je     L175
  mov    0x14(%rsp),%eax
  not    %eax
  and    $0x1,%eax
L148:
  mov    %r12,%rsi
  mov    %rbp,%rdi
  test   %eax,%eax
  je     L165
  call   <next@plt>
  lea    0x1(%rax),%edx
L38:
  mov    0x14(%rsp),%eax
  mov    0x8(%rsp),%rdi
  mov    %eax,%esi
  sar    %esi
  cmp    $0xa01,%eax
  setg   %al
  add    %r15,%rdi
  movzbl %al,%eax
  add    %eax,%edx
  mov    0x28(%rsp),%rax
  movslq %edx,%rcx
  add    %rax,%rcx
  cmp    %rdi,%rcx
  jae    L3
  movslq %esi,%rcx
  sub    %rcx,%rax
  cmp    %rax,%r15
  ja     L113
  lea    0x28(%rsp),%rdi
  call   <copy@plt>
  jmp    L166
  nopl   (%rax)
L165:
  call   <next@plt>
  test   %eax,%eax
  je     L107
  mov    %r12,%rsi
  mov    %rbp,%rdi
  call   <next@plt>
  lea    0x3(%rax),%edx
  jmp    L38
L107:
  lea    0x0(%r13,%r14,1),%rax
  mov    $0x1,%ebx
  mov    %rax,0x18(%rsp)
  jmp    L196
  nopw   0x0(%rax,%rax,1)
L173:
  movslq %ebx,%rax
  cmp    0x8(%rsp),%rax
  jae    L138
  mov    %r12,%rsi
  mov    %rbp,%rdi
  call   <next@plt>
  test   %eax,%eax
  jne    L194
L196:
  mov    %r12,%rsi
  mov    %rbp,%rdi
  add    %ebx,%ebx
  call   <next@plt>
  add    %eax,%ebx
  mov    0x18(%rsp),%rax
  cmp    %rax,0x30(%rsp)
  jb     L173
  mov    $0xfffffffc,%eax
  jmp    L230
L10:
  mov    %r12,%rsi
  mov    %rbp,%rdi
  call   <next@plt>
  jmp    L148
L89:
  mov    $0xfffffffa,%eax
  jmp    L230
L67:
  mov    $0xfffffff9,%eax
  jmp    L230
L138:
  mov    $0xfffffffb,%eax
  jmp    L230
L194:
  lea    0x3(%rbx),%edx
  jmp    L38
L113:
  mov    $0xfffffffd,%eax
  jmp    L230
L3:
  mov    $0xfffffffe,%eax
  jmp    L230
L27:
  mov    $0xfffffff8,%eax
  jmp    L230
L175:
  sub    %r13,%rax
  sub    $0x4,%rax
  cmp    %r14,%rax
  setae  %al
  movzbl %al,%eax
  neg    %eax
  jmp    L230
L280:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
int decompress_lz(char *dst, char *src, size_t src_length) {
  size_t dst_length = le32toh(*((uint32_t *)src));
  char *out = dst - 1;
  char *in = src + 4;
  uint16_t ctrl = 0;
  uint32_t off_copy = 0;
  while (1) {
    while (next(&in, &ctrl)) {
      if (in - src - 4 >= src_length)
        return -6;
      if (out >= dst + dst_length)
        return -7;
      *(++out) = *in++;
    }
    uint32_t off = 1;
    int32_t lng = 0;
    while (1) {
      off *= 2;
      off += next(&in, &ctrl);
      if (in - src - 4 >= src_length)
        return -9;
      if (off > 0x1000002)
        return -10;
      if (next(&in, &ctrl)) {
        break;
      }
      off--;
      off *= 2;
      off += next(&in, &ctrl);
    }
    if (off == 2) {
      lng = next(&in, &ctrl);
      off = off_copy;
    } else {
      if (in - src - 4 >= src_length)
        return -8;
      off -= 3;
      off <<= 8;
      off += (unsigned char)(*in++);
      if (off == -1) {
        if (in - src - 4 >= src_length)
          return -1;
        return 0;
      }
      lng = (off ^ 1) & 1;
    }
    if (lng == 0) {
      if (next(&in, &ctrl)) {
        lng = 3 + next(&in, &ctrl);
      } else {
        ++lng;
        do {
          lng *= 2;
          lng += next(&in, &ctrl);
          if (in >= src + src_length)
            return -4;
          if (lng >= dst_length)
            return -5;
        } while (!next(&in, &ctrl));
        lng += 3;
      }
    } else {
      lng = 1 + next(&in, &ctrl);
    }
    off_copy = off;
    if ((off >> 1) > 0x500)
      ++lng;
    if ((out + lng) >= (dst + dst_length))
      return -2;
    if ((out - (off >> 1)) < dst)
      return -3;
    ;
    copy(&out, off >> 1, lng);
  }
}
```