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

```asm
<crack_datetime>:
  endbr64
  push   %r15
  mov    %r8,%r15
  push   %r14
  mov    %rcx,%r14
  push   %r13
  mov    %rsi,%r13
  push   %r12
  mov    %rdx,%r12
  push   %rbp
  push   %rbx
  mov    %r9,%rbx
  sub    $0x38,%rsp
  mov    %rdi,0x8(%rsp)
  mov    0x78(%rsp),%rdx
  lea    0x20(%rsp),%rsi
  lea    0x18(%rsp),%rdi
  mov    0x70(%rsp),%rbp
  mov    %fs:0x28,%rax
  mov    %rax,0x28(%rsp)
  xor    %eax,%eax
  call   <get_datetime@plt>
  mov    0x8(%rsp),%r10
  test   %r10,%r10
  je     L9
  movabs $0x28f5c28f5c28f5c3,%rsi
  mov    0x18(%rsp),%rcx
  mov    %rcx,%rdx
  shr    $0x2,%rdx
  mov    %rdx,%rax
  mul    %rsi
  mov    %rdx,%rax
  and    $0xfffffffffffffffc,%rdx
  shr    $0x2,%rax
  add    %rax,%rdx
  mov    %rcx,%rax
  lea    (%rdx,%rdx,4),%rdx
  shl    $0x2,%rdx
  sub    %rdx,%rax
  cmp    $0x51,%rax
  sbb    %edx,%edx
  and    $0x64,%edx
  lea    0x76c(%rdx,%rax,1),%eax
  mov    %eax,(%r10)
L9:
  test   %r13,%r13
  je     L41
  movabs $0x28f5c28f5c28f5c3,%rsi
  mov    0x18(%rsp),%rdx
  shr    $0x2,%rdx
  mov    %rdx,%rax
  mul    %rsi
  mov    %rdx,%rcx
  shr    $0x4,%rdx
  mov    %rdx,%rax
  shr    $0x2,%rcx
  mul    %rsi
  mov    %rdx,%rax
  and    $0xfffffffffffffffc,%rdx
  shr    $0x2,%rax
  add    %rax,%rdx
  lea    (%rdx,%rdx,4),%rax
  shl    $0x2,%rax
  sub    %rax,%rcx
  mov    %rcx,0x0(%r13)
L41:
  test   %r12,%r12
  je     L4
  movabs $0x346dc5d63886594b,%rdx
  mov    %rdx,%rax
  mulq   0x18(%rsp)
  shr    $0xb,%rdx
  mov    %rdx,(%r12)
L4:
  test   %r14,%r14
  je     L59
  movabs $0x431bde82d7b634db,%rdx
  mov    %rdx,%rax
  mulq   0x20(%rsp)
  shr    $0x12,%rdx
  mov    %rdx,(%r14)
L59:
  test   %r15,%r15
  je     L25
  movabs $0x346dc5d63886594b,%rdx
  movabs $0x28f5c28f5c28f5c3,%rsi
  mov    %rdx,%rax
  mulq   0x20(%rsp)
  mov    %rdx,%rcx
  shr    $0xd,%rdx
  mov    %rdx,%rax
  shr    $0xb,%rcx
  mul    %rsi
  mov    %rdx,%rax
  and    $0xfffffffffffffffc,%rdx
  shr    $0x2,%rax
  add    %rax,%rdx
  lea    (%rdx,%rdx,4),%rax
  shl    $0x2,%rax
  sub    %rax,%rcx
  mov    %rcx,(%r15)
L25:
  test   %rbx,%rbx
  je     L64
  movabs $0x28f5c28f5c28f5c3,%rsi
  mov    0x20(%rsp),%rdx
  shr    $0x2,%rdx
  mov    %rdx,%rax
  mul    %rsi
  mov    %rdx,%rcx
  shr    $0x4,%rdx
  mov    %rdx,%rax
  shr    $0x2,%rcx
  mul    %rsi
  mov    %rdx,%rax
  and    $0xfffffffffffffffc,%rdx
  shr    $0x2,%rax
  add    %rax,%rdx
  lea    (%rdx,%rdx,4),%rax
  shl    $0x2,%rax
  sub    %rax,%rcx
  mov    %rcx,(%rbx)
L64:
  test   %rbp,%rbp
  je     L27
  movabs $0x28f5c28f5c28f5c3,%rsi
  mov    0x20(%rsp),%rcx
  mov    %rcx,%rdx
  shr    $0x2,%rdx
  mov    %rdx,%rax
  mul    %rsi
  mov    %rdx,%rax
  and    $0xfffffffffffffffc,%rdx
  shr    $0x2,%rax
  add    %rax,%rdx
  lea    (%rdx,%rdx,4),%rax
  shl    $0x2,%rax
  sub    %rax,%rcx
  mov    %rcx,0x0(%rbp)
L27:
  mov    0x28(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L31
  add    $0x38,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L31:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
void crack_datetime(int *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *hundredths, unsigned long *age) {
  unsigned long date, time;
  get_datetime(&date, &time, age);
  if (year) {
    *year = date % 100;
    *year += *year > 80 ? 1900 : 2000;
  }
  if (month)
    *month = (date / 100) % 100;
  if (day)
    *day = date / 10000;
  if (hour)
    *hour = time / 1000000;
  if (minute)
    *minute = (time / 10000) % 100;
  if (second)
    *second = (time / 100) % 100;
  if (hundredths)
    *hundredths = time % 100;
}
```