user: Translate the below assembly code into C programming language:

```asm
<base64encode>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  add    $0xffffffffffffff80,%rsp
  mov    %rdi,-0x68(%rbp)
  mov    %rsi,-0x70(%rbp)
  mov    %edx,-0x74(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movabs $0x4847464544434241,%rax
  movabs $0x504f4e4d4c4b4a49,%rdx
  mov    %rax,-0x50(%rbp)
  mov    %rdx,-0x48(%rbp)
  movabs $0x5857565554535251,%rax
  movabs $0x6665646362615a59,%rdx
  mov    %rax,-0x40(%rbp)
  mov    %rdx,-0x38(%rbp)
  movabs $0x6e6d6c6b6a696867,%rax
  movabs $0x767574737271706f,%rdx
  mov    %rax,-0x30(%rbp)
  mov    %rdx,-0x28(%rbp)
  movabs $0x333231307a797877,%rax
  movabs $0x2f2b393837363534,%rdx
  mov    %rax,-0x20(%rbp)
  mov    %rdx,-0x18(%rbp)
  movb   $0x0,-0x10(%rbp)
  movl   $0x0,-0x58(%rbp)
  movl   $0x0,-0x54(%rbp)
  jmp    L73
L61:
  subl   $0x1,-0x74(%rbp)
  shll   $0x8,-0x54(%rbp)
  addl   $0x8,-0x58(%rbp)
  mov    -0x68(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x68(%rbp)
  movzbl (%rax),%eax
  movzbl %al,%eax
  or     %eax,-0x54(%rbp)
  jmp    L6
L70:
  subl   $0x6,-0x58(%rbp)
  mov    -0x58(%rbp),%eax
  mov    -0x54(%rbp),%edx
  mov    %eax,%ecx
  sar    %cl,%edx
  mov    %edx,%eax
  and    $0x3f,%eax
  mov    %eax,%ecx
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movslq %ecx,%rdx
  movzbl -0x50(%rbp,%rdx,1),%edx
  mov    %dl,(%rax)
L6:
  cmpl   $0x5,-0x58(%rbp)
  jg     L70
L73:
  cmpl   $0x0,-0x74(%rbp)
  jg     L61
  cmpl   $0x4,-0x58(%rbp)
  jne    L74
  mov    -0x54(%rbp),%eax
  shl    $0x2,%eax
  and    $0x3c,%eax
  mov    %eax,%ecx
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movslq %ecx,%rdx
  movzbl -0x50(%rbp,%rdx,1),%edx
  mov    %dl,(%rax)
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movb   $0x3d,(%rax)
  jmp    L58
L74:
  cmpl   $0x2,-0x58(%rbp)
  jne    L58
  mov    -0x54(%rbp),%eax
  shl    $0x4,%eax
  and    $0x30,%eax
  mov    %eax,%ecx
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movslq %ecx,%rdx
  movzbl -0x50(%rbp,%rdx,1),%edx
  mov    %dl,(%rax)
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movb   $0x3d,(%rax)
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movb   $0x3d,(%rax)
L58:
  mov    -0x70(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x70(%rbp)
  movb   $0x0,(%rax)
  nop
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L67
  call   <__stack_chk_fail@plt>
L67:
  leave
  ret
```

assistant: ```c
void base64encode(const unsigned char *in, char *out, int len) {
  char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  int shift = 0;
  int accum = 0;
  while (len > 0) {
    len--;
    accum <<= 8;
    shift += 8;
    accum |= *in++;
    while (shift >= 6) {
      shift -= 6;
      *out++ = alphabet[(accum >> shift) & 0x3F];
    }
  }
  if (shift == 4) {
    *out++ = alphabet[(accum & 0xF) << 2];
    *out++ = '=';
  } else if (shift == 2) {
    *out++ = alphabet[(accum & 0x3) << 4];
    *out++ = '=';
    *out++ = '=';
  }
  *out++ = 0;
}
```