user: 请将这段汇编代码片段转换成等效的C代码:

```asm
<calculate_hash>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x38(%rbp)
  mov    %rsi,-0x40(%rbp)
  movl   $0x1,-0x30(%rbp)
  movl   $0x0,-0x2c(%rbp)
  jmp    L56
L26:
  cmpq   $0x15b0,-0x40(%rbp)
  jbe    L24
  mov    -0x38(%rbp),%rax
  mov    %rax,-0x28(%rbp)
  movq   $0x15b0,-0x20(%rbp)
  addq   $0xad80,-0x38(%rbp)
  subq   $0x15b0,-0x40(%rbp)
  jmp    L30
L24:
  mov    -0x38(%rbp),%rax
  mov    %rax,-0x28(%rbp)
  mov    -0x40(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  movq   $0x0,-0x38(%rbp)
  movq   $0x0,-0x40(%rbp)
L30:
  mov    -0x28(%rbp),%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  shr    $0x3,%rax
  shl    $0x6,%rax
  mov    %rax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x10(%rbp)
  jmp    L20
L5:
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
L20:
  mov    -0x18(%rbp),%rax
  cmp    -0x10(%rbp),%rax
  jb     L5
  mov    -0x20(%rbp),%rax
  lea    0x0(,%rax,8),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x8(%rbp)
  jmp    L58
L57:
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  add    %eax,-0x30(%rbp)
  mov    -0x30(%rbp),%eax
  add    %eax,-0x2c(%rbp)
  addq   $0x8,-0x18(%rbp)
L58:
  mov    -0x18(%rbp),%rax
  cmp    -0x8(%rbp),%rax
  jb     L57
  mov    -0x30(%rbp),%eax
  movslq %eax,%rdx
  imul   $0xffffffff80078071,%rdx,%rdx
  shr    $0x20,%rdx
  add    %eax,%edx
  sar    $0xf,%edx
  mov    %eax,%ecx
  sar    $0x1f,%ecx
  sub    %ecx,%edx
  imul   $0xfff1,%edx,%edx
  sub    %edx,%eax
  mov    %eax,-0x30(%rbp)
  mov    -0x2c(%rbp),%eax
  movslq %eax,%rdx
  imul   $0xffffffff80078071,%rdx,%rdx
  shr    $0x20,%rdx
  add    %eax,%edx
  sar    $0xf,%edx
  mov    %eax,%ecx
  sar    $0x1f,%ecx
  sub    %ecx,%edx
  imul   $0xfff1,%edx,%edx
  sub    %edx,%eax
  mov    %eax,-0x2c(%rbp)
L56:
  cmpq   $0x0,-0x40(%rbp)
  jne    L26
  mov    -0x2c(%rbp),%eax
  shl    $0x10,%eax
  or     -0x30(%rbp),%eax
  pop    %rbp
  ret
```

assistant: ```c
uint32_t calculate_hash(uint8_t *x_ptr, size_t x_len) {
  uint32_t s1 = 1;
  uint32_t s2 = 0;
  while (x_len > 0) {
    uint8_t *prefix_ptr;
    size_t prefix_len;
    if (x_len > 5552) {
      prefix_ptr = x_ptr;
      prefix_len = 5552;
      x_ptr = x_ptr + 5552;
      x_len = x_len - 5552;
    } else {
      prefix_ptr = x_ptr;
      prefix_len = x_len;
      x_ptr = NULL;
      x_len = 0;
    }
    uint8_t *p = prefix_ptr;
    uint8_t *end0 = prefix_ptr + (prefix_len / 8) * 8;
    while (p < end0) {
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
    }
    uint8_t *end1 = prefix_ptr + prefix_len;
    while (p < end1) {
      s1 += ((uint32_t)(*p));
      s2 += s1;
      p++;
    }
    s1 %= 65521;
    s2 %= 65521;
  }
  return (s2 << 16) | s1;
}
```