user: 请将这段汇编代码片段转换成等效的C代码:

```asm
<_timespec_to_string>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x90,%rsp
  mov    %rdi,-0x78(%rbp)
  mov    %rsi,-0x80(%rbp)
  mov    %rdx,-0x88(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movl   $0x15180,-0x40(%rbp)
  movl   $0xe10,-0x3c(%rbp)
  movl   $0x3c,-0x38(%rbp)
  movl   $0x1,-0x34(%rbp)
  lea    D16(%rip),%rax
  mov    %rax,-0x30(%rbp)
  lea    D55(%rip),%rax
  mov    %rax,-0x28(%rbp)
  lea    D57(%rip),%rax
  mov    %rax,-0x20(%rbp)
  lea    D24(%rip),%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x78(%rbp),%rax
  mov    (%rax),%eax
  mov    %eax,-0x6c(%rbp)
  cmpl   $0x0,-0x6c(%rbp)
  jne    L70
  mov    -0x88(%rbp),%rcx
  mov    -0x80(%rbp),%rax
  lea    D33(%rip),%rdx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %rax,-0x48(%rbp)
  mov    -0x88(%rbp),%rax
  sub    -0x48(%rbp),%rax
  jmp    L60
L70:
  mov    -0x80(%rbp),%rax
  mov    %rax,-0x60(%rbp)
  mov    -0x88(%rbp),%rax
  mov    %rax,-0x58(%rbp)
  movl   $0x0,-0x68(%rbp)
  jmp    L67
L21:
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,4),%edi
  mov    -0x6c(%rbp),%eax
  cltd
  idiv   %edi
  mov    %eax,-0x64(%rbp)
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,4),%ecx
  mov    -0x6c(%rbp),%eax
  cltd
  idiv   %ecx
  mov    %edx,-0x6c(%rbp)
  cmpl   $0x0,-0x64(%rbp)
  jle    L14
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x30(%rbp,%rax,8),%rcx
  mov    -0x64(%rbp),%edx
  mov    -0x58(%rbp),%rsi
  mov    -0x60(%rbp),%rax
  mov    %rcx,%r8
  mov    %edx,%ecx
  lea    D20(%rip),%rdx
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %rax,-0x50(%rbp)
  mov    -0x50(%rbp),%rax
  sub    %rax,-0x58(%rbp)
  mov    -0x50(%rbp),%rax
  add    %rax,-0x60(%rbp)
  cmpq   $0x0,-0x58(%rbp)
  jne    L14
  mov    -0x88(%rbp),%rax
  sub    -0x58(%rbp),%rax
  jmp    L60
L14:
  addl   $0x1,-0x68(%rbp)
L67:
  mov    -0x68(%rbp),%eax
  cmp    $0x3,%eax
  jbe    L21
  mov    -0x88(%rbp),%rax
  sub    -0x58(%rbp),%rax
L60:
  mov    -0x8(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L57
  call   <__stack_chk_fail@plt>
L57:
  leave
  ret
```

tool_calls: name: read_data
arguments: data_tag: D16
type_infered: string
name: read_data
arguments: data_tag: D55
type_infered: string
name: read_data
arguments: data_tag: D57
type_infered: string
name: read_data
arguments: data_tag: D24
type_infered: string
name: read_data
arguments: data_tag: D33
type_infered: string
name: read_data
arguments: data_tag: D20
type_infered: string

tool: D16: d

tool: D55: h

tool: D57: m

tool: D24: s

tool: D33: 0s

tool: D20: %ld%s

assistant: ```c
size_t _timespec_to_string(const struct timespec *value, char *out_result, size_t result_size) {
  const time_t divisors[] = {24 * 60 * 60, 60 * 60, 60, 1};
  const char *labels[] = {"d", "h", "m", "s"};
  time_t remainder_seconds = value->tv_sec;
  if (remainder_seconds == 0) {
    size_t written = snprintf(out_result, result_size, "0s");
    return result_size - written;
  }
  char *output = out_result;
  ssize_t output_remaining = result_size;
  for (int i = 0; i < sizeof(divisors) / sizeof(divisors[0]); ++i) {
    time_t quotient = remainder_seconds / divisors[i];
    remainder_seconds %= divisors[i];
    if (quotient > 0) {
      size_t written = snprintf(output, output_remaining, "%ld%s", quotient, labels[i]);
      output_remaining -= written;
      output += written;
      if (output_remaining <= 0) {
        return result_size - output_remaining;
      }
    }
  }
  return result_size - output_remaining;
}
```