user: Converte this assembly snippet into its equivalent C code:

```asm
<hexdump>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x48,%rsp
  mov    %rsi,%r14
  mov    %rdx,0x8(%rsp)
  mov    %rcx,%r12
  mov    %fs:0x28,%rax
  mov    %rax,0x38(%rsp)
  xor    %eax,%eax
  test   %rdi,%rdi
  je     L106
  mov    %rdi,%rdx
  lea    D43(%rip),%rsi
  mov    %rcx,%rdi
  call   <fprintf@plt>
L106:
  mov    0x8(%rsp),%rax
  mov    %eax,%r13d
  test   %eax,%eax
  je     L91
  lea    -0x1(%rax),%r15d
  mov    $0x0,%ebx
  lea    0x20(%rsp),%rax
  mov    %rax,0x10(%rsp)
  mov    %r13d,0x1c(%rsp)
  jmp    L110
L15:
  mov    %r13d,%edx
  lea    D9(%rip),%rsi
  mov    %r12,%rdi
  mov    $0x0,%eax
  call   <fprintf@plt>
L108:
  movzbl (%r14,%rbx,1),%edx
  lea    D21(%rip),%rsi
  mov    %r12,%rdi
  mov    $0x0,%eax
  call   <fprintf@plt>
  movzbl (%r14,%rbx,1),%eax
  lea    -0x20(%rax),%edx
  cmp    $0x5f,%dl
  mov    $0x2e,%edx
  cmovae %edx,%eax
  mov    %ebp,%edx
  mov    %al,0x20(%rsp,%rdx,1)
  add    $0x1,%ebp
  mov    %ebp,%ebp
  movb   $0x0,0x20(%rsp,%rbp,1)
  lea    0x1(%rbx),%rax
  cmp    %rbx,%r15
  je     L48
  mov    %rax,%rbx
L110:
  mov    %ebx,%r13d
  mov    %ebx,%ebp
  and    $0xf,%ebp
  jne    L0
  test   %ebx,%ebx
  je     L15
  mov    0x10(%rsp),%rdx
  lea    D52(%rip),%rsi
  mov    %r12,%rdi
  mov    $0x0,%eax
  call   <fprintf@plt>
  jmp    L15
L0:
  test   $0x7,%bl
  jne    L108
  mov    %r12,%rsi
  mov    $0x20,%edi
  call   <fputc@plt>
  jmp    L108
L48:
  mov    0x1c(%rsp),%r13d
  mov    0x8(%rsp),%eax
  and    $0xf,%eax
  lea    -0x1(%rax),%edx
  cmp    $0x7,%edx
  jbe    L33
  test   %eax,%eax
  je     L91
L39:
  lea    D13(%rip),%rbx
L113:
  mov    %r12,%rcx
  mov    $0x3,%edx
  mov    $0x1,%esi
  mov    %rbx,%rdi
  call   <fwrite@plt>
  add    $0x1,%r13d
  test   $0xf,%r13b
  jne    L113
L91:
  lea    0x20(%rsp),%rdx
  lea    D52(%rip),%rsi
  mov    %r12,%rdi
  mov    $0x0,%eax
  call   <fprintf@plt>
  mov    0x38(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L16
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L33:
  mov    %r12,%rsi
  mov    $0x20,%edi
  call   <fputc@plt>
  jmp    L39
L16:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: parse_data
arguments: data_label: D43
datatype: string
name: parse_data
arguments: data_label: D9
datatype: string
name: parse_data
arguments: data_label: D21
datatype: string
name: parse_data
arguments: data_label: D52
datatype: string
name: parse_data
arguments: data_label: D13
datatype: string

tool: D43: %s:


tool: D9: %08x 

tool: D21:  %02x

tool: D52:   |%s|


tool: D13:    

assistant: ```c
void hexdump(const char *desc, const void *addr, size_t len, FILE *fp) {
  unsigned int i;
  unsigned char buf[17];
  const unsigned char *pc = (const unsigned char *)addr;
  if (desc != NULL)
    fprintf(fp, "%s:\n", desc);
  for (i = 0; i < (unsigned int)len; i++) {
    if ((i % 16) == 0) {
      if (i != 0)
        fprintf(fp, "  |%s|\n", buf);
      fprintf(fp, "%08x ", i);
    } else if ((i % 8) == 0) {
      fprintf(fp, " ");
    }
    fprintf(fp, " %02x", pc[i]);
    if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
      buf[i % 16] = '.';
    } else {
      buf[i % 16] = pc[i];
    }
    buf[(i % 16) + 1] = '\0';
  }
  if (i % 16 <= 8 && i % 16 != 0)
    fprintf(fp, " ");
  while ((i % 16) != 0) {
    fprintf(fp, "   ");
    i++;
  }
  fprintf(fp, "  |%s|\n", buf);
}
```