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

```asm
<cat_mem_ctl>:
  endbr64
  push   %r15
  imul   %edx,%edi
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %esi,(%rsp)
  mov    %r9d,0xc(%rsp)
  mov    %fs:0x28,%rax
  mov    %rax,0x18(%rsp)
  xor    %eax,%eax
  mov    %edi,0x4(%rsp)
  movq   $0x0,0x10(%rsp)
  test   %edi,%edi
  je     L15
  movsbl %r8b,%eax
  mov    %edx,%ebx
  mov    %ecx,%r15d
  xor    %r12d,%r12d
  mov    %eax,0x8(%rsp)
  lea    0x10(%rsp),%rbp
  jmp    L86
  nopl   (%rax)
L95:
  add    $0x1,%r12d
  cmp    0x4(%rsp),%r12d
  je     L34
L86:
  mov    %r12d,%eax
  xor    %edx,%edx
  mov    %r12d,%ecx
  mov    %ebx,%esi
  div    %ebx
  mov    %r15d,%edi
  mov    %edx,%r14d
  mov    (%rsp),%edx
  mov    %eax,%r13d
  call   <mem_sz2@plt>
  push   $0x0
  mov    %r14d,%ecx
  mov    %r13d,%edx
  push   %r12
  mov    0x18(%rsp),%r8d
  lea    -0x1(%rax),%r9d
  mov    %rbp,%rdi
  lea    D12(%rip),%rsi
  xor    %eax,%eax
  call   <catf@plt>
  pop    %rdx
  pop    %rcx
  test   %rax,%rax
  jns    L95
L49:
  mov    0x10(%rsp),%rdi
  call   <free@plt>
L15:
  xor    %eax,%eax
L96:
  mov    0x18(%rsp),%rdx
  sub    %fs:0x28,%rdx
  jne    L10
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  cs nopw 0x0(%rax,%rax,1)
L34:
  movsbl 0xc(%rsp),%r14d
  mov    0x4(%rsp),%r15d
  xor    %r12d,%r12d
  lea    D3(%rip),%r13
  jmp    L32
  nopw   0x0(%rax,%rax,1)
L76:
  add    $0x1,%r12d
  cmp    %r15d,%r12d
  je     L55
L32:
  xor    %edx,%edx
  mov    %r12d,%eax
  mov    %r12d,%r9d
  mov    %r14d,%r8d
  div    %ebx
  mov    %r13,%rsi
  mov    %rbp,%rdi
  mov    %edx,%ecx
  mov    %eax,%edx
  xor    %eax,%eax
  call   <catf@plt>
  test   %rax,%rax
  jns    L76
  jmp    L49
  nopl   0x0(%rax)
L55:
  mov    0x10(%rsp),%rax
  jmp    L96
L10:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: disassemble_data
arguments: data_label: D12
type: string
name: disassemble_data
arguments: data_label: D3
type: string

tool: D12:         if(`enabled(%5$d)) begin
          en_%1$d_%2$d_%3$c <= 1;
          in_%1$d_%2$d_%3$c <= inputs_2[`in_from(%5$d)];
          addr_%1$d_%2$d_%3$c <= wraddr_%1$d_%2$d;
          wraddr_%1$d_%2$d <= wraddr_%1$d_%2$d == %4$d ? 0 : wraddr_%1$d_%2$d + 1;
        end
        else begin
          en_%1$d_%2$d_%3$c <= 0;
        end


tool: D3:         en_%1$d_%2$d_%3$c <= 1;
        addr_%1$d_%2$d_%3$c <= `raddr(%1$d);


assistant: ```c
char *cat_mem_ctl(unsigned inputs, unsigned period, unsigned n_mem, unsigned mem_sz, char write_class, char read_class) {
  char *s = NULL;
  unsigned i;
  for (i = 0; i < inputs * n_mem; ++i) {
    unsigned a = i / n_mem, b = i % n_mem;
    if (catf(&s,
             "        if(`enabled(%5$d)) begin\n"
             "          en_%1$d_%2$d_%3$c <= 1;\n"
             "          in_%1$d_%2$d_%3$c <= "
             "inputs_2[`in_from(%5$d)];\n"
             "          addr_%1$d_%2$d_%3$c <= wraddr_%1$d_%2$d;\n"
             "          wraddr_%1$d_%2$d <= wraddr_%1$d_%2$d "
             "== %4$d ? 0 : wraddr_%1$d_%2$d + 1;\n"
             "        end\n"
             "        else begin\n"
             "          en_%1$d_%2$d_%3$c <= 0;\n"
             "        end\n",
             a, b, write_class, mem_sz2(mem_sz, n_mem, period, i) - 1, i, 0) < 0)
      goto error;
  }
  for (i = 0; i < inputs * n_mem; ++i) {
    unsigned a = i / n_mem, b = i % n_mem;
    if (catf(&s,
             "        en_%1$d_%2$d_%3$c <= 1;\n"
             "        addr_%1$d_%2$d_%3$c <= `raddr(%1$d);\n",
             a, b, read_class, i) < 0)
      goto error;
  }
  return s;
error:
  free(s);
  return NULL;
}
```