user: What would the C source look like for the assembly code provided here:

```asm
<qbase64_encode>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x68,%rsp
  movdqa D6(%rip),%xmm0
  mov    %fs:0x28,%rax
  mov    %rax,0x58(%rsp)
  xor    %eax,%eax
  movaps %xmm0,0x10(%rsp)
  movdqa D9(%rip),%xmm0
  movaps %xmm0,0x20(%rsp)
  movdqa D39(%rip),%xmm0
  movaps %xmm0,0x30(%rsp)
  movdqa D47(%rip),%xmm0
  movaps %xmm0,0x40(%rsp)
  test   %rsi,%rsi
  je     L6
  mov    %rsi,%rax
  mov    %rdi,%rbp
  mov    %rsi,%rbx
  movabs $0xaaaaaaaaaaaaaaab,%rdx
  mul    %rdx
  xor    %eax,%eax
  mov    %rdx,%rcx
  and    $0xfffffffffffffffe,%rdx
  shr    %rcx
  add    %rcx,%rdx
  cmp    %rdx,%rsi
  setne  %al
  add    %rcx,%rax
  lea    0x1(,%rax,4),%edi
  call   <malloc@plt>
  mov    %rax,%r12
  test   %rax,%rax
  je     L68
  xor    %eax,%eax
  lea    -0x1(%rbp,%rbx,1),%r14
  movb   $0x0,0xf(%rsp)
  mov    %r12,%rcx
  mov    %ax,0xd(%rsp)
  cmp    %r14,%rbp
  ja     L116
  xor    %r13d,%r13d
  mov    $0xaaaaaaab,%ebx
  jmp    L15
  nopl   0x0(%rax)
L73:
  movzbl 0xf(%rsp),%esi
  movzbl 0xe(%rsp),%edx
  shr    $0x6,%sil
  shl    $0x2,%edx
  and    $0x3c,%edx
  movzbl %sil,%esi
  or     %esi,%edx
  movslq %edx,%rdx
  movzbl 0x10(%rsp,%rdx,1),%edx
  mov    %dl,0x2(%rcx)
  mov    $0x3d,%edx
  cmp    $0x2,%eax
  jne    L89
  movzbl 0xf(%rsp),%eax
  and    $0x3f,%eax
  movzbl 0x10(%rsp,%rax,1),%edx
L89:
  mov    %dl,0x3(%rcx)
  lea    0x4(%rcx),%r15
  lea    0xd(%rsp),%rdi
  xor    %esi,%esi
  mov    $0x3,%edx
  call   <memset@plt>
  mov    %r15,%rcx
L43:
  add    $0x1,%rbp
  add    $0x1,%r13d
  cmp    %rbp,%r14
  jb     L116
L15:
  mov    %r13d,%eax
  movzbl 0x0(%rbp),%esi
  imul   %rbx,%rax
  shr    $0x21,%rax
  lea    (%rax,%rax,2),%edx
  mov    %r13d,%eax
  sub    %edx,%eax
  movslq %eax,%rdx
  mov    %sil,0xd(%rsp,%rdx,1)
  cmp    $0x1,%eax
  jg     L61
  cmp    %rbp,%r14
  ja     L43
L61:
  movzbl 0xd(%rsp),%edx
  shr    $0x2,%dl
  and    $0x3f,%edx
  movzbl 0x10(%rsp,%rdx,1),%edx
  mov    %dl,(%rcx)
  movzbl 0xe(%rsp),%esi
  movzbl 0xd(%rsp),%edx
  shr    $0x4,%sil
  shl    $0x4,%edx
  movzbl %sil,%esi
  and    $0x30,%edx
  or     %esi,%edx
  movslq %edx,%rdx
  movzbl 0x10(%rsp,%rdx,1),%edx
  mov    %dl,0x1(%rcx)
  test   %eax,%eax
  jne    L73
  movb   $0x3d,0x2(%rcx)
  mov    $0x3d,%edx
  jmp    L89
  nopw   0x0(%rax,%rax,1)
L116:
  movb   $0x0,(%rcx)
L68:
  mov    0x58(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L104
  add    $0x68,%rsp
  mov    %r12,%rax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   (%rax)
L6:
  mov    0x58(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L104
  add    $0x68,%rsp
  lea    D40(%rip),%rdi
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  jmp    10b0 <strdup@plt>
L104:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: read_data
arguments: data_tag: D6
data_type: byte[16]
name: read_data
arguments: data_tag: D9
data_type: byte[16]
name: read_data
arguments: data_tag: D39
data_type: byte[16]
name: read_data
arguments: data_tag: D47
data_type: byte[16]
name: read_data
arguments: data_tag: D40
data_type: string

tool: {"D6": [0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50]}

tool: {"D9": [0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x61,0x62,0x63,0x64,0x65,0x66]}

tool: {"D39": [0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76]}

tool: {"D47": [0x77,0x78,0x79,0x7a,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2b,0x2f]}

tool: 

assistant: ```c
char *qbase64_encode(const void *bin, size_t size) {
  const char B64CHARTBL[64] = {'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', '+', '/'};
  if (size == 0) {
    return strdup("");
  }
  char *pszB64 = (char *)malloc(4 * ((size / 3) + ((size % 3 == 0) ? 0 : 1)) + 1);
  if (pszB64 == NULL) {
    return NULL;
  }
  char *pszB64Pt = pszB64;
  unsigned char *pBinPt, *pBinEnd = (unsigned char *)(bin + size - 1);
  unsigned char szIn[3] = {0, 0, 0};
  int nOffset;
  for (pBinPt = (unsigned char *)bin, nOffset = 0; pBinPt <= pBinEnd; pBinPt++, nOffset++) {
    int nIdxOfThree = nOffset % 3;
    szIn[nIdxOfThree] = *pBinPt;
    if (nIdxOfThree < 2 && pBinPt < pBinEnd)
      continue;
    *pszB64Pt++ = B64CHARTBL[((szIn[0] & 0xFC) >> 2)];
    *pszB64Pt++ = B64CHARTBL[(((szIn[0] & 0x03) << 4) | ((szIn[1] & 0xF0) >> 4))];
    *pszB64Pt++ = (nIdxOfThree >= 1) ? B64CHARTBL[(((szIn[1] & 0x0F) << 2) | ((szIn[2] & 0xC0) >> 6))] : '=';
    *pszB64Pt++ = (nIdxOfThree >= 2) ? B64CHARTBL[(szIn[2] & 0x3F)] : '=';
    memset((void *)szIn, 0, sizeof(szIn));
  }
  *pszB64Pt = '\0';
  return pszB64;
}
```