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

```asm
<pack_nametable>:
  endbr64
  push   %r15
  xor    %eax,%eax
  mov    %esi,%r15d
  push   %r14
  push   %r13
  mov    %r9,%r13
  push   %r12
  push   %rbp
  push   %rbx
  mov    %ecx,%ebx
  sub    $0x58,%rsp
  mov    %esi,0x48(%rsp)
  mov    %edx,0x14(%rsp)
  mov    %r8d,0x4c(%rsp)
  mov    %rdi,0x8(%rsp)
  call   <assert@plt>
  mov    %r13,%rdi
  xor    %eax,%eax
  call   <assert@plt>
  mov    0x90(%rsp),%rdi
  xor    %eax,%eax
  call   <assert@plt>
  movq   $0x0,0x0(%r13)
  test   %r15d,%r15d
  jle    L512
  mov    0x14(%rsp),%r10d
  xor    %eax,%eax
  mov    0x8(%rsp),%r14
  mov    %ebx,0x40(%rsp)
  xor    %r12d,%r12d
  xor    %ebx,%ebx
  mov    %eax,%r11d
  mov    %r10d,0x44(%rsp)
  nopw   0x0(%rax,%rax,1)
L343:
  mov    0x40(%rsp),%r15d
  test   %r10d,%r10d
  jle    L314
  xor    %ecx,%ecx
  xor    %ebp,%ebp
L520:
  movslq %r12d,%rax
  movzbl (%r14,%rax,1),%edx
  cmp    $0x1,%ecx
  jne    L215
L25:
  xor    %r9d,%r9d
  test   %dl,%dl
  jne    L183
  add    $0x1,%ebp
  add    $0x1,%r12d
  add    $0x1,%r15d
  cmp    %ebp,%r10d
  jle    L359
  movslq %r12d,%rax
  movzbl (%r14,%rax,1),%edx
L342:
  test   %dl,%dl
  jne    L183
  add    $0x1,%ebp
  add    $0x1,%r12d
  add    $0x1,%r15d
  mov    $0x1,%ecx
  cmp    %ebp,%r10d
  jg     L520
  nopw   0x0(%rax,%rax,1)
L359:
  mov    0x44(%rsp),%esi
  cmp    %esi,0x48(%rsp)
  jle    L268
L314:
  add    %r10d,0x44(%rsp)
  addl   $0x20,0x40(%rsp)
  jmp    L343
  nopw   0x0(%rax,%rax,1)
L460:
  xor    %r9d,%r9d
L183:
  lea    0x2(%rbx),%r8d
  mov    0x0(%r13),%rdi
  cmp    %r11d,%r8d
  jge    L398
L567:
  movslq %ebx,%rax
  mov    %r15d,%ecx
  mov    %ch,(%rdi,%rax,1)
  lea    0x1(%rbx),%eax
  mov    0x0(%r13),%rsi
  cltq
  mov    %r15b,(%rsi,%rax,1)
  test   %r9d,%r9d
  je     L92
  add    $0x4,%ebp
  add    $0x4,%r12d
  cmp    %ebp,%r10d
  jle    L71
  movslq %r12d,%rcx
  movzbl (%r14,%rcx,1),%eax
  lea    0x1(%r14,%rcx,1),%rsi
  mov    $0x4,%ecx
L334:
  cmp    %al,%dl
  je     L555
L167:
  lea    0x4(%rbx),%r9d
  mov    0x0(%r13),%rdi
  cmp    %r11d,%r9d
  jge    L26
L214:
  mov    %ecx,%eax
  movslq %r8d,%r8
  add    $0x3,%ebx
  add    %ecx,%r15d
  or     $0x40,%eax
  movslq %ebx,%rbx
  mov    %al,(%rdi,%r8,1)
  mov    0x0(%r13),%rax
  mov    %dl,(%rax,%rbx,1)
  cmp    %ebp,%r10d
  jle    L537
  movslq %r12d,%rax
  mov    %r9d,%ebx
  movzbl (%r14,%rax,1),%edx
L215:
  lea    0x1(%r15),%edi
  lea    0x1(%rbp),%ecx
  lea    0x1(%r12),%esi
L286:
  lea    0x2(%rcx),%r8d
  lea    -0x1(%rsi),%r12d
  lea    -0x1(%rcx),%ebp
  lea    -0x1(%rdi),%r15d
  cmp    %r8d,%r10d
  jle    L517
  cmp    %dl,0x1(%r14,%rax,1)
  je     L132
L517:
  test   %dl,%dl
  jne    L460
L565:
  mov    %esi,%r12d
  cmp    %ecx,%r10d
  jle    L359
  movslq %esi,%rax
  add    $0x1,%edi
  add    $0x1,%ecx
  add    $0x1,%esi
  movzbl (%r14,%rax,1),%edx
  jmp    L286
L555:
  add    $0x1,%ecx
  add    $0x1,%r12d
  add    $0x1,%ebp
  cmp    $0x3f,%ecx
  je     L167
  cmp    %ebp,%r10d
  jle    L8
  movzbl (%rsi),%eax
  add    $0x1,%rsi
  jmp    L334
  nopl   0x0(%rax,%rax,1)
L92:
  lea    0x4(%rbx),%ecx
  mov    0x0(%r13),%rdi
  cmp    %r11d,%ecx
  jge    L43
L407:
  movslq %r8d,%rax
  add    $0x3,%ebx
  add    $0x1,%ebp
  add    $0x1,%r12d
  movb   $0x0,(%rdi,%rax,1)
  movslq %ebx,%rbx
  mov    %rax,0x18(%rsp)
  mov    0x0(%r13),%rax
  mov    %dl,(%rax,%rbx,1)
  cmp    %ebp,%r10d
  jle    L557
  movslq %r12d,%r8
  movslq %ecx,%rax
  mov    $0x1,%ecx
  mov    %r15d,0x14(%rsp)
  movzbl (%r14,%r8,1),%r9d
  mov    %rax,0x8(%rsp)
  mov    %rax,%rbx
  mov    %r8,%r12
  lea    0x3(%rbp),%eax
  mov    %ecx,%r15d
  mov    %r14,%rdx
  mov    %r13,%rcx
  mov    %r8,%rsi
  mov    %r9d,%r13d
  mov    %r12d,%r14d
  cmp    %eax,%r10d
  jle    L326
  cmp    %r13b,0x1(%rdx,%rsi,1)
  je     L219
  nopw   0x0(%rax,%rax,1)
L326:
  add    $0x1,%ebx
  mov    (%rcx),%rdi
  cmp    %r11d,%ebx
  jge    L474
L80:
  mov    0x8(%rsp),%rax
  add    %r12,%rdi
  add    $0x1,%r15d
  add    $0x1,%ebp
  sub    %r8,%rax
  mov    %r13b,(%rdi,%rax,1)
  lea    0x1(%r14),%edi
  cmp    $0x3f,%r15d
  je     L277
  add    $0x1,%r12
  cmp    %ebp,%r10d
  jle    L400
  lea    0x3(%rbp),%eax
  movzbl (%rdx,%r12,1),%r13d
  mov    %r12,%rsi
  mov    %r12d,%r14d
  cmp    %eax,%r10d
  jle    L326
  cmp    %r13b,0x1(%rdx,%rsi,1)
  jne    L326
L219:
  cmp    %r13b,0x2(%rdx,%rsi,1)
  jne    L326
  cmp    %r13b,0x3(%rdx,%rsi,1)
  jne    L326
  mov    %rcx,%r13
  mov    0x18(%rsp),%rsi
  mov    %r15d,%ecx
  mov    0x14(%rsp),%r15d
  mov    0x0(%r13),%rax
  mov    %rdx,%r14
  add    %ecx,%r15d
  mov    %cl,(%rax,%rsi,1)
  cmp    %ebp,%r10d
  jle    L359
  movslq %r12d,%rax
  mov    $0x1,%r9d
  movzbl (%rdx,%rax,1),%edx
  jmp    L342
  nopl   0x0(%rax)
L277:
  mov    0x14(%rsp),%r15d
  mov    (%rcx),%rax
  mov    %edi,%r12d
  mov    %rdx,%r14
  mov    0x18(%rsp),%rsi
  mov    %rcx,%r13
  add    $0x3f,%r15d
  movb   $0x3f,(%rax,%rsi,1)
  cmp    %ebp,%r10d
  jle    L359
  movslq %edi,%rax
  movzbl (%rdx,%rax,1),%edx
  jmp    L25
  nopl   0x0(%rax,%rax,1)
L398:
  add    $0x40,%r11d
  mov    %dl,0x20(%rsp)
  movslq %r11d,%rsi
  mov    %r8d,0x30(%rsp)
  mov    %r10d,0x18(%rsp)
  mov    %r9d,0x14(%rsp)
  mov    %r11d,0x8(%rsp)
  call   <realloc@plt>
  movzbl 0x20(%rsp),%edx
  mov    0x30(%rsp),%r8d
  mov    %rax,0x0(%r13)
  mov    0x18(%rsp),%r10d
  mov    %rax,%rdi
  mov    0x14(%rsp),%r9d
  mov    0x8(%rsp),%r11d
  jmp    L567
  nopl   0x0(%rax)
L474:
  add    $0x40,%r11d
  mov    %rcx,0x38(%rsp)
  movslq %r11d,%rsi
  mov    %r10d,0x34(%rsp)
  mov    %rdx,0x28(%rsp)
  mov    %r8,0x20(%rsp)
  mov    %r11d,0x30(%rsp)
  call   <realloc@plt>
  mov    0x38(%rsp),%rcx
  mov    0x34(%rsp),%r10d
  mov    0x28(%rsp),%rdx
  mov    0x20(%rsp),%r8
  mov    %rax,%rdi
  mov    %rax,(%rcx)
  mov    0x30(%rsp),%r11d
  jmp    L80
  nopl   0x0(%rax)
L132:
  cmp    %dl,0x2(%r14,%rax,1)
  jne    L517
  movzbl 0x3(%r14,%rax,1),%eax
  test   %dl,%dl
  je     L565
  xor    %r9d,%r9d
  cmp    %dl,%al
  sete   %r9b
  jmp    L183
  nop
L43:
  add    $0x40,%r11d
  mov    %ecx,0x20(%rsp)
  movslq %r11d,%rsi
  mov    %dl,0x30(%rsp)
  mov    %r8d,0x18(%rsp)
  mov    %r10d,0x14(%rsp)
  mov    %r11d,0x8(%rsp)
  call   <realloc@plt>
  mov    0x20(%rsp),%ecx
  movzbl 0x30(%rsp),%edx
  mov    %rax,0x0(%r13)
  mov    0x18(%rsp),%r8d
  mov    %rax,%rdi
  mov    0x14(%rsp),%r10d
  mov    0x8(%rsp),%r11d
  jmp    L407
  nopw   0x0(%rax,%rax,1)
L26:
  add    $0x40,%r11d
  mov    %dl,0x28(%rsp)
  movslq %r11d,%rsi
  mov    %ecx,0x20(%rsp)
  mov    %r8d,0x30(%rsp)
  mov    %r9d,0x18(%rsp)
  mov    %r10d,0x14(%rsp)
  mov    %r11d,0x8(%rsp)
  call   <realloc@plt>
  movzbl 0x28(%rsp),%edx
  mov    0x20(%rsp),%ecx
  mov    %rax,0x0(%r13)
  mov    0x30(%rsp),%r8d
  mov    %rax,%rdi
  mov    0x18(%rsp),%r9d
  mov    0x14(%rsp),%r10d
  mov    0x8(%rsp),%r11d
  jmp    L214
L400:
  mov    %rcx,%r13
  mov    %edi,%r12d
  mov    %rdx,%r14
  mov    %r15d,%ecx
L74:
  mov    0x18(%rsp),%rsi
  mov    0x0(%r13),%rax
  mov    %cl,(%rax,%rsi,1)
  mov    0x44(%rsp),%esi
  cmp    %esi,0x48(%rsp)
  jg     L314
L268:
  mov    0x4c(%rsp),%edx
  mov    %r11d,%esi
  test   %edx,%edx
  jne    L78
L117:
  mov    0x90(%rsp),%rax
  mov    %ebx,(%rax)
  add    $0x58,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L8:
  mov    %ecx,%ebp
  or     $0x40,%ebp
L276:
  lea    0x4(%rbx),%r15d
  mov    0x0(%r13),%rdi
  cmp    %r11d,%r15d
  jge    L302
L181:
  movslq %r8d,%r8
  lea    0x3(%rbx),%eax
  mov    %r15d,%ebx
  mov    %bpl,(%rdi,%r8,1)
  mov    0x0(%r13),%rcx
  cltq
  mov    %dl,(%rcx,%rax,1)
  jmp    L359
L302:
  add    $0x40,%r11d
  mov    %r10d,0x30(%rsp)
  movslq %r11d,%rsi
  mov    %dl,0x18(%rsp)
  mov    %r8d,0x14(%rsp)
  mov    %r11d,0x8(%rsp)
  call   <realloc@plt>
  mov    0x30(%rsp),%r10d
  movzbl 0x18(%rsp),%edx
  mov    %rax,0x0(%r13)
  mov    0x14(%rsp),%r8d
  mov    %rax,%rdi
  mov    0x8(%rsp),%r11d
  jmp    L181
L71:
  mov    $0x44,%ebp
  jmp    L276
L557:
  mov    %ecx,%ebx
  mov    $0x1,%ecx
  jmp    L74
L537:
  mov    %r9d,%ebx
  jmp    L359
L78:
  lea    0x1(%rbx),%ebp
  add    $0x1,%esi
  mov    0x0(%r13),%rdi
  movslq %ebx,%rbx
  movslq %esi,%rsi
  cmp    %r11d,%ebp
  jge    L228
L401:
  movb   $0x0,(%rdi,%rbx,1)
  mov    %ebp,%ebx
  jmp    L117
L512:
  mov    0x4c(%rsp),%eax
  xor    %ebx,%ebx
  test   %eax,%eax
  je     L117
  xor    %ebx,%ebx
  xor    %edi,%edi
  mov    $0x1,%esi
  mov    $0x1,%ebp
L228:
  call   <realloc@plt>
  mov    %rax,0x0(%r13)
  mov    %rax,%rdi
  jmp    L401
```

