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

```asm
<encodeBase64>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x88,%rsp
  mov    %rdi,%rbp
  mov    %rdi,0x28(%rsp)
  mov    %rsi,%r15
  mov    %rsi,0x18(%rsp)
  mov    %fs:0x28,%rax
  mov    %rax,0x78(%rsp)
  xor    %eax,%eax
  lea    0x2(%rsi),%rdx
  movabs $0xaaaaaaaaaaaaaaab,%rcx
  mov    %rdx,%rax
  mul    %rcx
  mov    %rdx,%rax
  shr    %rax
  and    $0xfffffffffffffffe,%rdx
  add    %rax,%rdx
  mov    %rdx,%rax
  mul    %rcx
  shr    %rdx
  mov    %rdx,0x20(%rsp)
  lea    0x1(,%rdx,4),%rbx
  mov    %rbx,%rsi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,%r14
  mov    %rax,0x10(%rsp)
  mov    %rbx,%rdx
  mov    $0x0,%esi
  mov    %rax,%rdi
  call   <memset@plt>
  movabs $0x4847464544434241,%rax
  movabs $0x504f4e4d4c4b4a49,%rdx
  mov    %rax,0x30(%rsp)
  mov    %rdx,0x38(%rsp)
  movabs $0x5857565554535251,%rax
  movabs $0x6665646362615a59,%rdx
  mov    %rax,0x40(%rsp)
  mov    %rdx,0x48(%rsp)
  movabs $0x6e6d6c6b6a696867,%rax
  movabs $0x767574737271706f,%rdx
  mov    %rax,0x50(%rsp)
  mov    %rdx,0x58(%rsp)
  movabs $0x333231307a797877,%rax
  movabs $0x2f2b393837363534,%rdx
  mov    %rax,0x60(%rsp)
  mov    %rdx,0x68(%rsp)
  sub    $0x3,%r15
  je     L71
  mov    %rbp,%rbx
  mov    %r14,%rbp
  mov    $0x0,%r12d
  mov    $0x4,%eax
  sub    %r14d,%eax
  mov    %eax,0xc(%rsp)
L58:
  movsbl (%rbx),%edi
  call   <encode64Char1@plt>
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    %al,0x0(%rbp)
  movsbl 0x1(%rbx),%esi
  movsbl (%rbx),%edi
  call   <encode64Char2@plt>
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    %al,0x1(%rbp)
  movsbl 0x2(%rbx),%esi
  movsbl 0x1(%rbx),%edi
  call   <encode64Char3@plt>
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    %al,0x2(%rbp)
  movsbl 0x2(%rbx),%edi
  call   <encode64Char4@plt>
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    %al,0x3(%rbp)
  mov    %r12d,%eax
  lea    0x3(%r12),%r14d
  mov    0xc(%rsp),%ecx
  lea    (%rcx,%rbp,1),%r13d
  add    $0x3,%r12
  add    $0x3,%rbx
  add    $0x4,%rbp
  cmp    %r12,%r15
  ja     L58
  mov    0x18(%rsp),%rcx
  cmp    %r12,%rcx
  ja     L56
L21:
  mov    0x10(%rsp),%rax
  mov    0x20(%rsp),%rcx
  movb   $0x0,(%rax,%rcx,4)
  mov    0x78(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L53
  mov    0x10(%rsp),%rax
  add    $0x88,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L56:
  add    $0x4,%eax
  cltq
  cmp    %rcx,%rax
  jb     L94
  movslq %r13d,%rax
  mov    0x10(%rsp),%rcx
  movb   $0x3d,0x2(%rcx,%rax,1)
  mov    $0x0,%ebx
  jmp    L19
L71:
  mov    %r15,%r12
  mov    $0x0,%r13d
  mov    $0x0,%r14d
  mov    $0x1,%eax
L94:
  mov    0x28(%rsp),%rcx
  movzbl (%rcx,%rax,1),%ebx
  lea    0x2(%r14),%eax
  cltq
  mov    $0x0,%esi
  cmp    0x18(%rsp),%rax
  jae    L20
  movzbl (%rcx,%rax,1),%esi
L20:
  movsbl %sil,%esi
  movsbl %bl,%edi
  call   <encode64Char3@plt>
  mov    %rax,%rdx
  movslq %r13d,%rax
  movzbl 0x30(%rsp,%rdx,1),%edx
  mov    0x10(%rsp),%rcx
  mov    %dl,0x2(%rcx,%rax,1)
L19:
  add    $0x2,%r14d
  movslq %r14d,%r14
  cmp    0x18(%rsp),%r14
  jb     L55
  movslq %r13d,%rax
  mov    0x10(%rsp),%rcx
  movb   $0x3d,0x3(%rcx,%rax,1)
L32:
  add    0x28(%rsp),%r12
  movsbl (%r12),%edi
  call   <encode64Char1@plt>
  movslq %r13d,%r13
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    0x10(%rsp),%r14
  mov    %al,(%r14,%r13,1)
  movsbl %bl,%esi
  movsbl (%r12),%edi
  call   <encode64Char2@plt>
  movzbl 0x30(%rsp,%rax,1),%eax
  mov    %al,0x1(%r14,%r13,1)
  jmp    L21
L55:
  mov    0x28(%rsp),%rax
  movsbl (%rax,%r14,1),%edi
  call   <encode64Char4@plt>
  mov    %rax,%rdx
  movslq %r13d,%rax
  movzbl 0x30(%rsp,%rdx,1),%edx
  mov    0x10(%rsp),%rcx
  mov    %dl,0x3(%rcx,%rax,1)
  jmp    L32
L53:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
char *encodeBase64(const char *cstr, size_t len) {
  int i, o;
  i = o = 0;
  size_t outputLength = (len + 2 - ((len + 2) % 3)) / 3 * 4;
  char *output = (char *)calloc(sizeof(char), outputLength + 1);
  memset(output, 0, outputLength + 1);
  char base64Table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
  while (i < (len - 3)) {
    output[o] = base64Table[encode64Char1(cstr[i])];
    output[o + 1] = base64Table[encode64Char2(cstr[i], cstr[i + 1])];
    output[o + 2] = base64Table[encode64Char3(cstr[i + 1], cstr[i + 2])];
    output[o + 3] = base64Table[encode64Char4(cstr[i + 2])];
    i += 3;
    o += 4;
  }
  if (i < len) {
    char ci2, ci3;
    if ((i + 1) < len) {
      ci2 = cstr[i + 1];
      if ((i + 2) < len) {
        ci3 = cstr[i + 2];
      } else {
        ci3 = 0;
      }
      output[o + 2] = base64Table[encode64Char3(ci2, ci3)];
    } else {
      ci2 = 0;
      output[o + 2] = '=';
    }
    if ((i + 2) < len) {
      output[o + 3] = base64Table[encode64Char4(cstr[i + 2])];
    } else {
      output[o + 3] = '=';
    }
    output[o] = base64Table[encode64Char1(cstr[i])];
    output[o + 1] = base64Table[encode64Char2(cstr[i], ci2)];
  }
  output[outputLength] = '\0';
  return output;
}
```