user: 请将以下的汇编代码转换成C语言代码：

```asm
<utf8_to_latin1>:
  endbr64
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  mov    %rsi,%rbp
  mov    (%rsi),%esi
  cmp    $0x2,%esi
  jle    L121
  mov    %rdi,%rbx
  sub    $0x3,%esi
  test   %esi,%esi
  jle    L173
  mov    $0x0,%r14d
  mov    $0x0,%r13d
  mov    $0x0,%edx
  jmp    L191
L45:
  add    $0x1,%r14d
L32:
  add    $0x1,%edx
  movslq %edx,%rax
L78:
  mov    %eax,%edx
  movzbl (%rbx,%rax,1),%ecx
  add    $0x1,%rax
  test   %cl,%cl
  js     L78
L91:
  add    $0x1,%edx
  cmp    %esi,%edx
  jge    L138
L191:
  movslq %edx,%rax
  cmpb   $0x0,(%rbx,%rax,1)
  jns    L91
  cmpb   $0x0,0x1(%rbx,%rax,1)
  js     L45
  add    $0x1,%r13d
  jmp    L32
L138:
  mov    %r14d,%edx
  mov    %r13d,%esi
  lea    D47(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    $0x0,%r12d
  cmp    %r14d,%r13d
  jg     L120
L199:
  lea    D28(%rip),%rdi
  call   <puts@plt>
  mov    0x0(%rbp),%edi
  call   <malloc@plt>
  mov    %rax,%r12
  movslq 0x0(%rbp),%rsi
  add    %rbx,%rsi
  cmp    %rsi,%rbx
  jae    L119
  lea    0x1(%rax),%rdx
  mov    %rbx,%rcx
  mov    $0x3f,%edi
  jmp    L194
L183:
  add    $0x1,%rcx
  mov    %rdx,%r13
L39:
  mov    %al,-0x1(%rdx)
  movslq 0x0(%rbp),%rsi
  add    %rbx,%rsi
  add    $0x1,%rdx
  cmp    %rsi,%rcx
  jae    L64
L194:
  lea    -0x1(%rdx),%r8
  movzbl (%rcx),%eax
  test   %al,%al
  jns    L183
  cmp    $0xe0,%al
  ja     L155
  lea    0x1(%rcx),%r9
  cmp    %r9,%rsi
  jbe    L86
  shl    $0x6,%eax
  and    $0x7c0,%eax
  movzbl 0x1(%rcx),%esi
  and    $0x3f,%esi
  or     %esi,%eax
  mov    %rdx,%r13
  cmp    $0x100,%eax
  cmovge %edi,%eax
  add    $0x2,%rcx
  jmp    L39
L155:
  mov    %rdx,%r13
  add    $0x1,%rcx
  mov    %edi,%eax
  jmp    L39
L86:
  lea    0x1(%r8),%r13
  movb   $0x3f,(%r8)
L64:
  mov    0x0(%rbp),%esi
  lea    D27(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  sub    %r12,%r13
  mov    %r13d,%esi
  mov    %r13d,0x0(%rbp)
  lea    D48(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
L120:
  mov    %r12,%rax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
L119:
  mov    %rax,%r13
  jmp    L64
L121:
  mov    $0x0,%r12d
  jmp    L120
L173:
  mov    $0x0,%edx
  mov    $0x0,%esi
  lea    D47(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  jmp    L199
```

tool_calls: name: unpack_data
arguments: data_label: D47
datatype: string
name: unpack_data
arguments: data_label: D28
datatype: string
name: unpack_data
arguments: data_label: D27
datatype: string
name: unpack_data
arguments: data_label: D48
datatype: string

tool: D47: singlebyte %d multibyte %d


tool: D28: converting utf-8 -> latin1

tool: D27: previous length %d


tool: D48: new length %d


assistant: ```c
unsigned char *utf8_to_latin1(unsigned char *text, int *length) {
  int i;
  int singlebyte = 0;
  int multibyte = 0;
  if (*length < 3)
    return NULL;
  for (i = 0; i < *length - 3; i++) {
    if (text[i] >= 128) {
      if (text[i + 1] < 128)
        singlebyte++;
      else
        multibyte++;
      while (text[i] >= 128)
        i++;
    }
  }
  printf("singlebyte %d multibyte %d\n", singlebyte, multibyte);
  if (singlebyte > multibyte)
    return NULL;
  printf("converting utf-8 -> latin1\n");
  unsigned char *convtext = malloc(*length);
  unsigned char *cc = convtext;
  unsigned char *tt = text;
  int ch;
  while (tt < text + *length) {
    if (*tt < 128) {
      *cc++ = *tt++;
      continue;
    }
    if (*tt > 0xe0) {
      *cc++ = '?';
      tt++;
      continue;
    }
    if (tt + 1 >= text + *length) {
      *cc++ = '?';
      break;
    }
    ch = ((tt[0] & 0x1f) << 6) | (tt[1] & 0x3f);
    if (ch > 255) {
      *cc++ = '?';
    } else
      *cc++ = ch;
    tt += 2;
  }
  printf("previous length %d\n", *length);
  *length = cc - convtext;
  printf("new length %d\n", *length);
  return convtext;
}
```