user: 下面的汇编指令对应的C源代码是什么:

```asm
<base64decode>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x18,%rsp
  mov    %rdi,%r14
  mov    %rsi,%r12
  cmpb   $0x3d,-0x3(%rdi,%rsi,1)
  je     L118
  cmpb   $0x3d,-0x2(%rdi,%rsi,1)
  je     L59
  cmpb   $0x3d,-0x1(%rdi,%rsi,1)
  jne    L39
  sub    $0x1,%r12
  jmp    L39
L118:
  sub    $0x3,%r12
L39:
  lea    (%r12,%r12,2),%rax
  add    %rax,%rax
  lea    0x7(%rax),%rdi
  cmovns %rax,%rdi
  sar    $0x3,%rdi
  mov    %rdi,(%rdx)
  call   <malloc@plt>
  mov    %rax,%rbp
  mov    %rax,0x8(%rsp)
  test   %r12,%r12
  jle    L29
  lea    -0x1(%r12),%rax
  and    $0xfffffffffffffffc,%rax
  lea    0x4(%r14,%rax,1),%r15
  mov    %r14,%rbx
  add    %r12,%r14
  jmp    L14
L59:
  sub    $0x2,%r12
  jmp    L39
L82:
  movsbl (%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%r12d
  movsbl 0x1(%rbx),%edi
  call   <b2n@plt>
  shr    $0x4,%ax
  and    $0x3,%eax
  shl    $0x2,%r12d
  or     %eax,%r12d
  mov    %r12b,0x0(%rbp)
  add    $0x1,%rbp
L40:
  add    $0x4,%rbx
  cmp    %r15,%rbx
  je     L25
L14:
  mov    %r14,%rax
  sub    %rbx,%rax
  cmp    $0x2,%rax
  je     L82
  cmp    $0x3,%rax
  je     L34
  movsbl (%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%r13d
  movsbl 0x1(%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%r12d
  movsbl 0x2(%rbx),%edi
  call   <b2n@plt>
  mov    %al,0x7(%rsp)
  movsbl 0x3(%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%ecx
  movzbl %r12b,%r12d
  mov    %r12d,%eax
  sar    $0x4,%eax
  and    $0x3,%eax
  shl    $0x2,%r13d
  or     %eax,%r13d
  mov    %r13b,0x0(%rbp)
  movzbl 0x7(%rsp),%eax
  mov    %eax,%edx
  sar    $0x2,%edx
  and    $0xf,%edx
  shl    $0x4,%r12d
  or     %r12d,%edx
  mov    %dl,0x1(%rbp)
  shl    $0x6,%eax
  or     %eax,%ecx
  mov    %cl,0x2(%rbp)
  add    $0x3,%rbp
  jmp    L40
L34:
  movsbl (%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%r13d
  movsbl 0x1(%rbx),%edi
  call   <b2n@plt>
  mov    %eax,%r12d
  movsbl 0x2(%rbx),%edi
  call   <b2n@plt>
  movzbl %r12b,%edx
  mov    %edx,%ecx
  sar    $0x4,%ecx
  and    $0x3,%ecx
  shl    $0x2,%r13d
  or     %ecx,%r13d
  mov    %r13b,0x0(%rbp)
  mov    %eax,%r12d
  shr    $0x2,%r12w
  and    $0xf,%r12d
  shl    $0x4,%edx
  or     %edx,%r12d
  mov    %r12b,0x1(%rbp)
  add    $0x2,%rbp
  jmp    L40
L29:
  mov    0x8(%rsp),%rbp
L25:
  movb   $0x0,0x0(%rbp)
  mov    0x8(%rsp),%rax
  add    $0x18,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
```

assistant: ```c
unsigned char *base64decode(char *base64, long size, long *outsize) {
  long real_size;
  unsigned char c0, c1, c2, c3;
  if (base64[size - 1 - 2] == '=')
    real_size = size - 3;
  else if (base64[size - 1 - 1] == '=')
    real_size = size - 2;
  else if (base64[size - 1] == '=')
    real_size = size - 1;
  else
    real_size = size;
  *outsize = real_size * 6 / 8;
  unsigned char *res = (unsigned char *)malloc(real_size * 6 / 8);
  unsigned char *res_p = res;
  int rest_bit = 8;
  int idx;
  for (idx = 0; idx < real_size; idx += 4) {
    switch (real_size - idx) {
    case 2:
      c0 = b2n(base64[idx + 0]);
      c1 = b2n(base64[idx + 1]);
      res_p[0] = c0 << 2 | (c1 & 0x30) >> 4;
      res_p += 1;
      break;
    case 3:
      c0 = b2n(base64[idx + 0]);
      c1 = b2n(base64[idx + 1]);
      c2 = b2n(base64[idx + 2]);
      res_p[0] = c0 << 2 | (c1 & 0x30) >> 4;
      res_p[1] = c1 << 4 | (c2 & 0x3c) >> 2;
      res_p += 2;
      break;
    default:
      c0 = b2n(base64[idx + 0]);
      c1 = b2n(base64[idx + 1]);
      c2 = b2n(base64[idx + 2]);
      c3 = b2n(base64[idx + 3]);
      res_p[0] = c0 << 2 | (c1 & 0x30) >> 4;
      res_p[1] = c1 << 4 | (c2 & 0x3c) >> 2;
      res_p[2] = c2 << 6 | c3;
      res_p += 3;
      break;
    }
  }
  *res_p = 0;
  return res;
}
```