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

```asm
<tile_to_linear_4x2>:
  endbr64
  push   %r15
  mov    %ecx,%r15d
  push   %r14
  imul   %edx,%r15d
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x18,%rsp
  mov    %ecx,0x8(%rsp)
  test   %ecx,%ecx
  je     L49
  mov    %edx,%eax
  movl   $0x0,0x4(%rsp)
  mov    %rdi,%rbx
  mov    %rsi,%rbp
  shl    $0x4,%eax
  mov    %edx,%r14d
  xor    %r13d,%r13d
  mov    %eax,0xc(%rsp)
L39:
  xor    %r12d,%r12d
  test   %r14d,%r14d
  je     L27
  xchg   %ax,%ax
L30:
  mov    0x8(%rsp),%esi
  mov    %r12d,%edx
  mov    %r13d,%ecx
  mov    %r14d,%edi
  call   <tile_4x2_read@plt>
  mov    0x4(%rsp),%esi
  lea    0x400(%rax),%r11d
  lea    (%r12,%rsi,1),%edx
  nopl   0x0(%rax)
L13:
  lea    0x10(%rdx),%ecx
  cmp    %ecx,%r15d
  jbe    L40
  mov    %eax,%ecx
  movzbl 0x0(%rbp,%rcx,1),%r9d
  lea    0x1(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r8d
  lea    0x2(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%edi
  lea    0x3(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%esi
  mov    %edx,%ecx
  mov    %r9b,(%rbx,%rcx,1)
  lea    0x1(%rdx),%ecx
  mov    %r8b,(%rbx,%rcx,1)
  lea    0x2(%rdx),%ecx
  mov    %dil,(%rbx,%rcx,1)
  lea    0x3(%rdx),%ecx
  mov    %sil,(%rbx,%rcx,1)
  lea    0x4(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r9d
  lea    0x5(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r8d
  lea    0x6(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%edi
  lea    0x7(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%esi
  lea    0x4(%rdx),%ecx
  mov    %r9b,(%rbx,%rcx,1)
  lea    0x5(%rdx),%ecx
  mov    %r8b,(%rbx,%rcx,1)
  lea    0x6(%rdx),%ecx
  mov    %dil,(%rbx,%rcx,1)
  lea    0x7(%rdx),%ecx
  mov    %sil,(%rbx,%rcx,1)
  lea    0x8(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r9d
  lea    0x9(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r8d
  lea    0xa(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%edi
  lea    0xb(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%esi
  lea    0x8(%rdx),%ecx
  mov    %r9b,(%rbx,%rcx,1)
  lea    0x9(%rdx),%ecx
  mov    %r8b,(%rbx,%rcx,1)
  lea    0xa(%rdx),%ecx
  mov    %dil,(%rbx,%rcx,1)
  lea    0xb(%rdx),%ecx
  mov    %sil,(%rbx,%rcx,1)
  lea    0xc(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r9d
  lea    0xd(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%r8d
  lea    0xe(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%edi
  lea    0xf(%rax),%ecx
  movzbl 0x0(%rbp,%rcx,1),%esi
  lea    0xc(%rdx),%ecx
  mov    %r9b,(%rbx,%rcx,1)
  lea    0xd(%rdx),%ecx
  mov    %r8b,(%rbx,%rcx,1)
  lea    0xe(%rdx),%ecx
  mov    %dil,(%rbx,%rcx,1)
  lea    0xf(%rdx),%ecx
  mov    %sil,(%rbx,%rcx,1)
L40:
  add    $0x40,%eax
  add    %r14d,%edx
  cmp    %r11d,%eax
  jne    L13
  add    $0x10,%r12d
  cmp    %r12d,%r14d
  ja     L30
L27:
  mov    0xc(%rsp),%edi
  add    $0x10,%r13d
  add    %edi,0x4(%rsp)
  cmp    %r13d,0x8(%rsp)
  ja     L39
L49:
  add    $0x18,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
```

assistant: ```c
void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size) {
  int trans_addr;
  unsigned int i, j, k, index;
  unsigned char data8[4];
  unsigned int max_index = x_size * y_size;
  for (i = 0; i < y_size; i = i + 16) {
    for (j = 0; j < x_size; j = j + 16) {
      trans_addr = tile_4x2_read(x_size, y_size, j, i);
      for (k = 0; k < 16; k++) {
        index = (i * x_size) + (x_size * k) + j;
        if (index + 16 >= max_index) {
          continue;
        }
        data8[0] = p_tiled_addr[trans_addr + 64 * k + 0];
        data8[1] = p_tiled_addr[trans_addr + 64 * k + 1];
        data8[2] = p_tiled_addr[trans_addr + 64 * k + 2];
        data8[3] = p_tiled_addr[trans_addr + 64 * k + 3];
        p_linear_addr[i * x_size + x_size * k + j] = data8[0];
        p_linear_addr[i * x_size + x_size * k + j + 1] = data8[1];
        p_linear_addr[i * x_size + x_size * k + j + 2] = data8[2];
        p_linear_addr[i * x_size + x_size * k + j + 3] = data8[3];
        data8[0] = p_tiled_addr[trans_addr + 64 * k + 4];
        data8[1] = p_tiled_addr[trans_addr + 64 * k + 5];
        data8[2] = p_tiled_addr[trans_addr + 64 * k + 6];
        data8[3] = p_tiled_addr[trans_addr + 64 * k + 7];
        p_linear_addr[i * x_size + x_size * k + j + 4] = data8[0];
        p_linear_addr[i * x_size + x_size * k + j + 5] = data8[1];
        p_linear_addr[i * x_size + x_size * k + j + 6] = data8[2];
        p_linear_addr[i * x_size + x_size * k + j + 7] = data8[3];
        data8[0] = p_tiled_addr[trans_addr + 64 * k + 8];
        data8[1] = p_tiled_addr[trans_addr + 64 * k + 9];
        data8[2] = p_tiled_addr[trans_addr + 64 * k + 10];
        data8[3] = p_tiled_addr[trans_addr + 64 * k + 11];
        p_linear_addr[i * x_size + x_size * k + j + 8] = data8[0];
        p_linear_addr[i * x_size + x_size * k + j + 9] = data8[1];
        p_linear_addr[i * x_size + x_size * k + j + 10] = data8[2];
        p_linear_addr[i * x_size + x_size * k + j + 11] = data8[3];
        data8[0] = p_tiled_addr[trans_addr + 64 * k + 12];
        data8[1] = p_tiled_addr[trans_addr + 64 * k + 13];
        data8[2] = p_tiled_addr[trans_addr + 64 * k + 14];
        data8[3] = p_tiled_addr[trans_addr + 64 * k + 15];
        p_linear_addr[i * x_size + x_size * k + j + 12] = data8[0];
        p_linear_addr[i * x_size + x_size * k + j + 13] = data8[1];
        p_linear_addr[i * x_size + x_size * k + j + 14] = data8[2];
        p_linear_addr[i * x_size + x_size * k + j + 15] = data8[3];
      }
    }
  }
}
```