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

```asm
<ber_string_test>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  push   %rbx
  sub    $0x78,%rsp
  mov    %rdi,-0x78(%rbp)
  mov    %rsi,-0x80(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x18(%rbp)
  xor    %eax,%eax
  lea    D35(%rip),%rax
  mov    %rax,-0x40(%rbp)
  lea    D30(%rip),%rax
  mov    %rax,-0x38(%rbp)
  lea    D33(%rip),%rax
  mov    %rax,-0x30(%rbp)
  lea    D16(%rip),%rax
  mov    %rax,-0x28(%rbp)
  lea    D41(%rip),%rax
  mov    %rax,%rdi
  call   <puts@plt>
  movl   $0x0,-0x68(%rbp)
  jmp    L14
L32:
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rax
  mov    %rax,%rsi
  lea    D37(%rip),%rax
  mov    %rax,%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  movl   $0x0,-0x64(%rbp)
  jmp    L0
L42:
  cmpl   $0x0,-0x64(%rbp)
  jne    L28
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rdx
  mov    -0x80(%rbp),%rax
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <ber_encode_string@plt>
  mov    %rax,-0x50(%rbp)
  jmp    L16
L28:
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  mov    %rax,%rdx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rcx
  mov    -0x80(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <ber_encode_string_len@plt>
  mov    %rax,-0x50(%rbp)
L16:
  mov    -0x50(%rbp),%rax
  lea    0x4(%rax),%rcx
  lea    -0x6c(%rbp),%rdx
  lea    -0x60(%rbp),%rax
  mov    %rax,%rsi
  mov    %rcx,%rdi
  call   <ber_decode_string_len_buffer@plt>
  mov    %rax,-0x48(%rbp)
  mov    -0x6c(%rbp),%eax
  movslq %eax,%rbx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  cmp    %rax,%rbx
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x6c(%rbp),%edx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rcx
  mov    -0x60(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <strncmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x80(%rbp),%rax
  add    $0x4,%rax
  cmp    %rax,-0x48(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x50(%rbp),%rax
  lea    0x4(%rax),%rcx
  lea    -0x58(%rbp),%rax
  mov    $0x80,%edx
  mov    %rax,%rsi
  mov    %rcx,%rdi
  call   <ber_decode_string_alloc@plt>
  mov    %rax,-0x48(%rbp)
  mov    -0x58(%rbp),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  mov    %rax,%rbx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  cmp    %rax,%rbx
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x6c(%rbp),%edx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rcx
  mov    -0x60(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <strncmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x80(%rbp),%rax
  add    $0x4,%rax
  cmp    %rax,-0x48(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x58(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x50(%rbp),%rax
  lea    0x4(%rax),%rdi
  lea    -0x70(%rbp),%rdx
  lea    -0x60(%rbp),%rax
  mov    %rdx,%rcx
  mov    $0x80,%edx
  mov    %rax,%rsi
  call   <ber_decode_string_buffer@plt>
  mov    %rax,-0x48(%rbp)
  mov    -0x60(%rbp),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  mov    %rax,%rbx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rax
  mov    %rax,%rdi
  call   <strlen@plt>
  cmp    %rax,%rbx
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x6c(%rbp),%edx
  mov    -0x68(%rbp),%eax
  cltq
  mov    -0x40(%rbp,%rax,8),%rcx
  mov    -0x60(%rbp),%rax
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <strncmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  mov    -0x80(%rbp),%rax
  add    $0x4,%rax
  cmp    %rax,-0x48(%rbp)
  sete   %al
  movzbl %al,%eax
  mov    %eax,%edi
  call   <assert@plt>
  addl   $0x1,-0x64(%rbp)
L0:
  cmpl   $0x1,-0x64(%rbp)
  jle    L42
  mov    -0x80(%rbp),%rax
  sub    -0x50(%rbp),%rax
  sar    $0x2,%rax
  mov    %eax,%edx
  mov    -0x50(%rbp),%rax
  add    $0x4,%rax
  mov    %rax,%rsi
  lea    D65(%rip),%rax
  mov    %rax,%rdi
  call   <hexdump@plt>
  addl   $0x1,-0x68(%rbp)
L14:
  mov    -0x68(%rbp),%eax
  cmp    $0x3,%eax
  jbe    L32
  mov    $0xa,%edi
  call   <putchar@plt>
  nop
  mov    -0x18(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L5
  call   <__stack_chk_fail@plt>
L5:
  mov    -0x8(%rbp),%rbx
  leave
  ret
```

tool_calls: name: retrieve_data
arguments: tag: D35
type_infered: string
name: retrieve_data
arguments: tag: D30
type_infered: string
name: retrieve_data
arguments: tag: D33
type_infered: string
name: retrieve_data
arguments: tag: D16
type_infered: string
name: retrieve_data
arguments: tag: D41
type_infered: string
name: retrieve_data
arguments: tag: D37
type_infered: string
name: retrieve_data
arguments: tag: D65
type_infered: string

tool: D35: a

tool: D30: ab

tool: D33: test123

tool: D16: testing_longer_name

tool: D41: # Testing BER string coding

tool: D37: ber_encode_string("%s")

tool: 

assistant: ```c
void ber_string_test(uint8_t *buf, uint8_t *buf_end) {
  uint8_t *enc_out, *dec_out;
  const char *values[] = {"a", "ab", "test123", "testing_longer_name"};
  const char *str;
  char *astr;
  uint8_t next;
  uint32_t i, enc_method, str_len;
  printf("# Testing BER string coding\n");
  for (i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {
    printf("ber_encode_string(\"%s\")", values[i]);
    for (enc_method = 0; enc_method < 2; ++enc_method) {
      if (enc_method == 0) {
        enc_out = ber_encode_string(buf_end, values[i]);
      } else {
        enc_out = ber_encode_string_len(buf_end, values[i], strlen(values[i]));
      }
      dec_out = ber_decode_string_len_buffer(enc_out + 1, &str, &str_len);
      assert(str_len == strlen(values[i]));
      assert(strncmp(str, values[i], str_len) == 0);
      assert(dec_out == buf_end + 1);
      dec_out = ber_decode_string_alloc(enc_out + 1, &astr, 128);
      assert(strlen(astr) == strlen(values[i]));
      assert(strncmp(str, values[i], str_len) == 0);
      assert(dec_out == buf_end + 1);
      free(astr);
      dec_out = ber_decode_string_buffer(enc_out + 1, &str, 128, &next);
      assert(strlen(str) == strlen(values[i]));
      assert(strncmp(str, values[i], str_len) == 0);
      assert(dec_out == buf_end + 1);
    }
    hexdump("", enc_out + 1, buf_end - enc_out);
  }
  printf("\n");
}
```