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

```asm
<print_string>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x40,%rsp
  mov    %rdi,-0x28(%rbp)
  mov    %rsi,-0x30(%rbp)
  mov    %edx,-0x34(%rbp)
  cmpl   $0x0,-0x34(%rbp)
  jns    L127
  mov    -0x30(%rbp),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  cltq
  jmp    L98
L127:
  mov    -0x34(%rbp),%eax
  cltq
L98:
  mov    -0x30(%rbp),%rdx
  add    %rdx,%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x30(%rbp),%rax
  mov    %rax,-0x18(%rbp)
  jmp    L139
L76:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  sub    $0x7,%eax
  cmp    $0x1b,%eax
  ja     L92
  mov    %eax,%eax
  lea    0x0(,%rax,4),%rdx
  lea    D17(%rip),%rax
  mov    (%rdx,%rax,1),%eax
  cltq
  lea    D17(%rip),%rdx
  add    %rdx,%rax
  notrack jmp *%rax
  lea    D110(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D89(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D87(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D41(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D4(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D109(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D20(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
  lea    D60(%rip),%rax
  mov    %rax,-0x10(%rbp)
  jmp    L42
L92:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <isprint@plt>
  test   %eax,%eax
  je     L66
  lea    D39(%rip),%rax
  jmp    L3
L66:
  lea    D52(%rip),%rax
L3:
  mov    %rax,-0x10(%rbp)
  nop
L42:
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  movzbl %al,%edx
  mov    -0x10(%rbp),%rcx
  mov    -0x28(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <fprintf@plt>
  addq   $0x1,-0x18(%rbp)
L139:
  mov    -0x18(%rbp),%rax
  cmp    -0x8(%rbp),%rax
  jb     L76
  nop
  nop
  leave
  ret
```

tool_calls: name: read_data
arguments: data_label: D110
data_type: string
name: read_data
arguments: data_label: D89
data_type: string
name: read_data
arguments: data_label: D87
data_type: string
name: read_data
arguments: data_label: D41
data_type: string
name: read_data
arguments: data_label: D4
data_type: string
name: read_data
arguments: data_label: D109
data_type: string
name: read_data
arguments: data_label: D20
data_type: string
name: read_data
arguments: data_label: D60
data_type: string
name: read_data
arguments: data_label: D39
data_type: string
name: read_data
arguments: data_label: D52
data_type: string

tool: D110: \a

tool: D89: \b

tool: D87: \f

tool: D41: \n

tool: D4: \r

tool: D109: \t

tool: D20: \v

tool: D60: \"

tool: D39: %c

tool: D52: \x%02x

assistant: ```c
void print_string(FILE *file, const char *s, int len) {
  const char *end = s + (len < 0 ? (int)strlen(s) : len);
  const char *p;
  for (p = s; p < end; ++p) {
    const char *format;
    switch (*p) {
    case '\a':
      format = "\\a";
      break;
    case '\b':
      format = "\\b";
      break;
    case '\f':
      format = "\\f";
      break;
    case '\n':
      format = "\\n";
      break;
    case '\r':
      format = "\\r";
      break;
    case '\t':
      format = "\\t";
      break;
    case '\v':
      format = "\\v";
      break;
    case '\"':
      format = "\\\"";
      break;
    default:
      format = isprint(*p) ? "%c" : "\\x%02x";
      break;
    }
    fprintf(file, format, ((unsigned)*p) & 0xff);
  }
}
```