user: Please show me the C implementation that matches the assembly code listed below:

```asm
<GoLGrid_evolve_strip_keep_bit_0>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x8,%rsp
  mov    %rdi,-0x68(%rbp)
  mov    %rsi,-0x70(%rbp)
  mov    %rdx,-0x78(%rbp)
  mov    %ecx,-0x7c(%rbp)
  mov    -0x78(%rbp),%rax
  shl    $0x3,%rax
  neg    %rax
  mov    %rax,%rdx
  mov    -0x68(%rbp),%rax
  add    %rdx,%rax
  mov    (%rax),%rax
  mov    %rax,-0x58(%rbp)
  mov    -0x68(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x50(%rbp)
  mov    -0x78(%rbp),%rax
  shl    $0x3,%rax
  add    %rax,-0x68(%rbp)
  mov    -0x68(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x48(%rbp)
  movq   $0x0,-0x40(%rbp)
L12:
  mov    -0x58(%rbp),%rax
  shr    %rax
  mov    %rax,-0x38(%rbp)
  mov    -0x38(%rbp),%rax
  mov    %rax,-0x30(%rbp)
  mov    -0x58(%rbp),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x58(%rbp),%rax
  add    %rax,%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x20(%rbp),%rax
  or     %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x50(%rbp),%rax
  shr    %rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x28(%rbp),%rax
  and    -0x20(%rbp),%rax
  mov    %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  xor    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x50(%rbp),%rax
  add    %rax,%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x28(%rbp),%rax
  and    -0x20(%rbp),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  or     %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  xor    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x48(%rbp),%rax
  shr    %rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x28(%rbp),%rax
  and    -0x20(%rbp),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  or     %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  xor    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x48(%rbp),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x28(%rbp),%rax
  and    -0x20(%rbp),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  or     %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  xor    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x48(%rbp),%rax
  add    %rax,%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x30(%rbp),%rax
  and    -0x38(%rbp),%rax
  mov    %rax,-0x20(%rbp)
  mov    -0x28(%rbp),%rax
  and    -0x20(%rbp),%rax
  mov    %rax,-0x10(%rbp)
  mov    -0x10(%rbp),%rax
  or     %rax,-0x18(%rbp)
  mov    -0x20(%rbp),%rax
  xor    %rax,-0x28(%rbp)
  mov    -0x38(%rbp),%rax
  xor    %rax,-0x30(%rbp)
  mov    -0x18(%rbp),%rax
  not    %rax
  and    -0x28(%rbp),%rax
  mov    %rax,%rdx
  mov    -0x30(%rbp),%rax
  or     -0x50(%rbp),%rax
  and    %rdx,%rax
  and    $0xfffffffffffffffe,%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x8(%rbp),%rax
  or     %rax,-0x40(%rbp)
  mov    -0x70(%rbp),%rax
  mov    (%rax),%rax
  and    $0x1,%eax
  or     -0x8(%rbp),%rax
  mov    %rax,%rdx
  mov    -0x70(%rbp),%rax
  mov    %rdx,(%rax)
  mov    -0x78(%rbp),%rax
  shl    $0x3,%rax
  add    %rax,-0x70(%rbp)
  subl   $0x1,-0x7c(%rbp)
  cmpl   $0x0,-0x7c(%rbp)
  jle    L16
  mov    -0x50(%rbp),%rax
  mov    %rax,-0x58(%rbp)
  mov    -0x48(%rbp),%rax
  mov    %rax,-0x50(%rbp)
  mov    -0x78(%rbp),%rax
  shl    $0x3,%rax
  add    %rax,-0x68(%rbp)
  mov    -0x68(%rbp),%rax
  mov    (%rax),%rax
  mov    %rax,-0x48(%rbp)
  jmp    L12
L16:
  nop
  mov    -0x40(%rbp),%rax
  leave
  ret
```

assistant: ```c
unsigned long long int GoLGrid_evolve_strip_keep_bit_0(const unsigned long long int *in_entry, unsigned long long int *out_entry, unsigned long long int row_offset, int row_count) {
  unsigned long long int upper_word = *(in_entry - row_offset);
  unsigned long long int mid_word = *in_entry;
  in_entry += row_offset;
  unsigned long long int lower_word = *in_entry;
  unsigned long long int or_of_out_words = 0;
  while (1) {
    unsigned long long int nb_to_add = (upper_word >> 1);
    unsigned long long int nb_sum_bit_0 = nb_to_add;
    nb_to_add = upper_word;
    unsigned long long int nb_sum_bit_1 = nb_sum_bit_0 & nb_to_add;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = (upper_word << 1);
    unsigned long long int carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    nb_sum_bit_1 = nb_sum_bit_1 | carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = (mid_word >> 1);
    carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    unsigned long long int nb_sum_overflow = nb_sum_bit_1 & carry_0_to_1;
    nb_sum_bit_1 = nb_sum_bit_1 ^ carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = (mid_word << 1);
    carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    unsigned long long int carry_1_to_2 = nb_sum_bit_1 & carry_0_to_1;
    nb_sum_overflow = nb_sum_overflow | carry_1_to_2;
    nb_sum_bit_1 = nb_sum_bit_1 ^ carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = (lower_word >> 1);
    carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    carry_1_to_2 = nb_sum_bit_1 & carry_0_to_1;
    nb_sum_overflow = nb_sum_overflow | carry_1_to_2;
    nb_sum_bit_1 = nb_sum_bit_1 ^ carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = lower_word;
    carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    carry_1_to_2 = nb_sum_bit_1 & carry_0_to_1;
    nb_sum_overflow = nb_sum_overflow | carry_1_to_2;
    nb_sum_bit_1 = nb_sum_bit_1 ^ carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    nb_to_add = (lower_word << 1);
    carry_0_to_1 = nb_sum_bit_0 & nb_to_add;
    carry_1_to_2 = nb_sum_bit_1 & carry_0_to_1;
    nb_sum_overflow = nb_sum_overflow | carry_1_to_2;
    nb_sum_bit_1 = nb_sum_bit_1 ^ carry_0_to_1;
    nb_sum_bit_0 = nb_sum_bit_0 ^ nb_to_add;
    unsigned long long int out_word = (~(nb_sum_overflow)&nb_sum_bit_1 & (nb_sum_bit_0 | mid_word)) & 0xfffffffffffffffeULL;
    or_of_out_words |= out_word;
    *out_entry = (*out_entry & 0x0000000000000001ULL) | out_word;
    out_entry += row_offset;
    row_count--;
    if (row_count <= 0)
      break;
    upper_word = mid_word;
    mid_word = lower_word;
    in_entry += row_offset;
    lower_word = *in_entry;
  }
  return or_of_out_words;
}
```