user: Translate the below assembly code into C programming language:

```asm
<png_find_best_filter>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0xc8,%rsp
  mov    %rdi,-0xb8(%rbp)
  mov    %esi,-0xbc(%rbp)
  mov    %edx,-0xc0(%rbp)
  mov    %ecx,-0xc4(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x18(%rbp)
  xor    %eax,%eax
  mov    $0x0,%eax
  call   <make_num_bits_table@plt>
  cmpl   $0x0,-0xc4(%rbp)
  jle    L95
  mov    $0x5,%eax
  jmp    L48
L95:
  mov    $0x2,%eax
L48:
  mov    %eax,-0x98(%rbp)
  mov    -0xc0(%rbp),%eax
  sar    $0x3,%eax
  mov    %eax,-0x94(%rbp)
  mov    -0x94(%rbp),%eax
  imul   -0xbc(%rbp),%eax
  mov    %eax,-0x90(%rbp)
  mov    -0x94(%rbp),%eax
  mov    %eax,-0x8c(%rbp)
  cmpl   $0x0,-0xc4(%rbp)
  je     L55
  mov    -0x94(%rbp),%eax
  imul   -0xbc(%rbp),%eax
  jmp    L24
L55:
  mov    $0x0,%eax
L24:
  mov    %eax,-0x88(%rbp)
  mov    $0x2000,%esi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,-0x50(%rbp)
  mov    $0x2000,%esi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,-0x48(%rbp)
  mov    $0x2000,%esi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,-0x40(%rbp)
  mov    $0x2000,%esi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,-0x38(%rbp)
  mov    $0x2000,%esi
  mov    $0x1,%edi
  call   <calloc@plt>
  mov    %rax,-0x30(%rbp)
  mov    -0x94(%rbp),%eax
  sub    $0x1,%eax
  mov    %eax,-0x84(%rbp)
  mov    -0x84(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x22(%rbp)
  mov    -0x84(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x21(%rbp)
  mov    -0x84(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%edx
  mov    -0x84(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %al,-0x20(%rbp)
  mov    -0x84(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%edx
  mov    -0x84(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %al,-0x1f(%rbp)
  mov    -0x84(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%ebx
  mov    -0x84(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    $0x0,%edx
  mov    %eax,%esi
  mov    $0x0,%edi
  call   <PaethPredictor@plt>
  mov    %eax,%edx
  mov    %ebx,%eax
  sub    %edx,%eax
  mov    %al,-0x1e(%rbp)
  movl   $0x0,-0x70(%rbp)
  movl   $0x0,-0x6c(%rbp)
  movl   $0x0,-0x68(%rbp)
  movl   $0x0,-0x64(%rbp)
  movl   $0x0,-0x60(%rbp)
  mov    -0x94(%rbp),%eax
  mov    %eax,-0xac(%rbp)
  jmp    L28
L63:
  mov    -0xac(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %al,-0x1d(%rbp)
  mov    -0xac(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%edx
  mov    -0xac(%rbp),%eax
  sub    -0x8c(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %al,-0x1c(%rbp)
  mov    -0xac(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%edx
  mov    -0xac(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%ecx
  mov    %edx,%eax
  sub    %ecx,%eax
  mov    %al,-0x1b(%rbp)
  mov    -0xac(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%edx
  mov    -0xac(%rbp),%eax
  sub    -0x8c(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%eax
  movzbl %al,%ecx
  mov    -0xac(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rsi
  mov    -0xb8(%rbp),%rax
  add    %rsi,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  add    %ecx,%eax
  mov    %eax,%ecx
  shr    $0x1f,%ecx
  add    %ecx,%eax
  sar    %eax
  neg    %eax
  add    %edx,%eax
  mov    %al,-0x1a(%rbp)
  mov    -0xac(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%ebx
  mov    -0xac(%rbp),%eax
  sub    -0x8c(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rdx
  mov    -0xb8(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%edx
  mov    -0xac(%rbp),%eax
  sub    -0x88(%rbp),%eax
  movslq %eax,%rcx
  mov    -0xb8(%rbp),%rax
  add    %rcx,%rax
  movzbl (%rax),%eax
  movzbl %al,%ecx
  mov    -0xac(%rbp),%eax
  sub    -0x8c(%rbp),%eax
  movslq %eax,%rsi
  mov    -0xb8(%rbp),%rax
  add    %rsi,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  mov    %ecx,%esi
  mov    %eax,%edi
  call   <PaethPredictor@plt>
  mov    %eax,%edx
  mov    %ebx,%eax
  sub    %edx,%eax
  mov    %al,-0x19(%rbp)
  movl   $0x0,-0xa8(%rbp)
  jmp    L10
L14:
  mov    -0xa8(%rbp),%eax
  cltq
  movzbl -0x1d(%rbp,%rax,1),%eax
  movzbl %al,%eax
  shl    $0x8,%eax
  mov    %eax,%edx
  mov    -0xa8(%rbp),%eax
  cltq
  movzbl -0x22(%rbp,%rax,1),%eax
  movzbl %al,%eax
  or     %edx,%eax
  mov    %eax,-0x7c(%rbp)
  mov    -0x7c(%rbp),%eax
  sar    $0x3,%eax
  mov    %eax,-0x78(%rbp)
  mov    -0x7c(%rbp),%eax
  and    $0x7,%eax
  mov    $0x1,%edx
  mov    %eax,%ecx
  shl    %cl,%edx
  mov    %edx,%eax
  mov    %eax,-0x74(%rbp)
  mov    -0xa8(%rbp),%eax
  cltq
  mov    -0x50(%rbp,%rax,8),%rdx
  mov    -0x78(%rbp),%eax
  cltq
  add    %rdx,%rax
  movzbl (%rax),%eax
  test   %al,%al
  sete   %al
  movzbl %al,%eax
  and    -0x74(%rbp),%eax
  test   %eax,%eax
  je     L59
  mov    -0xa8(%rbp),%eax
  cltq
  mov    -0x50(%rbp,%rax,8),%rdx
  mov    -0x78(%rbp),%eax
  cltq
  add    %rdx,%rax
  movzbl (%rax),%eax
  mov    %eax,%edx
  mov    -0x74(%rbp),%eax
  mov    %edx,%ecx
  or     %eax,%ecx
  mov    -0xa8(%rbp),%eax
  cltq
  mov    -0x50(%rbp,%rax,8),%rdx
  mov    -0x78(%rbp),%eax
  cltq
  add    %rdx,%rax
  mov    %ecx,%edx
  mov    %dl,(%rax)
  mov    -0xa8(%rbp),%eax
  cltq
  mov    -0x70(%rbp,%rax,4),%eax
  lea    0x1(%rax),%edx
  mov    -0xa8(%rbp),%eax
  cltq
  mov    %edx,-0x70(%rbp,%rax,4)
L59:
  addl   $0x1,-0xa8(%rbp)
L10:
  cmpl   $0x4,-0xa8(%rbp)
  jle    L14
  lea    -0x1d(%rbp),%rcx
  lea    -0x22(%rbp),%rax
  mov    $0x5,%edx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <memcpy@plt>
  addl   $0x1,-0xac(%rbp)
L28:
  mov    -0xac(%rbp),%eax
  cmp    -0x90(%rbp),%eax
  jl     L63
  movl   $0x0,-0xa0(%rbp)
  mov    D8(%rip),%rax
  mov    (%rax),%eax
  mov    %eax,-0x9c(%rbp)
  movl   $0x0,-0xa4(%rbp)
  jmp    L118
L2:
  mov    -0xa4(%rbp),%eax
  cltq
  mov    -0x70(%rbp,%rax,4),%eax
  mov    %eax,-0x80(%rbp)
  mov    -0x80(%rbp),%eax
  cmp    -0x9c(%rbp),%eax
  jge    L26
  mov    -0xa4(%rbp),%eax
  mov    %eax,-0xa0(%rbp)
  mov    -0x80(%rbp),%eax
  mov    %eax,-0x9c(%rbp)
L26:
  addl   $0x1,-0xa4(%rbp)
L118:
  mov    -0xa4(%rbp),%eax
  cmp    -0x98(%rbp),%eax
  jl     L2
  mov    -0x50(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x48(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x40(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x38(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x30(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0xa0(%rbp),%eax
  mov    -0x18(%rbp),%rdx
  sub    %fs:0x28,%rdx
  je     L21
  call   <__stack_chk_fail@plt>
L21:
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

assistant: ```c
int png_find_best_filter(unsigned char *src, unsigned width, int bpp, int y) {
  make_num_bits_table();
  int num_filters = y > 0 ? 5 : 2;
  int bytes_per_pixel = bpp >> 3;
  int w = width * bytes_per_pixel;
  int back_x = bytes_per_pixel;
  int back_y = y ? width * bytes_per_pixel : 0;
  unsigned char *pairs[5];
  pairs[0] = calloc(1, 8192);
  pairs[1] = calloc(1, 8192);
  pairs[2] = calloc(1, 8192);
  pairs[3] = calloc(1, 8192);
  pairs[4] = calloc(1, 8192);
  unsigned char old[5];
  int l = bytes_per_pixel - 1;
  old[0] = src[l];
  old[1] = src[l];
  old[2] = src[l] - src[l - back_y];
  old[3] = src[l] - src[l - back_y];
  old[4] = src[l] - PaethPredictor(0, src[l - back_y], 0);
  int different_pairs[5] = {0, 0, 0, 0, 0};
  int x;
  for (x = bytes_per_pixel; x < w; x++) {
    unsigned char dest[5];
    dest[0] = src[x];
    dest[1] = src[x] - src[x - back_x];
    dest[2] = src[x] - src[x - back_y];
    dest[3] = src[x] - (src[x - back_x] + src[x - back_y]) / 2;
    dest[4] = src[x] - PaethPredictor(src[x - back_x], src[x - back_y], src[x - back_x - back_y]);
    int i;
    for (i = 0; i < 5; i++) {
      int v = dest[i] << 8 | old[i];
      int p = v >> 3;
      int b = 1 << (v & 7);
      if (!pairs[i][p] & b) {
        pairs[i][p] |= b;
        different_pairs[i]++;
      }
    }
    memcpy(old, dest, sizeof(old));
  }
  int f;
  int best_nr = 0;
  int best_energy = INT_MAX;
  for (f = 0; f < num_filters; f++) {
    int energy = different_pairs[f];
    if (energy < best_energy) {
      best_nr = f;
      best_energy = energy;
    }
  }
  free(pairs[0]);
  free(pairs[1]);
  free(pairs[2]);
  free(pairs[3]);
  free(pairs[4]);
  return best_nr;
}
```