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

```asm
<decode_quoted_printable>:
  endbr64
  push   %r15
  push   %r14
  mov    %esi,%r14d
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x18,%rsp
  mov    (%rdx),%ebx
  movl   $0x0,(%rdx)
  test   %r14d,%r14d
  je     L68
  mov    %rdi,%r12
  lea    0x1(%r14),%edi
  mov    %rdx,%r13
  mov    %ecx,%r15d
  mov    %edi,(%rsp)
  call   <malloc@plt>
  mov    %rax,%rbp
  test   %rax,%rax
  je     L68
  test   %r15d,%r15d
  je     L118
  lea    -0x1(%r14),%edx
  mov    %rax,%rdi
  xor    %ecx,%ecx
  mov    $0x20,%r10d
  movabs $0x7e0000007e03ff,%r15
  jmp    L440
  nopl   0x0(%rax,%rax,1)
L178:
  cmp    $0x5f,%al
  cmove  %r10d,%eax
L211:
  add    $0x1,%ecx
  mov    %al,(%rdi)
  lea    0x1(%rdi),%rsi
  cmp    %ecx,%ebx
  jbe    L269
L28:
  lea    -0x1(%rdx),%eax
  test   %edx,%edx
  je     L269
  mov    %edx,%r14d
  mov    %rsi,%rdi
  mov    %eax,%edx
  mov    %r8,%r12
L440:
  movzbl (%r12),%eax
  lea    0x1(%r12),%r8
  cmp    $0x3d,%al
  jne    L178
  movzbl 0x1(%r12),%r9d
  mov    %r9d,%esi
  and    $0xffffffdf,%esi
  sub    $0x41,%esi
  cmp    $0x5,%sil
  jbe    L410
  lea    -0x30(%r9),%esi
  cmp    $0x9,%sil
  ja     L211
L410:
  movzbl 0x2(%r12),%esi
  lea    -0x30(%rsi),%r11d
  cmp    $0x36,%r11b
  ja     L211
  bt     %r11,%r15
  jae    L211
  movzbl %r9b,%eax
  mov    $0x30,%r8d
  cmp    $0x39,%r9b
  jbe    L352
  cmp    $0x47,%r9b
  sbb    %r8d,%r8d
  and    $0xffffffe0,%r8d
  add    $0x57,%r8d
L352:
  sub    %r8d,%eax
  mov    $0x30,%r8d
  shl    $0x4,%eax
  cmp    $0x39,%sil
  jbe    L106
  cmp    $0x47,%sil
  sbb    %r8d,%r8d
  and    $0xffffffe0,%r8d
  add    $0x57,%r8d
L106:
  sub    %r8d,%esi
  or     %esi,%eax
  test   %edx,%edx
  je     L390
  xor    %esi,%esi
  lea    -0x3(%r14),%edx
  cmp    $0x2,%r14d
  cmove  %esi,%edx
L390:
  mov    %al,(%rdi)
  lea    0x3(%r12),%r8
  lea    0x1(%rdi),%rsi
  add    $0x1,%ecx
  cmp    %ecx,%ebx
  ja     L28
  nopl   0x0(%rax)
L269:
  movb   $0x0,(%rsi)
  sub    %rbp,%rsi
  mov    %esi,0x0(%r13)
  add    $0x1,%esi
  jmp    L29
L199:
  mov    %rbp,%rdi
  call   <free@plt>
L68:
  add    $0x18,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L118:
  mov    (%rsp),%edi
  call   <malloc@plt>
  mov    %rax,(%rsp)
  test   %rax,%rax
  je     L199
  mov    (%rsp),%r15
  mov    %r14d,%edx
  mov    %r12,%rsi
  movabs $0x7e0000007e03ff,%r12
  mov    %r15,%rdi
  call   <memcpy@plt>
  movb   $0x0,(%r15,%r14,1)
  mov    %r15,%r14
  mov    %rbp,%r15
L355:
  mov    $0xa,%esi
  mov    %r14,%rdi
  call   <strchr@plt>
  test   %rax,%rax
  je     L334
  lea    -0x1(%rax),%rdx
  lea    0x1(%rax),%rsi
  cmp    %r14,%rdx
  jb     L443
  movzbl -0x1(%rax),%ecx
  cmp    $0xd,%cl
  jne    L427
  jmp    L301
  nopl   0x0(%rax)
L202:
  movzbl (%rdx),%ecx
L427:
  cmp    $0x20,%cl
  je     L136
  cmp    $0x9,%cl
  jne    L443
L136:
  sub    $0x1,%rdx
  cmp    %r14,%rdx
  jae    L202
L443:
  movb   $0x0,0x1(%rdx)
  lea    0x1(%r15),%rax
  xchg   %ax,%ax
L124:
  movzbl (%r14),%edx
  lea    -0x1(%rax),%rdi
  lea    0x1(%r14),%r8
  test   %dl,%dl
  je     L330
  cmp    $0x3d,%dl
  jne    L90
  movzbl 0x1(%r14),%r9d
  test   %r9b,%r9b
  je     L99
  mov    %r9d,%ecx
  and    $0xffffffdf,%ecx
  sub    $0x41,%ecx
  cmp    $0x5,%cl
  jbe    L447
  lea    -0x30(%r9),%ecx
  cmp    $0x9,%cl
  jbe    L447
  cs nopw 0x0(%rax,%rax,1)
L90:
  mov    %rax,%rdi
  mov    %r8,%r14
L369:
  mov    %dl,-0x1(%rax)
  mov    %rax,%rdx
  add    $0x1,%rax
  sub    %rbp,%rdx
  mov    %edx,%ecx
  cmp    %edx,%ebx
  ja     L124
  nopl   0x0(%rax)
L88:
  movb   $0x0,(%rdi)
  mov    (%rsp),%rdi
  mov    %ecx,0xc(%rsp)
  call   <free@plt>
  mov    0xc(%rsp),%ecx
  mov    %ecx,0x0(%r13)
  lea    0x1(%rcx),%esi
L29:
  add    $0x18,%rsp
  mov    %rbp,%rdi
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  jmp    10f0 <realloc@plt>
  nopl   0x0(%rax)
L330:
  test   %rsi,%rsi
  je     L319
  mov    %rax,%rdx
  movb   $0xa,(%rdi)
  mov    %rax,%r15
  sub    %rbp,%rdx
  mov    %edx,%ecx
  cmp    %edx,%ebx
  jbe    L84
L424:
  mov    %rsi,%r14
  jmp    L355
  nop
L447:
  movzbl 0x2(%r14),%ecx
  lea    -0x30(%rcx),%edi
  cmp    $0x36,%dil
  ja     L90
  bt     %rdi,%r12
  jae    L90
  movzbl %r9b,%edx
  mov    $0x30,%edi
  cmp    $0x39,%r9b
  jbe    L451
  cmp    $0x47,%r9b
  sbb    %edi,%edi
  and    $0xffffffe0,%edi
  add    $0x57,%edi
L451:
  sub    %edi,%edx
  mov    $0x30,%r8d
  shl    $0x4,%edx
  cmp    $0x39,%cl
  jbe    L137
  cmp    $0x47,%cl
  sbb    %r8d,%r8d
  and    $0xffffffe0,%r8d
  add    $0x57,%r8d
L137:
  sub    %r8d,%ecx
  mov    %rax,%rdi
  add    $0x3,%r14
  or     %ecx,%edx
  jmp    L369
  cs nopw 0x0(%rax,%rax,1)
L99:
  mov    %rdi,%rax
  sub    %rbp,%rax
  mov    %eax,%ecx
  cmp    %eax,%ebx
  jbe    L88
  test   %rsi,%rsi
  je     L88
  mov    %rdi,%r15
  jmp    L424
  nopl   0x0(%rax)
L319:
  mov    %edi,%ecx
  sub    %ebp,%ecx
  jmp    L88
  nopl   0x0(%rax)
L334:
  mov    %r14,%rdi
  call   <strlen@plt>
  xor    %esi,%esi
  cltq
  lea    -0x1(%r14,%rax,1),%rdx
L170:
  cmp    %r14,%rdx
  jae    L202
  jmp    L443
  nopw   0x0(%rax,%rax,1)
L84:
  mov    %rax,%rdi
  jmp    L88
  nopl   0x0(%rax,%rax,1)
L301:
  lea    -0x2(%rax),%rdx
  jmp    L170
```

