user: Converte this assembly snippet into its equivalent C code:

```asm
<test_blocks>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x830,%rsp
  mov    %edi,-0x824(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  movl   $0x0,-0x814(%rbp)
L18:
  cmpl   $0x0,-0x814(%rbp)
  jne    L0
  movl   $0x0,-0x818(%rbp)
  jmp    L6
L0:
  mov    -0x814(%rbp),%eax
  sub    $0x1,%eax
  mov    $0x1,%edx
  mov    %eax,%ecx
  shl    %cl,%edx
  mov    %edx,%eax
  mov    %eax,-0x818(%rbp)
L6:
  mov    -0x818(%rbp),%eax
  cmp    -0x824(%rbp),%eax
  jbe    L93
  mov    -0x824(%rbp),%eax
  mov    %eax,-0x818(%rbp)
L93:
  mov    -0x818(%rbp),%eax
  shl    $0xa,%eax
  mov    %eax,%edx
  mov    -0x818(%rbp),%eax
  mov    %eax,%esi
  lea    D8(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x814(%rbp),%ecx
  lea    -0x810(%rbp),%rax
  mov    $0xffffffff,%edx
  mov    %ecx,%esi
  mov    %rax,%rdi
  call   <data_fill@plt>
  lea    -0x810(%rbp),%rdx
  mov    -0x818(%rbp),%eax
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <block_write@plt>
  mov    -0x818(%rbp),%eax
  cmp    -0x824(%rbp),%eax
  je     L91
  addl   $0x1,-0x814(%rbp)
  jmp    L18
L91:
  nop
  movl   $0x0,-0x814(%rbp)
L26:
  cmpl   $0x0,-0x814(%rbp)
  jne    L29
  movl   $0x0,-0x818(%rbp)
  jmp    L7
L29:
  mov    -0x814(%rbp),%eax
  sub    $0x1,%eax
  mov    $0x1,%edx
  mov    %eax,%ecx
  shl    %cl,%edx
  mov    %edx,%eax
  mov    %eax,-0x818(%rbp)
L7:
  mov    -0x818(%rbp),%eax
  cmp    -0x824(%rbp),%eax
  jbe    L81
  mov    -0x824(%rbp),%eax
  mov    %eax,-0x818(%rbp)
L81:
  mov    -0x818(%rbp),%eax
  shl    $0xa,%eax
  mov    %eax,%edx
  mov    -0x818(%rbp),%eax
  mov    %eax,%esi
  lea    D16(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    -0x814(%rbp),%ecx
  lea    -0x810(%rbp),%rax
  mov    $0xffffffff,%edx
  mov    %ecx,%esi
  mov    %rax,%rdi
  call   <data_fill@plt>
  lea    -0x410(%rbp),%rdx
  mov    -0x818(%rbp),%eax
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <block_read@plt>
  lea    -0x410(%rbp),%rdx
  lea    -0x810(%rbp),%rax
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <data_check@plt>
  mov    -0x818(%rbp),%eax
  cmp    -0x824(%rbp),%eax
  je     L98
  addl   $0x1,-0x814(%rbp)
  jmp    L26
L98:
  nop
  lea    D9(%rip),%rax
  mov    %rax,%rdi
  call   <puts@plt>
  nop
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L32
  call   <__stack_chk_fail@plt>
L32:
  leave
  ret
```

tool_calls: name: extract_symbolic_data
arguments: tag: D8
datatype: string
name: extract_symbolic_data
arguments: tag: D16
datatype: string
name: extract_symbolic_data
arguments: tag: D9
datatype: string

tool: D8: Writing block %u at address %06X.


tool: D16: Reading block %u at address %06X.


tool: D9: Done.

assistant: ```c
void test_blocks(unsigned blocknum) {
  unsigned char data[1024];
  unsigned char rdata[1024];
  unsigned bn;
  int i;
  for (i = 0;; i++) {
    if (i == 0)
      bn = 0;
    else
      bn = 1 << (i - 1);
    if (bn > blocknum)
      bn = blocknum;
    printf("Writing block %u at address %06X.\n", bn, bn * 1024);
    data_fill(data, i, ~0);
    block_write(bn, data);
    if (bn == blocknum)
      break;
  }
  for (i = 0;; i++) {
    if (i == 0)
      bn = 0;
    else
      bn = 1 << (i - 1);
    if (bn > blocknum)
      bn = blocknum;
    printf("Reading block %u at address %06X.\n", bn, bn * 1024);
    data_fill(data, i, ~0);
    block_read(bn, rdata);
    data_check(data, rdata);
    if (bn == blocknum)
      break;
  }
  printf("Done.\n");
}
```