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

```asm
<UTF2Lat>:
  endbr64
  push   %r15
  movslq %edx,%rax
  mov    %rdi,%r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x18,%rsp
  mov    %rax,0x8(%rsp)
  test   %eax,%eax
  jle    L160
  mov    %rdi,%r13
  mov    %rsi,%r12
  mov    %rax,%rbp
  mov    %rsi,%r14
  xor    %ebx,%ebx
  jmp    L196
  nopl   (%rax)
L193:
  and    $0xffffffe0,%eax
  cmp    $0xc0,%al
  jne    L395
  movzbl 0x1(%r14),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  je     L278
L395:
  call   <tolower@plt>
  add    $0x1,%r14
  mov    %al,(%r15)
  test   %al,%al
  je     L13
L374:
  movzbl %al,%edi
  call   <filtre@plt>
  test   %rax,%rax
  je     L13
  add    $0x1,%r15
  lea    0x0(%rbp,%r13,1),%eax
  mov    %r14,%rbx
  sub    %r15d,%eax
  sub    %r12,%rbx
  test   %eax,%eax
  jle    L294
  cmp    0x8(%rsp),%rbx
  jge    L294
L196:
  movzbl (%r14),%eax
  test   %al,%al
  je     L294
  mov    %eax,%esi
  movzbl %al,%edi
  and    $0xfffffff0,%esi
  cmp    $0xe0,%sil
  jne    L193
  movzbl 0x1(%r14),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  jne    L395
  movzbl 0x2(%r14),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  jne    L395
  movb   $0x0,(%r15)
  cmpb   $0xe2,(%r14)
  je     L209
L13:
  movb   $0x0,(%r15)
  add    $0x18,%rsp
  mov    %ebx,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  xchg   %ax,%ax
L278:
  movb   $0x0,(%r15)
  movzbl (%r14),%eax
  add    $0x3e,%eax
  cmp    $0x9,%al
  ja     L13
  lea    D24(%rip),%rcx
  movzbl %al,%eax
  movslq (%rcx,%rax,4),%rax
  add    %rcx,%rax
  notrack jmp *%rax
  nopl   0x0(%rax,%rax,1)
L294:
  mov    %ebx,%eax
L54:
  movb   $0x0,(%r15)
  add    $0x18,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   (%rax)
  movzbl 0x1(%r14),%eax
  cmp    $0x86,%al
  je     L348
  cmp    $0x9c,%al
  jne    L13
  movb   $0x98,(%r15)
  add    $0x2,%r14
  mov    $0xffffff98,%eax
  jmp    L374
  nopl   0x0(%rax,%rax,1)
  cmpb   $0x92,0x1(%r14)
  jne    L13
  movb   $0x83,(%r15)
  add    $0x2,%r14
  mov    $0xffffff83,%eax
  jmp    L374
  nopl   (%rax)
  movzbl 0x1(%r14),%eax
  and    $0x3f,%eax
  or     $0xffffff80,%eax
  cmp    $0xa0,%al
  je     L545
  mov    %al,(%r15)
  add    $0x2,%r14
  jmp    L374
  nopw   0x0(%rax,%rax,1)
  movzbl 0x1(%r14),%eax
  add    $0x6e,%eax
  cmp    $0x2c,%al
  ja     L13
  lea    D9(%rip),%rdx
  movzbl %al,%eax
  movslq (%rdx,%rax,4),%rax
  add    %rdx,%rax
  notrack jmp *%rax
  nopl   0x0(%rax)
  movzbl 0x1(%r14),%eax
  cmp    $0xb3,%al
  je     L558
  or     $0xffffffc0,%eax
  add    $0x2,%r14
  mov    %al,(%r15)
  jmp    L374
L209:
  movzbl 0x1(%r14),%esi
  cmp    $0x82,%sil
  je     L526
  cmp    $0x84,%sil
  je     L567
  cmp    $0x80,%sil
  jne    L13
  movzbl 0x2(%r14),%eax
  add    $0x6d,%eax
  cmp    $0x27,%al
  ja     L13
  lea    D5(%rip),%rdx
  movzbl %al,%eax
  movslq (%rdx,%rax,4),%rax
  add    %rdx,%rax
  notrack jmp *%rax
L545:
  movb   $0x20,(%r15)
  add    $0x2,%r14
  mov    $0x20,%eax
  jmp    L374
L558:
  movb   $0xa2,(%r15)
  add    $0x2,%r14
  mov    $0xffffffa2,%eax
  jmp    L374
L348:
  movb   $0x88,(%r15)
  add    $0x2,%r14
  mov    $0xffffff88,%eax
  jmp    L374
  movb   $0x9e,(%r15)
  add    $0x2,%r14
  mov    $0xffffff9e,%eax
  jmp    L374
  movb   $0x8f,(%r15)
  add    $0x2,%r14
  mov    $0xffffff8f,%eax
  jmp    L374
  movb   $0x9a,(%r15)
  add    $0x2,%r14
  mov    $0xffffff9a,%eax
  jmp    L374
  movb   $0x8a,(%r15)
  add    $0x2,%r14
  mov    $0xffffff8a,%eax
  jmp    L374
  movb   $0x9c,(%r15)
  add    $0x2,%r14
  mov    $0xffffff9c,%eax
  jmp    L374
  movb   $0x8c,(%r15)
  add    $0x2,%r14
  mov    $0xffffff8c,%eax
  jmp    L374
  movb   $0x8e,(%r15)
  add    $0x2,%r14
  mov    $0xffffff8e,%eax
  jmp    L374
  movb   $0x9b,(%r15)
  add    $0x3,%r14
  mov    $0xffffff9b,%eax
  jmp    L374
  movb   $0x8b,(%r15)
  add    $0x3,%r14
  mov    $0xffffff8b,%eax
  jmp    L374
  movb   $0x89,(%r15)
  add    $0x3,%r14
  mov    $0xffffff89,%eax
  jmp    L374
  movb   $0x85,(%r15)
  add    $0x3,%r14
  mov    $0xffffff85,%eax
  jmp    L374
  movb   $0x95,(%r15)
  add    $0x3,%r14
  mov    $0xffffff95,%eax
  jmp    L374
  movb   $0x87,(%r15)
  add    $0x3,%r14
  mov    $0xffffff87,%eax
  jmp    L374
  movb   $0x86,(%r15)
  add    $0x3,%r14
  mov    $0xffffff86,%eax
  jmp    L374
  movb   $0x84,(%r15)
  add    $0x3,%r14
  mov    $0xffffff84,%eax
  jmp    L374
  movb   $0x94,(%r15)
  add    $0x3,%r14
  mov    $0xffffff94,%eax
  jmp    L374
  movb   $0x93,(%r15)
  add    $0x3,%r14
  mov    $0xffffff93,%eax
  jmp    L374
  movb   $0x82,(%r15)
  add    $0x3,%r14
  mov    $0xffffff82,%eax
  jmp    L374
  movb   $0x27,(%r15)
  add    $0x3,%r14
  mov    $0x27,%eax
  jmp    L374
  movb   $0x91,(%r15)
  add    $0x3,%r14
  mov    $0xffffff91,%eax
  jmp    L374
  movb   $0x97,(%r15)
  add    $0x3,%r14
  mov    $0xffffff97,%eax
  jmp    L374
  movb   $0x96,(%r15)
  add    $0x3,%r14
  mov    $0xffffff96,%eax
  jmp    L374
  nopl   0x0(%rax)
L160:
  xor    %eax,%eax
  jmp    L54
L567:
  cmpb   $0xa2,0x2(%r14)
  jne    L13
  movb   $0x99,(%r15)
  add    $0x3,%r14
  mov    $0xffffff99,%eax
  jmp    L374
L526:
  cmpb   $0xac,0x2(%r14)
  jne    L13
  movb   $0x80,(%r15)
  add    $0x3,%r14
  jmp    L374
```

