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

```asm
<fast_validate_len>:
  endbr64
  push   %rbp
  push   %rbx
  sub    $0x8,%rsp
  mov    %rdi,%rbp
  mov    %rsi,%rbx
  mov    $0x1,%edi
  call   <assert@plt>
  test   %rbx,%rbx
  je     L141
  mov    %rbp,%rdx
  mov    $0x0,%ecx
  mov    $0x10000,%esi
  mov    $0x800,%edi
  jmp    L100
L141:
  mov    %rbp,%rdx
  jmp    L63
L13:
  mov    %rbx,%r8
  sub    %rcx,%r8
  cmp    $0x1,%r8
  jbe    L63
  test   $0x1e,%al
  je     L63
  movzbl 0x1(%rdx),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  je     L185
L63:
  mov    %rdx,%rax
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  ret
L185:
  add    $0x1,%rdx
  jmp    L194
L53:
  mov    %rbx,%r8
  sub    %rcx,%r8
  cmp    $0x2,%r8
  jbe    L63
  mov    %eax,%ecx
  and    $0xf,%ecx
  mov    %rdx,%r8
  mov    %edi,%r9d
L182:
  movzbl 0x1(%r8),%eax
  mov    %eax,%r10d
  and    $0xffffffc0,%r10d
  cmp    $0x80,%r10b
  jne    L63
  shl    $0x6,%ecx
  and    $0x3f,%eax
  or     %eax,%ecx
  movzbl 0x2(%r8),%eax
  mov    %eax,%r10d
  and    $0xffffffc0,%r10d
  cmp    $0x80,%r10b
  jne    L63
  shl    $0x6,%ecx
  and    $0x3f,%eax
  or     %ecx,%eax
  cmp    $0x10ffff,%eax
  ja     L63
  cmp    %eax,%r9d
  ja     L63
  mov    %eax,%ecx
  and    $0xfffff800,%ecx
  cmp    $0xd800,%ecx
  je     L63
  lea    -0xfdd0(%rax),%ecx
  cmp    $0x1f,%ecx
  jbe    L63
  and    $0xfffe,%eax
  cmp    $0xfffe,%eax
  je     L63
  lea    0x2(%r8),%rdx
L194:
  add    $0x1,%rdx
  mov    %rdx,%rcx
  sub    %rbp,%rcx
  cmp    %rbx,%rcx
  jae    L63
L100:
  movzbl (%rdx),%eax
  test   %al,%al
  je     L63
  jns    L194
  mov    %eax,%r8d
  and    $0xffffffe0,%r8d
  cmp    $0xc0,%r8b
  je     L13
  mov    %eax,%r8d
  and    $0xfffffff0,%r8d
  cmp    $0xe0,%r8b
  je     L53
  mov    %eax,%r8d
  and    $0xfffffff8,%r8d
  cmp    $0xf0,%r8b
  jne    L63
  mov    %rbx,%r8
  sub    %rcx,%r8
  cmp    $0x3,%r8
  jbe    L63
  and    $0x7,%eax
  lea    0x1(%rdx),%r8
  movzbl 0x1(%rdx),%ecx
  mov    %ecx,%r9d
  and    $0xffffffc0,%r9d
  cmp    $0x80,%r9b
  jne    L63
  shl    $0x6,%eax
  and    $0x3f,%ecx
  or     %eax,%ecx
  mov    %esi,%r9d
  jmp    L182
```

assistant: ```c
const char *fast_validate_len(const char *str, size_t max_len) {
  unsigned int val = 0;
  unsigned int min = 0;
  const char *p;
  assert(max_len >= 0);
  for (p = str; ((size_t)(p - str) < max_len) && *p; p++) {
    if (*(unsigned char *)p < 128)
      ;
    else {
      const char *last;
      last = p;
      if ((*(unsigned char *)p & 0xe0) == 0xc0) {
        if (max_len - (p - str) < 2)
          goto error;
        if ((*(unsigned char *)p & 0x1e) == 0)
          goto error;
        p++;
        if ((*(unsigned char *)p & 0xc0) != 0x80)
          goto error;
      } else {
        if ((*(unsigned char *)p & 0xf0) == 0xe0) {
          if (max_len - (p - str) < 3)
            goto error;
          min = (1 << 11);
          val = *(unsigned char *)p & 0x0f;
          goto TWO_REMAINING;
        } else if ((*(unsigned char *)p & 0xf8) == 0xf0) {
          if (max_len - (p - str) < 4)
            goto error;
          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;
}
```