user: Please show me the C implementation that matches the assembly code listed below:

```asm
<hex_dump>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x20,%rsp
  mov    %rdi,-0x18(%rbp)
  mov    %esi,-0x1c(%rbp)
  movl   $0x0,-0x4(%rbp)
  jmp    L24
L76:
  mov    -0x4(%rbp),%eax
  mov    %eax,%esi
  lea    D12(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L212
L183:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%esi
  lea    D6(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
L212:
  cmpl   $0x7,-0x8(%rbp)
  jle    L183
  mov    $0x20,%edi
  call   <putchar@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L148
L127:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%esi
  lea    D6(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
L148:
  cmpl   $0x7,-0x8(%rbp)
  jle    L127
  subq   $0x10,-0x18(%rbp)
  mov    $0x7c,%edi
  call   <putchar@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L252
L33:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%edi
  call   <isprint@plt>
  test   %rax,%rax
  je     L128
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%edi
  call   <putchar@plt>
  jmp    L12
L128:
  mov    $0x2e,%edi
  call   <putchar@plt>
L12:
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
L252:
  cmpl   $0xf,-0x8(%rbp)
  jle    L33
  lea    D69(%rip),%rax
  mov    %rax,%rdi
  call   <puts@plt>
  addl   $0x10,-0x4(%rbp)
  subl   $0x10,-0x1c(%rbp)
L24:
  cmpl   $0xf,-0x1c(%rbp)
  jg     L76
  cmpl   $0x0,-0x1c(%rbp)
  jle    L55
  mov    -0x4(%rbp),%eax
  mov    %eax,%esi
  lea    D12(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L94
L164:
  cmpl   $0x0,-0x1c(%rbp)
  jle    L215
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%esi
  lea    D6(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L87
L215:
  lea    D36(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
L87:
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
  subl   $0x1,-0x1c(%rbp)
L94:
  cmpl   $0x7,-0x8(%rbp)
  jle    L164
  mov    $0x20,%edi
  call   <putchar@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L85
L97:
  cmpl   $0x0,-0x1c(%rbp)
  jle    L191
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%esi
  lea    D6(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L18
L191:
  lea    D36(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
L18:
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
  subl   $0x1,-0x1c(%rbp)
L85:
  cmpl   $0x7,-0x8(%rbp)
  jle    L97
  subq   $0x10,-0x18(%rbp)
  addl   $0x10,-0x1c(%rbp)
  mov    $0x7c,%edi
  call   <putchar@plt>
  movl   $0x0,-0x8(%rbp)
  jmp    L120
L178:
  cmpl   $0x0,-0x1c(%rbp)
  jg     L37
  mov    $0x20,%edi
  call   <putchar@plt>
  jmp    L176
L37:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%edi
  call   <isprint@plt>
  test   %rax,%rax
  je     L38
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %eax,%edi
  call   <putchar@plt>
  jmp    L176
L38:
  mov    $0x2e,%edi
  call   <putchar@plt>
L176:
  addl   $0x1,-0x8(%rbp)
  addq   $0x1,-0x18(%rbp)
  subl   $0x1,-0x1c(%rbp)
L120:
  cmpl   $0xf,-0x8(%rbp)
  jle    L178
  lea    D69(%rip),%rax
  mov    %rax,%rdi
  call   <puts@plt>
  jmp    L242
L55:
  nop
L242:
  leave
  ret
```

tool_calls: name: read_data
arguments: tag: D12
type: string
name: read_data
arguments: tag: D6
type: string
name: read_data
arguments: tag: D69
type: string
name: read_data
arguments: tag: D36
type: string

tool: D12: $%04x: 

tool: D6: %02x 

tool: D69: |

tool: D36:    

assistant: ```c
void hex_dump(const unsigned char *data, int size) {
  int i;
  unsigned int offset = 0;
  for (; size >= 8 << 1; size -= 8 << 1) {
    printf("$%04x:"
           " ",
           offset);
    for (i = 0; i < 8; i++, data++)
      printf("%02x"
             " ",
             *data);
    putchar(' ');
    for (i = 0; i < 8; i++, data++)
      printf("%02x"
             " ",
             *data);
    data -= 8 << 1;
    putchar('|');
    for (i = 0; i < 8 << 1; i++, data++) {
      if (isprint(*data))
        putchar(*data);
      else
        putchar('.');
    }
    printf("|\n");
    offset += 8 << 1;
  }
  if (size <= 0)
    return;
  printf("$%04x:"
         " ",
         offset);
  for (i = 0; i < 8; i++, data++, size--) {
    if (size > 0)
      printf("%02x"
             " ",
             *data);
    else
      printf("  "
             " ");
  }
  putchar(' ');
  for (i = 0; i < 8; i++, data++, size--) {
    if (size > 0)
      printf("%02x"
             " ",
             *data);
    else
      printf("  "
             " ");
  }
  data -= 8 << 1;
  size += 8 << 1;
  putchar('|');
  for (i = 0; i < 8 << 1; i++, data++, size--) {
    if (size <= 0) {
      putchar(' ');
      continue;
    }
    if (isprint(*data))
      putchar(*data);
    else
      putchar('.');
  }
  printf("|\n");
}
```