user: 下面的汇编指令对应的C源代码是什么：

```asm
<fast_validate>:
  endbr64
  movzbl (%rdi),%eax
  mov    %rdi,%r8
  test   %al,%al
  jne    L153
  jmp    L18
  nopl   0x0(%rax,%rax,1)
L44:
  movzbl 0x1(%rdx),%eax
  lea    0x1(%rdx),%r8
  test   %al,%al
  je     L18
L153:
  mov    %r8,%rdx
  test   %al,%al
  jns    L44
  mov    %eax,%ecx
  and    $0xffffffe0,%ecx
  cmp    $0xc0,%cl
  je     L85
  mov    %eax,%edx
  and    $0xfffffff0,%edx
  cmp    $0xe0,%dl
  je     L35
  mov    %eax,%edx
  and    $0xfffffff8,%edx
  cmp    $0xf0,%dl
  jne    L18
  movzbl 0x1(%r8),%ecx
  and    $0x7,%eax
  lea    0x1(%r8),%rdx
  mov    %ecx,%esi
  and    $0xffffffc0,%esi
  cmp    $0x80,%sil
  jne    L18
  shl    $0x6,%eax
  and    $0x3f,%ecx
  mov    $0x10000,%edi
  or     %eax,%ecx
L51:
  movzbl 0x1(%rdx),%eax
  mov    %eax,%esi
  and    $0xffffffc0,%esi
  cmp    $0x80,%sil
  jne    L18
  and    $0x3f,%eax
  shl    $0x6,%ecx
  or     %eax,%ecx
  movzbl 0x2(%rdx),%eax
  mov    %eax,%esi
  and    $0xffffffc0,%esi
  cmp    $0x80,%sil
  jne    L18
  shl    $0x6,%ecx
  and    $0x3f,%eax
  or     %ecx,%eax
  cmp    $0x10ffff,%eax
  ja     L18
  cmp    %eax,%edi
  ja     L18
  mov    %eax,%ecx
  and    $0xfffff800,%ecx
  cmp    $0xd800,%ecx
  je     L18
  lea    -0xfdd0(%rax),%ecx
  cmp    $0x1f,%ecx
  jbe    L18
  and    $0xfffe,%eax
  cmp    $0xfffe,%eax
  je     L18
  add    $0x2,%rdx
  jmp    L44
  nopw   0x0(%rax,%rax,1)
L85:
  test   $0x1e,%al
  je     L18
  movzbl 0x1(%r8),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  je     L157
L18:
  mov    %r8,%rax
  ret
  nopl   0x0(%rax)
L157:
  add    $0x1,%rdx
  jmp    L44
  nopl   0x0(%rax)
L35:
  mov    %eax,%ecx
  mov    %r8,%rdx
  mov    $0x800,%edi
  and    $0xf,%ecx
  jmp    L51
```

assistant: ```c
const char *fast_validate(const char *str) {
  unsigned int val = 0;
  unsigned int min = 0;
  const char *p;
  for (p = str; *p; p++) {
    if (*(unsigned char *)p < 128)
      ;
    else {
      const char *last;
      last = p;
      if ((*(unsigned char *)p & 0xe0) == 0xc0) {
        if ((*(unsigned char *)p & 0x1e) == 0)
          goto error;
        p++;
        if ((*(unsigned char *)p & 0xc0) != 0x80)
          goto error;
      } else {
        if ((*(unsigned char *)p & 0xf0) == 0xe0) {
          min = (1 << 11);
          val = *(unsigned char *)p & 0x0f;
          goto TWO_REMAINING;
        } else if ((*(unsigned char *)p & 0xf8) == 0xf0) {
          min = (1 << 16);
          val = *(unsigned char *)p & 0x07;
        } else
          goto error;
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
      TWO_REMAINING:
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
        if (val < min)
          goto error;
        if (!((val) < 0x110000 && (((val)&0xFFFFF800) != 0xD800) && ((val) < 0xFDD0 || (val) > 0xFDEF) && ((val)&0xFFFE) != 0xFFFE))
          goto error;
      }
      continue;
    error:
      return last;
    }
  }
  return p;
}
```