user: 请从给定的汇编指令推导出C源代码：

```asm
<utf8_write_char>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x20,%rsp
  mov    %edi,-0x14(%rbp)
  mov    %rsi,-0x20(%rbp)
  mov    -0x20(%rbp),%rax
  mov    %rax,-0x8(%rbp)
  cmpl   $0x10ffff,-0x14(%rbp)
  jg     L75
  cmpl   $0xd7ff,-0x14(%rbp)
  jle    L85
  cmpl   $0xdfff,-0x14(%rbp)
  jle    L75
L85:
  mov    $0x1,%eax
  jmp    L78
L75:
  mov    $0x0,%eax
L78:
  mov    %eax,%edi
  call   <assert@plt>
  cmpl   $0x7f,-0x14(%rbp)
  jg     L56
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    -0x14(%rbp),%edx
  mov    %dl,(%rax)
  mov    $0x1,%eax
  jmp    L55
L56:
  cmpl   $0x7ff,-0x14(%rbp)
  jg     L35
  mov    -0x14(%rbp),%eax
  sar    $0x6,%eax
  or     $0xffffffc0,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    $0x2,%eax
  jmp    L55
L35:
  cmpl   $0xffff,-0x14(%rbp)
  jg     L70
  mov    -0x14(%rbp),%eax
  sar    $0xc,%eax
  or     $0xffffffe0,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  sar    $0x6,%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    $0x3,%eax
  jmp    L55
L70:
  mov    -0x14(%rbp),%eax
  sar    $0x12,%eax
  or     $0xfffffff0,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  sar    $0xc,%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  sar    $0x6,%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0x14(%rbp),%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  mov    %eax,%ecx
  mov    -0x8(%rbp),%rax
  lea    0x1(%rax),%rdx
  mov    %rdx,-0x8(%rbp)
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    $0x4,%eax
L55:
  leave
  ret
```

assistant: ```c
int utf8_write_char(uint32_t unicode, char *out) {
  unsigned char *o = (unsigned char *)out;
  assert(unicode <= 0x10FFFF && !(unicode >= 0xD800 && unicode <= 0xDFFF));
  if (unicode <= 0x7F) {
    *o++ = unicode;
    return 1;
  } else if (unicode <= 0x7FF) {
    *o++ = 0xC0 | unicode >> 6;
    *o++ = 0x80 | (unicode & 0x3F);
    return 2;
  } else if (unicode <= 0xFFFF) {
    *o++ = 0xE0 | unicode >> 12;
    *o++ = 0x80 | (unicode >> 6 & 0x3F);
    *o++ = 0x80 | (unicode & 0x3F);
    return 3;
  } else {
    *o++ = 0xF0 | unicode >> 18;
    *o++ = 0x80 | (unicode >> 12 & 0x3F);
    *o++ = 0x80 | (unicode >> 6 & 0x3F);
    *o++ = 0x80 | (unicode & 0x3F);
    return 4;
  }
}
```