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

```asm
<parseUTF8char>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0x38,%rsp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x18(%rbp)
  xor    %eax,%eax
  movw   $0x0,-0x1d(%rbp)
  movw   $0x0,-0x1b(%rbp)
  movb   $0x0,-0x19(%rbp)
  movq   $0x0,-0x28(%rbp)
  mov    -0x40(%rbp),%rax
  movq   $0x0,(%rax)
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <hexDigitToValue@plt>
  shl    $0x4,%eax
  mov    %eax,%ebx
  mov    -0x38(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <hexDigitToValue@plt>
  add    %ebx,%eax
  mov    %al,-0x1d(%rbp)
  mov    -0x38(%rbp),%rax
  add    $0x2,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <hexDigitToValue@plt>
  shl    $0x4,%eax
  mov    %eax,%ebx
  mov    -0x38(%rbp),%rax
  add    $0x3,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  mov    %eax,%edi
  call   <hexDigitToValue@plt>
  add    %ebx,%eax
  mov    %al,-0x1c(%rbp)
  movzbl -0x1c(%rbp),%eax
  test   %al,%al
  js     L38
  movzbl -0x1d(%rbp),%eax
  test   %al,%al
  je     L11
L38:
  movzbl -0x1c(%rbp),%eax
  and    $0x3f,%eax
  mov    %al,-0x19(%rbp)
  movzbl -0x19(%rbp),%eax
  or     $0xffffff80,%eax
  mov    %al,-0x19(%rbp)
  movzbl -0x1c(%rbp),%eax
  shr    $0x6,%al
  mov    %al,-0x1a(%rbp)
  movzbl -0x1d(%rbp),%eax
  test   %al,%al
  je     L70
  movzbl -0x1d(%rbp),%eax
  movzbl %al,%eax
  shl    $0x2,%eax
  and    $0x3f,%eax
  mov    %al,-0x29(%rbp)
  movzbl -0x1a(%rbp),%eax
  or     -0x29(%rbp),%al
  mov    %al,-0x1a(%rbp)
  movzbl -0x1a(%rbp),%eax
  or     $0xffffff80,%eax
  mov    %al,-0x1a(%rbp)
  movzbl -0x1d(%rbp),%eax
  cmp    $0xf,%al
  jbe    L12
  movzbl -0x1d(%rbp),%eax
  shr    $0x4,%al
  mov    %al,-0x1b(%rbp)
  movzbl -0x1b(%rbp),%eax
  or     $0xffffffe0,%eax
  mov    %al,-0x1b(%rbp)
  jmp    L21
L12:
  movzbl -0x1a(%rbp),%eax
  or     $0x40,%eax
  mov    %al,-0x1a(%rbp)
  jmp    L21
L70:
  movzbl -0x1a(%rbp),%eax
  or     $0xffffffc0,%eax
  mov    %al,-0x1a(%rbp)
  jmp    L21
L11:
  movzbl -0x1c(%rbp),%eax
  mov    %al,-0x19(%rbp)
L21:
  movzbl -0x1b(%rbp),%eax
  test   %al,%al
  setne  %al
  movzbl %al,%edx
  movzbl -0x1a(%rbp),%eax
  test   %al,%al
  setne  %al
  movzbl %al,%eax
  add    %eax,%edx
  movzbl -0x19(%rbp),%eax
  test   %al,%al
  setne  %al
  movzbl %al,%eax
  add    %edx,%eax
  movslq %eax,%rdx
  mov    -0x40(%rbp),%rax
  mov    %rdx,(%rax)
  mov    -0x40(%rbp),%rax
  mov    (%rax),%rax
  test   %rax,%rax
  jne    L40
  mov    $0x0,%eax
  jmp    L57
L40:
  mov    -0x40(%rbp),%rax
  mov    (%rax),%rax
  mov    %eax,%edi
  call   <malloc@plt>
  mov    %rax,-0x28(%rbp)
  movzbl -0x1b(%rbp),%eax
  test   %al,%al
  je     L20
  movzbl -0x1b(%rbp),%eax
  mov    %eax,%edx
  mov    -0x28(%rbp),%rax
  mov    %dl,(%rax)
  movzbl -0x1a(%rbp),%edx
  mov    -0x28(%rbp),%rax
  add    $0x1,%rax
  mov    %dl,(%rax)
  movzbl -0x19(%rbp),%edx
  mov    -0x28(%rbp),%rax
  add    $0x2,%rax
  mov    %dl,(%rax)
  jmp    L96
L20:
  movzbl -0x1a(%rbp),%eax
  test   %al,%al
  je     L63
  movzbl -0x1a(%rbp),%eax
  mov    %eax,%edx
  mov    -0x28(%rbp),%rax
  mov    %dl,(%rax)
  movzbl -0x19(%rbp),%edx
  mov    -0x28(%rbp),%rax
  add    $0x1,%rax
  mov    %dl,(%rax)
  jmp    L96
L63:
  movzbl -0x19(%rbp),%eax
  mov    %eax,%edx
  mov    -0x28(%rbp),%rax
  mov    %dl,(%rax)
L96:
  mov    -0x28(%rbp),%rax
L57:
  mov    -0x18(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L111
  call   <__stack_chk_fail@plt>
L111:
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

assistant: ```c
char *parseUTF8char(const char *str, size_t *len) {
  unsigned char plane[2] = {0, 0};
  unsigned char utf8Value[3] = {0, 0, 0};
  char *utf8char = NULL;
  *len = 0;
  plane[0] = hexDigitToValue(str[0]) * 16 + hexDigitToValue(str[1]);
  plane[1] = hexDigitToValue(str[2]) * 16 + hexDigitToValue(str[3]);
  if (plane[1] > 127 || plane[0] != 0) {
    utf8Value[2] = plane[1] & 63;
    utf8Value[2] |= 128;
    utf8Value[1] = plane[1] >> 6;
    if (plane[0] != 0) {
      unsigned char tmp = (plane[0] << 2) & 63;
      utf8Value[1] |= tmp;
      utf8Value[1] |= 128;
      if (plane[0] > 15) {
        utf8Value[0] = plane[0] >> 4;
        utf8Value[0] |= 224;
      } else {
        utf8Value[1] |= 64;
      }
    } else {
      utf8Value[1] |= 192;
    }
  } else {
    utf8Value[2] = plane[1];
  }
  *len = (utf8Value[0] != 0) + (utf8Value[1] != 0) + (utf8Value[2] != 0);
  if (*len == 0) {
    return NULL;
  }
  utf8char = malloc(sizeof(char) * *len);
  if (utf8Value[0] != 0) {
    utf8char[0] = utf8Value[0];
    utf8char[1] = utf8Value[1];
    utf8char[2] = utf8Value[2];
  } else if (utf8Value[1] != 0) {
    utf8char[0] = utf8Value[1];
    utf8char[1] = utf8Value[2];
  } else {
    utf8char[0] = utf8Value[2];
  }
  return utf8char;
}
```