assistant: ```c
int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int buf_len) {
  const unsigned char *p;
  unsigned char *q;
  int i;
  for (i = buf_len, p = buffer, q = buffer_lower; p - buffer < buf_len && i > 0 && *p != '\0';) {
    const unsigned char *p_org = p;
    if ((*p & 0xf0) == 0xe0 && (*(p + 1) & 0xc0) == 0x80 && (*(p + 2) & 0xc0) == 0x80) {
      *q = '\0';
      switch (*p) {
      case 0xE2:
        switch (*(p + 1)) {
        case 0x80:
          switch (*(p + 2)) {
          case 0x93:
            (*q) = 150;
            break;
          case 0x94:
            (*q) = 151;
            break;
          case 0x98:
            (*q) = 145;
            break;
          case 0x99:
            (*q) = '\'';
            break;
          case 0x9A:
            (*q) = 130;
            break;
          case 0x9C:
            (*q) = 147;
            break;
          case 0x9D:
            (*q) = 148;
            break;
          case 0x9E:
            (*q) = 132;
            break;
          case 0xA0:
            (*q) = 134;
            break;
          case 0xA1:
            (*q) = 135;
            break;
          case 0xA2:
            (*q) = 149;
            break;
          case 0xA6:
            (*q) = 133;
            break;
          case 0xB0:
            (*q) = 137;
            break;
          case 0xB9:
            (*q) = 139;
            break;
          case 0xBA:
            (*q) = 155;
            break;
          }
          break;
        case 0x82:
          switch (*(p + 2)) {
          case 0xAC:
            (*q) = 128;
            break;
          }
          break;
        case 0x84:
          switch (*(p + 2)) {
          case 0xA2:
            (*q) = 153;
            break;
          }
          break;
        }
        break;
      }
      p += 3;
    } else if ((*p & 0xe0) == 0xc0 && (*(p + 1) & 0xc0) == 0x80) {
      *q = '\0';
      switch (*p) {
      case 0xC2:
        (*q) = ((*(p + 1)) | 0x80) & 0xBF;
        if ((*q) == 0xA0)
          (*q) = ' ';
        break;
      case 0xC3:
        switch (*(p + 1)) {
        case 0xB3:
          (*q) = 162;
          break;
        default:
          (*q) = (*(p + 1)) | 0xC0;
          break;
        }
        break;
      case 0xC5:
        switch (*(p + 1)) {
        case 0x92:
          (*q) = 140;
          break;
        case 0x93:
          (*q) = 156;
          break;
        case 0xA0:
          (*q) = 138;
          break;
        case 0xA1:
          (*q) = 154;
          break;
        case 0xB8:
          (*q) = 143;
          break;
        case 0xBD:
          (*q) = 142;
          break;
        case 0xBE:
          (*q) = 158;
          break;
        }
        break;
      case 0xC6:
        switch (*(p + 1)) {
        case 0x92:
          (*q) = 131;
          break;
        }
        break;
      case 0xCB:
        switch (*(p + 1)) {
        case 0x86:
          (*q) = 136;
          break;
        case 0x9C:
          (*q) = 152;
          break;
        }
        break;
      }
      p += 2;
    } else {
      *q = tolower(*p++);
    }
    if (*q == '\0' || filtre(*q) == 0) {
      *q = '\0';
      return (p_org - buffer);
    }
    q++;
    i--;
  }
  *q = '\0';
  return (p - buffer);
}
```