assistant: ```c
char *decode_quoted_printable(unsigned char *buf, unsigned int len, unsigned int *ret_len, int header) {
  unsigned char *dest, *deststart;
  unsigned int limit = *ret_len;
  *ret_len = 0;
  if (!len)
    return NULL;
  if (!(dest = (unsigned char *)malloc(len + 1)))
    return NULL;
  deststart = dest;
  if (header) {
    unsigned int real_len = 0;
    while (len--) {
      unsigned char c = *buf++;
      if ('=' == c) {
        unsigned char c2;
        c = buf[0];
        c2 = buf[1];
        if (((((c) >= '0') && ((c) <= '9')) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) && ((((c2) >= '0') && ((c2) <= '9')) || (((c2) >= 'A') && ((c2) <= 'F')) || (((c2) >= 'a') && ((c2) <= 'f')))) {
          c = (((c) - (((c) > '9') ? (((c) > 'F') ? 'a' - 10 : 'A' - 10) : '0')) << 4) | ((c2) - (((c2) > '9') ? (((c2) > 'F') ? 'a' - 10 : 'A' - 10) : '0'));
          if (len)
            len--;
          if (len)
            len--;
          buf += 2;
        } else
          c = '=';
      } else if ('_' == c)
        c = ' ';
      *dest++ = c;
      if (++real_len >= limit)
        break;
    }
    *dest = 0;
    *ret_len = dest - deststart;
    return (char *)realloc(deststart, *ret_len + 1);
  } else {
    unsigned char *text, *textstart;
    if (!(text = (unsigned char *)malloc(len + 1))) {
      free(dest);
      return NULL;
    }
    memcpy(text, buf, len);
    text[len] = 0;
    textstart = text;
    while (text) {
      unsigned char c;
      unsigned char *lp = text;
      {
        unsigned char *ep;
        if ((ep = (unsigned char *)strchr((char *)lp, '\n'))) {
          text = ep + 1;
          ep--;
          if (ep >= lp) {
            if ('\r' == *ep)
              ep--;
          }
        } else {
          ep = lp + strlen((char *)lp) - 1;
          text = NULL;
        }
        while ((ep >= lp) && (((c = *ep) == ' ') || (c == '\t')))
          ep--;
        *(ep + 1) = '\0';
      }
      do {
        switch (c = *lp++) {
        case '\0':
          if (text)
            *dest++ = '\n';
          break;
        case '=':
          if ((c = *lp)) {
            unsigned char d = *(lp + 1);
            if (((((c) >= '0') && ((c) <= '9')) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) && ((((d) >= '0') && ((d) <= '9')) || (((d) >= 'A') && ((d) <= 'F')) || (((d) >= 'a') && ((d) <= 'f')))) {
              *dest++ = (((c) - (((c) > '9') ? (((c) > 'F') ? 'a' - 10 : 'A' - 10) : '0')) << 4) | ((d) - (((d) > '9') ? (((d) > 'F') ? 'a' - 10 : 'A' - 10) : '0'));
              lp += 2;
            } else {
              *dest++ = '=';
            }
          }
          break;
        default:
          *dest++ = c;
          break;
        }
        if ((unsigned int)(dest - deststart) >= limit) {
          text = NULL;
          break;
        }
      } while (c);
    }
    *dest = 0;
    free(textstart);
    *ret_len = dest - deststart;
    return (char *)realloc(deststart, *ret_len + 1);
  }
}
```