user: What is the c source code of the assembly code below:

```asm
<ns_hexdump>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x60,%rsp
  mov    %rdi,-0x48(%rbp)
  mov    %esi,-0x4c(%rbp)
  mov    %rdx,-0x58(%rbp)
  mov    %ecx,-0x50(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  mov    -0x48(%rbp),%rax
  mov    %rax,-0x28(%rbp)
  movq   $0x0,-0x20(%rbp)
  movq   $0x0,-0x18(%rbp)
  movb   $0x0,-0x10(%rbp)
  movl   $0x0,-0x30(%rbp)
  movl   $0x0,-0x34(%rbp)
  jmp    L96
L7:
  mov    -0x34(%rbp),%eax
  cltd
  shr    $0x1c,%edx
  add    %edx,%eax
  and    $0xf,%eax
  sub    %edx,%eax
  mov    %eax,-0x2c(%rbp)
  cmpl   $0x0,-0x2c(%rbp)
  jne    L55
  cmpl   $0x0,-0x34(%rbp)
  jle    L15
  mov    -0x50(%rbp),%eax
  sub    -0x30(%rbp),%eax
  mov    -0x30(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x58(%rbp),%rdx
  lea    (%rcx,%rdx,1),%rdi
  lea    -0x20(%rbp),%rdx
  mov    %rdx,%rcx
  lea    D51(%rip),%rdx
  mov    %eax,%esi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %eax,%edx
  mov    -0x30(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x30(%rbp)
L15:
  mov    -0x50(%rbp),%eax
  sub    -0x30(%rbp),%eax
  mov    -0x30(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x58(%rbp),%rdx
  lea    (%rcx,%rdx,1),%rdi
  mov    -0x34(%rbp),%edx
  mov    %edx,%ecx
  lea    D3(%rip),%rdx
  mov    %eax,%esi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %eax,%edx
  mov    -0x30(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x30(%rbp)
L55:
  mov    -0x34(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%edx
  mov    -0x50(%rbp),%eax
  sub    -0x30(%rbp),%eax
  mov    -0x30(%rbp),%ecx
  movslq %ecx,%rsi
  mov    -0x58(%rbp),%rcx
  lea    (%rsi,%rcx,1),%rdi
  mov    %edx,%ecx
  lea    D35(%rip),%rdx
  mov    %eax,%esi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %eax,%edx
  mov    -0x30(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x30(%rbp)
  mov    -0x34(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  cmp    $0x1f,%al
  jbe    L8
  mov    -0x34(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  cmp    $0x7e,%al
  ja     L8
  mov    -0x34(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %eax,%edx
  jmp    L2
L8:
  mov    $0x2e,%edx
L2:
  mov    -0x2c(%rbp),%eax
  cltq
  mov    %dl,-0x20(%rbp,%rax,1)
  mov    -0x2c(%rbp),%eax
  add    $0x1,%eax
  cltq
  movb   $0x0,-0x20(%rbp,%rax,1)
  addl   $0x1,-0x34(%rbp)
L96:
  mov    -0x34(%rbp),%eax
  cmp    -0x4c(%rbp),%eax
  jl     L7
  jmp    L47
L87:
  mov    -0x50(%rbp),%eax
  sub    -0x30(%rbp),%eax
  mov    -0x30(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x58(%rbp),%rdx
  lea    (%rcx,%rdx,1),%rdi
  lea    D49(%rip),%rdx
  mov    %rdx,%rcx
  lea    D34(%rip),%rdx
  mov    %eax,%esi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %eax,%edx
  mov    -0x30(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x30(%rbp)
L47:
  mov    -0x34(%rbp),%eax
  lea    0x1(%rax),%edx
  mov    %edx,-0x34(%rbp)
  and    $0xf,%eax
  test   %eax,%eax
  jne    L87
  mov    -0x50(%rbp),%eax
  sub    -0x30(%rbp),%eax
  mov    -0x30(%rbp),%edx
  movslq %edx,%rcx
  mov    -0x58(%rbp),%rdx
  lea    (%rcx,%rdx,1),%rdi
  lea    -0x20(%rbp),%rdx
  mov    %rdx,%rcx
  lea    D5(%rip),%rdx
  mov    %eax,%esi
  mov    $0x0,%eax
  call   <snprintf@plt>
  mov    %eax,%edx
  mov    -0x30(%rbp),%eax
  add    %edx,%eax
  mov    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  mov    -0x8(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L68
  call   <__stack_chk_fail@plt>
L68:
  leave
  ret
```

tool_calls: name: extract_symbolic_data
arguments: tag: D51
type: string
name: extract_symbolic_data
arguments: tag: D3
type: string
name: extract_symbolic_data
arguments: tag: D35
type: string
name: extract_symbolic_data
arguments: tag: D49
type: string
name: extract_symbolic_data
arguments: tag: D34
type: string
name: extract_symbolic_data
arguments: tag: D5
type: string

tool: D51:   %s


tool: D3: %04x 

tool: D35:  %02x

tool: D49:    

tool: D34: %s

tool: D5:   %s



assistant: ```c
int ns_hexdump(const void *buf, int len, char *dst, int dst_len) {
  const unsigned char *p = (const unsigned char *)buf;
  char ascii[17] = "";
  int i, idx, n = 0;
  for (i = 0; i < len; i++) {
    idx = i % 16;
    if (idx == 0) {
      if (i > 0)
        n += snprintf(dst + n, dst_len - n, "  %s\n", ascii);
      n += snprintf(dst + n, dst_len - n, "%04x ", i);
    }
    n += snprintf(dst + n, dst_len - n, " %02x", p[i]);
    ascii[idx] = p[i] < 0x20 || p[i] > 0x7e ? '.' : p[i];
    ascii[idx + 1] = '\0';
  }
  while (i++ % 16)
    n += snprintf(dst + n, dst_len - n, "%s", "   ");
  n += snprintf(dst + n, dst_len - n, "  %s\n\n", ascii);
  return n;
}
```