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

```asm
<find_next_zero_bit>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x28(%rbp)
  mov    %rsi,-0x30(%rbp)
  mov    %rdx,-0x38(%rbp)
  mov    -0x38(%rbp),%rax
  shr    $0x6,%rax
  lea    0x0(,%rax,8),%rdx
  mov    -0x28(%rbp),%rax
  add    %rdx,%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x38(%rbp),%rax
  and    $0xffffffffffffffc0,%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x38(%rbp),%rax
  cmp    -0x30(%rbp),%rax
  jb     L0
  mov    -0x30(%rbp),%rax
  jmp    L32
L0:
  mov    -0x10(%rbp),%rax
  sub    %rax,-0x30(%rbp)
  andq   $0x3f,-0x38(%rbp)
  cmpq   $0x0,-0x38(%rbp)
  je     L56
  mov    -0x18(%rbp),%rax
  lea    0x8(%rax),%rdx
  mov    %rdx,-0x18(%rbp)
  mov    (%rax),%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x38(%rbp),%rax
  mov    %eax,%edx
  mov    $0x40,%eax
  sub    %edx,%eax
  mov    $0xffffffffffffffff,%rdx
  mov    %eax,%ecx
  shr    %cl,%rdx
  mov    %rdx,%rax
  or     %rax,-0x8(%rbp)
  cmpq   $0x3f,-0x30(%rbp)
  jbe    L101
  cmpq   $0xffffffffffffffff,-0x8(%rbp)
  jne    L25
  subq   $0x40,-0x30(%rbp)
  addq   $0x40,-0x10(%rbp)
  jmp    L56
L122:
  mov    -0x18(%rbp),%rax
  lea    0x8(%rax),%rdx
  mov    %rdx,-0x18(%rbp)
  mov    (%rax),%rax
  mov    %rax,-0x8(%rbp)
  cmpq   $0xffffffffffffffff,-0x8(%rbp)
  jne    L117
  addq   $0x40,-0x10(%rbp)
  subq   $0x40,-0x30(%rbp)
L56:
  mov    -0x30(%rbp),%rax
  and    $0xffffffffffffffc0,%rax
  test   %rax,%rax
  jne    L122
  cmpq   $0x0,-0x30(%rbp)
  jne    L9
  mov    -0x10(%rbp),%rax
  jmp    L32
L9:
  mov    -0x18(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x8(%rbp)
  jmp    L141
L101:
  nop
L141:
  mov    -0x30(%rbp),%rax
  mov    $0xffffffffffffffff,%rdx
  mov    %eax,%ecx
  shl    %cl,%rdx
  mov    %rdx,%rax
  or     %rax,-0x8(%rbp)
  cmpq   $0xffffffffffffffff,-0x8(%rbp)
  jne    L143
  mov    -0x10(%rbp),%rdx
  mov    -0x30(%rbp),%rax
  add    %rdx,%rax
  jmp    L32
L25:
  nop
  jmp    L110
L117:
  nop
  jmp    L110
L143:
  nop
L110:
  mov    -0x8(%rbp),%rax
  not    %rax
  mov    $0xffffffffffffffff,%rdx
  bsf    %rax,%rax
  cmove  %rdx,%rax
  add    $0x1,%rax
  sub    $0x1,%eax
  movslq %eax,%rdx
  mov    -0x10(%rbp),%rax
  add    %rdx,%rax
L32:
  pop    %rbp
  ret
```

assistant: ```c
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) {
  const unsigned long *p = addr + ((offset) / ((int)((sizeof(long) * 8))));
  unsigned long result = offset & ~(((int)((sizeof(long) * 8))) - 1);
  unsigned long tmp;
  if (offset >= size)
    return size;
  size -= result;
  offset %= ((int)((sizeof(long) * 8)));
  if (offset) {
    tmp = *(p++);
    tmp |= ~0UL >> (((int)((sizeof(long) * 8))) - offset);
    if (size < ((int)((sizeof(long) * 8))))
      goto found_first;
    if (~tmp)
      goto found_middle;
    size -= ((int)((sizeof(long) * 8)));
    result += ((int)((sizeof(long) * 8)));
  }
  while (size & ~(((int)((sizeof(long) * 8))) - 1)) {
    if (~(tmp = *(p++)))
      goto found_middle;
    result += ((int)((sizeof(long) * 8)));
    size -= ((int)((sizeof(long) * 8)));
  }
  if (!size)
    return result;
  tmp = *p;
found_first:
  tmp |= ~0UL << size;
  if (tmp == ~0UL)
    return result + size;
found_middle:
  return result + (__builtin_ffsl(~(tmp)) - 1);
}
```