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

```asm
<__ultoa>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x30,%rsp
  mov    %edi,-0x14(%rbp)
  mov    %rsi,-0x20(%rbp)
  mov    %edx,-0x18(%rbp)
  mov    %ecx,-0x24(%rbp)
  mov    %r8,-0x30(%rbp)
  mov    -0x20(%rbp),%rax
  mov    %rax,-0x10(%rbp)
  cmpl   $0x10,-0x18(%rbp)
  je     L110
  cmpl   $0x10,-0x18(%rbp)
  jg     L17
  cmpl   $0x8,-0x18(%rbp)
  je     L80
  cmpl   $0xa,-0x18(%rbp)
  jne    L17
  cmpl   $0x9,-0x14(%rbp)
  jg     L134
  mov    -0x14(%rbp),%eax
  add    $0x30,%eax
  subq   $0x1,-0x10(%rbp)
  mov    %eax,%edx
  mov    -0x10(%rbp),%rax
  mov    %dl,(%rax)
  mov    -0x10(%rbp),%rax
  jmp    L153
L134:
  mov    D7(%rip),%rax
  mov    (%rax),%eax
  cmp    %eax,-0x14(%rbp)
  jle    L85
  mov    -0x14(%rbp),%edx
  movslq %edx,%rax
  imul   $0x66666667,%rax,%rax
  shr    $0x20,%rax
  sar    $0x2,%eax
  mov    %edx,%esi
  sar    $0x1f,%esi
  sub    %esi,%eax
  mov    %eax,%ecx
  mov    %ecx,%eax
  shl    $0x2,%eax
  add    %ecx,%eax
  add    %eax,%eax
  mov    %edx,%ecx
  sub    %eax,%ecx
  mov    %ecx,%eax
  add    $0x30,%eax
  subq   $0x1,-0x10(%rbp)
  mov    %eax,%edx
  mov    -0x10(%rbp),%rax
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    $0x2,%edx
  sar    $0x1f,%eax
  mov    %eax,%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  cltq
  mov    %rax,-0x8(%rbp)
  jmp    L93
L85:
  mov    -0x14(%rbp),%eax
  cltq
  mov    %rax,-0x8(%rbp)
L93:
  mov    -0x8(%rbp),%rcx
  movabs $0x6666666666666667,%rdx
  mov    %rcx,%rax
  imul   %rdx
  mov    %rdx,%rax
  sar    $0x2,%rax
  mov    %rcx,%rsi
  sar    $0x3f,%rsi
  sub    %rsi,%rax
  mov    %rax,%rdx
  mov    %rdx,%rax
  shl    $0x2,%rax
  add    %rdx,%rax
  add    %rax,%rax
  sub    %rax,%rcx
  mov    %rcx,%rdx
  mov    %edx,%eax
  add    $0x30,%eax
  subq   $0x1,-0x10(%rbp)
  mov    %eax,%edx
  mov    -0x10(%rbp),%rax
  mov    %dl,(%rax)
  mov    -0x8(%rbp),%rcx
  movabs $0x6666666666666667,%rdx
  mov    %rcx,%rax
  imul   %rdx
  mov    %rdx,%rax
  sar    $0x2,%rax
  sar    $0x3f,%rcx
  mov    %rcx,%rdx
  sub    %rdx,%rax
  mov    %rax,-0x8(%rbp)
  cmpq   $0x0,-0x8(%rbp)
  jne    L93
  jmp    L11
L126:
  nop
L80:
  mov    -0x14(%rbp),%eax
  and    $0x7,%eax
  add    $0x30,%eax
  subq   $0x1,-0x10(%rbp)
  mov    %eax,%edx
  mov    -0x10(%rbp),%rax
  mov    %dl,(%rax)
  sarl   $0x3,-0x14(%rbp)
  cmpl   $0x0,-0x14(%rbp)
  jne    L126
  cmpl   $0x0,-0x24(%rbp)
  je     L56
  mov    -0x10(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x30,%al
  je     L56
  subq   $0x1,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  movb   $0x30,(%rax)
  jmp    L56
L12:
  nop
L110:
  mov    -0x14(%rbp),%eax
  cltq
  and    $0xf,%eax
  mov    %rax,%rdx
  mov    -0x30(%rbp),%rax
  add    %rdx,%rax
  subq   $0x1,-0x10(%rbp)
  movzbl (%rax),%edx
  mov    -0x10(%rbp),%rax
  mov    %dl,(%rax)
  sarl   $0x4,-0x14(%rbp)
  cmpl   $0x0,-0x14(%rbp)
  jne    L12
  jmp    L11
L17:
  mov    $0x1,%edi
  call   <exit@plt>
  jmp    L11
L56:
  nop
L11:
  mov    -0x10(%rbp),%rax
L153:
  leave
  ret
```

assistant: ```c
char *__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) {
  char *cp = endp;
  long sval;
  switch (base) {
  case 10:
    if (val < 10) {
      *--cp = ((val) + '0');
      return (cp);
    }
    if (val > LONG_MAX) {
      *--cp = ((val % 10) + '0');
      sval = val / 10;
    } else
      sval = val;
    do {
      *--cp = ((sval % 10) + '0');
      sval /= 10;
    } while (sval != 0);
    break;
  case 8:
    do {
      *--cp = ((val & 7) + '0');
      val >>= 3;
    } while (val);
    if (octzero && *cp != '0')
      *--cp = '0';
    break;
  case 16:
    do {
      *--cp = xdigs[val & 15];
      val >>= 4;
    } while (val);
    break;
  default:
    exit(1);
  }
  return (cp);
}
```