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

```asm
<is_uint_n_range>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x50,%rsp
  mov    %rdi,-0x28(%rbp)
  mov    %rsi,-0x30(%rbp)
  mov    %rdx,-0x38(%rbp)
  mov    %rcx,-0x40(%rbp)
  mov    %r8d,-0x44(%rbp)
  mov    %r9d,-0x48(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movl   $0xffffffff,-0x10(%rbp)
  movl   $0x0,-0x18(%rbp)
  movl   $0x0,-0x14(%rbp)
  mov    -0x28(%rbp),%rax
  movzbl (%rax),%eax
  test   %al,%al
  je     L20
  cmpq   $0x0,-0x30(%rbp)
  je     L20
  cmpq   $0x4,-0x40(%rbp)
  ja     L20
  cmpq   $0x0,-0x40(%rbp)
  jne    L47
  cmpq   $0x0,-0x38(%rbp)
  je     L47
L20:
  mov    $0xffffffff,%eax
  jmp    L27
L61:
  mov    -0x28(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <isdigit@plt>
  test   %rax,%rax
  jne    L75
  mov    $0xffffffff,%eax
  jmp    L27
L75:
  mov    -0x28(%rbp),%rax
  movzbl (%rax),%eax
  sub    $0x30,%eax
  movzbl %al,%eax
  mov    %eax,-0xc(%rbp)
  addl   $0x1,-0x14(%rbp)
  cmpl   $0x13,-0x14(%rbp)
  jle    L167
  mov    -0x10(%rbp),%eax
  sub    -0xc(%rbp),%eax
  movslq %eax,%rdx
  imul   $0x66666667,%rdx,%rdx
  shr    $0x20,%rdx
  sar    $0x2,%edx
  sar    $0x1f,%eax
  sub    %eax,%edx
  mov    -0x18(%rbp),%eax
  cmp    %eax,%edx
  jge    L167
  mov    $0xffffffff,%eax
  jmp    L27
L167:
  mov    -0x18(%rbp),%edx
  mov    %edx,%eax
  shl    $0x2,%eax
  add    %edx,%eax
  add    %eax,%eax
  mov    %eax,%edx
  mov    -0xc(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x18(%rbp)
  addq   $0x1,-0x28(%rbp)
L47:
  mov    -0x28(%rbp),%rax
  movzbl (%rax),%eax
  test   %al,%al
  je     L176
  mov    -0x30(%rbp),%rax
  lea    -0x1(%rax),%rdx
  mov    %rdx,-0x30(%rbp)
  test   %rax,%rax
  jne    L61
L176:
  mov    -0x18(%rbp),%eax
  cmp    %eax,-0x44(%rbp)
  jg     L52
  mov    -0x18(%rbp),%eax
  cmp    %eax,-0x48(%rbp)
  jge    L63
L52:
  mov    $0xffffffff,%eax
  jmp    L27
L63:
  cmpq   $0x0,-0x38(%rbp)
  je     L40
  mov    -0x40(%rbp),%rax
  mov    %eax,%edx
  mov    $0x4,%eax
  sub    %edx,%eax
  shl    $0x8,%eax
  mov    %ax,-0x1a(%rbp)
  lea    -0x1a(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  lea    -0x18(%rbp),%rdx
  lea    (%rdx,%rax,1),%rcx
  mov    -0x40(%rbp),%rdx
  mov    -0x38(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <memcpy@plt>
L40:
  mov    $0x0,%eax
L27:
  mov    -0x8(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L85
  call   <__stack_chk_fail@plt>
L85:
  leave
  ret
```

assistant: ```c
int is_uint_n_range(const char *str, size_t n, void *value, size_t size, uint64_t min, uint64_t max) {
  const uint64_t max_uint64 = ~(uint64_t)0UL;
  uint64_t value_uint64 = 0, c;
  unsigned short value_offset;
  int len = 0;
  if ('\0' == *str || 0 == n || sizeof(uint64_t) < size || (0 == size && NULL != value)) {
    return -1;
  }
  while ('\0' != *str && 0 < n--) {
    if (0 == isdigit(*str))
      return -1;
    c = (uint64_t)(unsigned char)(*str - '0');
    if (20 <= ++len && (max_uint64 - c) / 10 < value_uint64)
      return -1;
    value_uint64 = value_uint64 * 10 + c;
    str++;
  }
  if (min > value_uint64 || value_uint64 > max)
    return -1;
  if (NULL != value) {
    value_offset = (unsigned short)((sizeof(uint64_t) - size) << 8);
    memcpy(value, (unsigned char *)&value_uint64 + *((unsigned char *)&value_offset), size);
  }
  return 0;
}
```