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

```asm
<udp_sum_calc>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x18(%rbp)
  mov    %rsi,-0x20(%rbp)
  mov    %rdx,-0x28(%rbp)
  mov    %ecx,%eax
  mov    %ax,-0x2c(%rbp)
  movw   $0x11,-0xe(%rbp)
  movw   $0x0,-0xc(%rbp)
  movl   $0x0,-0x8(%rbp)
  movzwl -0x2c(%rbp),%eax
  and    $0x1,%eax
  mov    %ax,-0xc(%rbp)
  cmpw   $0x0,-0xc(%rbp)
  je     L70
  movzwl -0x2c(%rbp),%edx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movb   $0x0,(%rax)
L70:
  movl   $0x0,-0x4(%rbp)
  jmp    L91
L6:
  mov    -0x4(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  shl    $0x8,%eax
  mov    %eax,%ecx
  mov    -0x4(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  add    %ecx,%eax
  mov    %ax,-0xa(%rbp)
  movzwl -0xa(%rbp),%eax
  add    %eax,-0x8(%rbp)
  addl   $0x2,-0x4(%rbp)
L91:
  movzwl -0x2c(%rbp),%edx
  movzwl -0xc(%rbp),%eax
  add    %edx,%eax
  cmp    %eax,-0x4(%rbp)
  jl     L6
  movl   $0x0,-0x4(%rbp)
  jmp    L84
L90:
  mov    -0x4(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x18(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  shl    $0x8,%eax
  mov    %eax,%ecx
  mov    -0x4(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x18(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  add    %ecx,%eax
  mov    %ax,-0xa(%rbp)
  movzwl -0xa(%rbp),%eax
  add    %eax,-0x8(%rbp)
  addl   $0x2,-0x4(%rbp)
L84:
  cmpl   $0x3,-0x4(%rbp)
  jle    L90
  movl   $0x0,-0x4(%rbp)
  jmp    L55
L18:
  mov    -0x4(%rbp),%eax
  movslq %eax,%rdx
  mov    -0x20(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  shl    $0x8,%eax
  mov    %eax,%ecx
  mov    -0x4(%rbp),%eax
  cltq
  lea    0x1(%rax),%rdx
  mov    -0x20(%rbp),%rax
  add    %rdx,%rax
  movzbl (%rax),%eax
  movzbl %al,%eax
  add    %ecx,%eax
  mov    %ax,-0xa(%rbp)
  movzwl -0xa(%rbp),%eax
  add    %eax,-0x8(%rbp)
  addl   $0x2,-0x4(%rbp)
L55:
  cmpl   $0x3,-0x4(%rbp)
  jle    L18
  movzwl -0xe(%rbp),%edx
  movzwl -0x2c(%rbp),%eax
  add    %edx,%eax
  add    %eax,-0x8(%rbp)
  jmp    L54
L11:
  mov    -0x8(%rbp),%eax
  movzwl %ax,%edx
  mov    -0x8(%rbp),%eax
  shr    $0x10,%eax
  add    %edx,%eax
  mov    %eax,-0x8(%rbp)
L54:
  mov    -0x8(%rbp),%eax
  shr    $0x10,%eax
  test   %eax,%eax
  jne    L11
  notl   -0x8(%rbp)
  mov    -0x8(%rbp),%eax
  test   %ax,%ax
  jne    L98
  movl   $0xffff,-0x8(%rbp)
L98:
  mov    -0x8(%rbp),%eax
  pop    %rbp
  ret
```

assistant: ```c
unsigned short udp_sum_calc(unsigned char *src_addr, unsigned char *dst_addr, unsigned char *data, unsigned short len) {
  unsigned short prot_udp = 17;
  unsigned short padd = 0;
  unsigned short word16;
  unsigned int sum = 0;
  int i;
  padd = (len % 2);
  if (padd) {
    data[len] = 0;
  }
  for (i = 0; i < len + padd; i += 2) {
    word16 = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
    sum += word16;
  }
  for (i = 0; i < 4; i += 2) {
    word16 = ((src_addr[i] << 8) & 0xFF00) + (src_addr[i + 1] & 0xFF);
    sum += word16;
  }
  for (i = 0; i < 4; i += 2) {
    word16 = ((dst_addr[i] << 8) & 0xFF00) + (dst_addr[i + 1] & 0xFF);
    sum += word16;
  }
  sum += prot_udp + len;
  while (sum >> 16)
    sum = (sum & 0xFFFF) + (sum >> 16);
  sum = ~sum;
  if ((unsigned short)sum == 0)
    sum = 0xFFFF;
  return (unsigned short)sum;
}
```