assistant: ```c
void pack_nametable(const unsigned char *nametable, int nametable_sz, int width, int vram_address, int zero_terminate, unsigned char **out, int *out_sz) {
  int out_pos = 0;
  int buf_sz = 0;
  int y = 0;
  int in_pos = 0;
  assert(nametable);
  assert(out);
  assert(out_sz);
  *out = 0;
  while (y * width < nametable_sz) {
    unsigned char rlech;
    int count;
    int count_pos;
    int x = 0;
    int state = 0;
    int start_rle = 0;
    int addr = vram_address + (y * 32);
    while (x < width) {
      const unsigned char ch = nametable[in_pos];
      switch (state) {
      case 0:
        start_rle = (x + 4 <= width) && (nametable[in_pos + 1] == ch) && (nametable[in_pos + 2] == ch) && (nametable[in_pos + 3] == ch);
      case 1:
        if (ch == 0) {
          start_rle = 0;
          ++in_pos;
          ++x;
          ++addr;
          break;
        }
        if (out_pos + 2 >= buf_sz) {
          buf_sz += 64;
          *out = (unsigned char *)realloc(*out, buf_sz);
        }
        (*out)[out_pos++] = (unsigned char)(addr >> 8);
        (*out)[out_pos++] = (unsigned char)(addr & 255);
        if (start_rle) {
          count = 4;
          rlech = ch;
          in_pos += 4;
          x += 4;
          state = 2;
        } else {
          count_pos = out_pos;
          if (out_pos + 2 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = 0;
          count = 1;
          (*out)[out_pos++] = ch;
          ++in_pos;
          ++x;
          state = 3;
        }
        break;
      case 2:
        if (ch == rlech) {
          ++count;
          ++in_pos;
          ++x;
        }
        if ((ch != rlech) || (count == 0x3F)) {
          if (out_pos + 2 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = (unsigned char)(0x40 | count);
          (*out)[out_pos++] = rlech;
          addr += count;
          state = 0;
        }
        break;
      case 3:
        start_rle = ((x + 4 <= width) && (nametable[in_pos + 1] == ch) && (nametable[in_pos + 2] == ch) && (nametable[in_pos + 3] == ch));
        if (start_rle) {
          (*out)[count_pos] = count;
          addr += count;
          state = 1;
        } else {
          if (out_pos + 1 >= buf_sz) {
            buf_sz += 64;
            *out = (unsigned char *)realloc(*out, buf_sz);
          }
          (*out)[out_pos++] = ch;
          ++in_pos;
          ++x;
          ++count;
          if (count == 0x3F) {
            (*out)[count_pos] = count;
            addr += count;
            state = 1;
          }
        }
        break;
      }
    }
    switch (state) {
    case 0:
    case 1:
      break;
    case 2:
      if (out_pos + 2 >= buf_sz) {
        buf_sz += 64;
        *out = (unsigned char *)realloc(*out, buf_sz);
      }
      (*out)[out_pos++] = (unsigned char)(0x40 | count);
      (*out)[out_pos++] = rlech;
      break;
    case 3:
      (*out)[count_pos] = count;
      break;
    }
    ++y;
  }
  if (zero_terminate) {
    if (out_pos + 1 >= buf_sz) {
      buf_sz += 1;
      *out = (unsigned char *)realloc(*out, buf_sz);
    }
    (*out)[out_pos++] = 0;
  }
  *out_sz = out_pos;
}
```