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

```asm
<json_print_string>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x20,%rsp
  mov    %rdi,-0x18(%rbp)
  mov    %rsi,-0x20(%rbp)
  mov    $0x22,%edi
  call   <putchar@plt>
  movq   $0x0,-0x8(%rbp)
  jmp    L68
L119:
  mov    -0x18(%rbp),%rdx
  mov    -0x8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  cmp    $0x2f,%eax
  jg     L124
  cmp    $0x8,%eax
  jl     L164
  sub    $0x8,%eax
  cmp    $0x27,%eax
  ja     L164
  mov    %eax,%eax
  lea    0x0(,%rax,4),%rdx
  lea    D29(%rip),%rax
  mov    (%rdx,%rax,1),%eax
  cltq
  lea    D29(%rip),%rdx
  add    %rdx,%rax
  notrack jmp *%rax
L124:
  cmp    $0x5c,%eax
  je     L95
  jmp    L164
  lea    D97(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
L95:
  lea    D49(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D36(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D79(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D26(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D30(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D64(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
  lea    D33(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
L164:
  mov    -0x18(%rbp),%rdx
  mov    -0x8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <iscntrl@plt>
  test   %eax,%eax
  je     L31
  mov    -0x18(%rbp),%rdx
  mov    -0x8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%esi
  lea    D11(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L133
L31:
  mov    -0x18(%rbp),%rdx
  mov    -0x8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <putchar@plt>
L133:
  addq   $0x1,-0x8(%rbp)
L68:
  mov    -0x8(%rbp),%rax
  cmp    -0x20(%rbp),%rax
  jb     L119
  mov    $0x22,%edi
  call   <putchar@plt>
  nop
  leave
  ret
```

tool_calls: name: parse_data
arguments: data_tag: D97
type_guessed: string
name: parse_data
arguments: data_tag: D49
type_guessed: string
name: parse_data
arguments: data_tag: D36
type_guessed: string
name: parse_data
arguments: data_tag: D79
type_guessed: string
name: parse_data
arguments: data_tag: D26
type_guessed: string
name: parse_data
arguments: data_tag: D30
type_guessed: string
name: parse_data
arguments: data_tag: D64
type_guessed: string
name: parse_data
arguments: data_tag: D33
type_guessed: string
name: parse_data
arguments: data_tag: D11
type_guessed: string

tool: D97: \"

tool: D49: \\

tool: D36: \/

tool: D79: \b

tool: D26: \f

tool: D30: \n

tool: D64: \r

tool: D33: \t

tool: D11: \u%.4u

assistant: ```c
void json_print_string(const char *str, size_t bytes) {
  size_t i;
  printf("\"");
  for (i = 0; i < bytes; ++i) {
    switch (str[i]) {
    case '\"':
      printf("\\\"");
      break;
    case '\\':
      printf("\\\\");
      break;
    case '/':
      printf("\\/");
      break;
    case '\b':
      printf("\\b");
      break;
    case '\f':
      printf("\\f");
      break;
    case '\n':
      printf("\\n");
      break;
    case '\r':
      printf("\\r");
      break;
    case '\t':
      printf("\\t");
      break;
    default:
      if (iscntrl(str[i])) {
        printf("\\u%.4u", str[i]);
      } else {
        printf("%c", str[i]);
      }
    }
  }
  printf("\"");
}
```