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

```asm
<test8>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x20,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  lea    -0x18(%rbp),%rax
  mov    %rax,%rdi
  call   <KeyVal_new@plt>
  movzbl %al,%eax
  lea    D349(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D395(%rip),%rdx
  lea    D173(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D330(%rip),%rdx
  lea    D154(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D5(%rip),%rdx
  lea    D463(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D139(%rip),%rdx
  lea    D490(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D253(%rip),%rdx
  lea    D62(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D32(%rip),%rdx
  lea    D524(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D128(%rip),%rdx
  lea    D472(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D42(%rip),%rdx
  lea    D461(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D398(%rip),%rdx
  lea    D351(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rax
  lea    D48(%rip),%rdx
  lea    D321(%rip),%rcx
  mov    %rcx,%rsi
  mov    %rax,%rdi
  call   <KeyVal_setValue@plt>
  movzbl %al,%eax
  lea    D481(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D154(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D470(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D410(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  test   %eax,%eax
  jne    L1
  mov    -0x10(%rbp),%rax
  mov    %rax,%rsi
  lea    D539(%rip),%rax
  mov    %rax,%rdi
  call   <printf@plt>
L1:
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D463(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D178(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D562(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D490(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D184(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D200(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D62(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D105(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D216(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D524(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D470(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D243(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D472(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D128(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D599(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D461(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  movzbl %al,%eax
  lea    D271(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  mov    -0x10(%rbp),%rax
  lea    D42(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  sete   %al
  movzbl %al,%eax
  lea    D605(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x10(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x18(%rbp),%rsi
  lea    -0x10(%rbp),%rax
  mov    $0x1,%ecx
  lea    D351(%rip),%rdx
  mov    %rax,%rdi
  call   <KeyVal_getValue@plt>
  mov    %al,-0x19(%rbp)
  cmpb   $0x2,-0x19(%rbp)
  sete   %al
  movzbl %al,%eax
  lea    D511(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <ok@plt>
  mov    -0x18(%rbp),%rax
  mov    %rax,%rdi
  call   <KeyVal_delete@plt>
  movzbl %al,%eax
  lea    D429(%rip),%rdx
  mov    %rdx,%rsi
  mov    %eax,%edi
  call   <_check_err@plt>
  nop
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L0
  call   <__stack_chk_fail@plt>
L0:
  leave
  ret
```

tool_calls: name: disassemble_data
arguments: tag: D349
type_infered: string
name: disassemble_data
arguments: tag: D395
type_infered: string
name: disassemble_data
arguments: tag: D173
type_infered: string
name: disassemble_data
arguments: tag: D481
type_infered: string
name: disassemble_data
arguments: tag: D330
type_infered: string
name: disassemble_data
arguments: tag: D154
type_infered: string
name: disassemble_data
arguments: tag: D5
type_infered: string
name: disassemble_data
arguments: tag: D463
type_infered: string
name: disassemble_data
arguments: tag: D139
type_infered: string
name: disassemble_data
arguments: tag: D490
type_infered: string
name: disassemble_data
arguments: tag: D253
type_infered: string
name: disassemble_data
arguments: tag: D62
type_infered: string
name: disassemble_data
arguments: tag: D32
type_infered: string
name: disassemble_data
arguments: tag: D524
type_infered: string
name: disassemble_data
arguments: tag: D128
type_infered: string
name: disassemble_data
arguments: tag: D472
type_infered: string
name: disassemble_data
arguments: tag: D42
type_infered: string
name: disassemble_data
arguments: tag: D461
type_infered: string
name: disassemble_data
arguments: tag: D398
type_infered: string
name: disassemble_data
arguments: tag: D351
type_infered: string
name: disassemble_data
arguments: tag: D48
type_infered: string
name: disassemble_data
arguments: tag: D321
type_infered: string
name: disassemble_data
arguments: tag: D271
type_infered: string
name: disassemble_data
arguments: tag: D470
type_infered: string
name: disassemble_data
arguments: tag: D410
type_infered: string
name: disassemble_data
arguments: tag: D539
type_infered: string
name: disassemble_data
arguments: tag: D178
type_infered: string
name: disassemble_data
arguments: tag: D562
type_infered: string
name: disassemble_data
arguments: tag: D184
type_infered: string
name: disassemble_data
arguments: tag: D200
type_infered: string
name: disassemble_data
arguments: tag: D105
type_infered: string
name: disassemble_data
arguments: tag: D216
type_infered: string
name: disassemble_data
arguments: tag: D243
type_infered: string
name: disassemble_data
arguments: tag: D599
type_infered: string
name: disassemble_data
arguments: tag: D605
type_infered: string
name: disassemble_data
arguments: tag: D511
type_infered: string
name: disassemble_data
arguments: tag: D429
type_infered: string

tool: D349: KeyVal_new

tool: D395: 2

tool: D173: k1

tool: D481: KeyVal_setValue

tool: D330: asdf${k1}zxcv

tool: D154: k2

tool: D5: ${k1}zxcv

tool: D463: k3

tool: D139: asdf${k1}

tool: D490: k4

tool: D253: a${k1}b${k1}${k1}c

tool: D62: k5

tool: D32: ${k${k1}}

tool: D524: k6

tool: D128: }${

tool: D472: k7

tool: D42: ${}

tool: D461: k8

tool: D398: ${k10}

tool: D351: k9

tool: D48: ${k9}

tool: D321: k10

tool: D271: KeyVal_getValue

tool: D470: asdf2zxcv

tool: D410: 8a. variable in middle of string

tool: D539:  - got '%s' instead of 'asdf2zxcv'


tool: D178: 2zxcv

tool: D562: 8b. variable at beginning of string

tool: D184: asdf2

tool: D200: 8c. variable at end of string

tool: D105: a2b22c

tool: D216: 8d. multiple variables in the string

tool: D243: 8e. embedded variables

tool: D599: 8f. weird initial closing brace

tool: D605: 8g. empty variable name

tool: D511: 8h. recursive variables detected

tool: D429: KeyVal_delete

assistant: ```c
void test8() {
  struct KeyVal *kv;
  _check_err(KeyVal_new(&kv), "KeyVal_new");
  _check_err(KeyVal_setValue(kv, "k1", "2"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k2", "asdf${k1}zxcv"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k3", "${k1}zxcv"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k4", "asdf${k1}"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k5", "a${k1}b${k1}${k1}c"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k6", "${k${k1}}"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k7", "}${"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k8", "${}"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k9", "${k10}"), "KeyVal_setValue");
  _check_err(KeyVal_setValue(kv, "k10", "${k9}"), "KeyVal_setValue");
  char *value;
  _check_err(KeyVal_getValue(&value, kv, "k2", 1), "KeyVal_getValue");
  if (!ok(strcmp(value, "asdf2zxcv") == 0, "8a. variable in middle of string")) {
    printf(" - got '%s' instead of 'asdf2zxcv'\n", value);
  }
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k3", 1), "KeyVal_getValue");
  ok(strcmp(value, "2zxcv") == 0, "8b. variable at beginning of string");
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k4", 1), "KeyVal_getValue");
  ok(strcmp(value, "asdf2") == 0, "8c. variable at end of string");
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k5", 1), "KeyVal_getValue");
  ok(strcmp(value, "a2b22c") == 0, "8d. multiple variables in the string");
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k6", 1), "KeyVal_getValue");
  ok(strcmp(value, "asdf2zxcv") == 0, "8e. embedded variables");
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k7", 1), "KeyVal_getValue");
  ok(strcmp(value, "}${") == 0, "8f. weird initial closing brace");
  free(value);
  _check_err(KeyVal_getValue(&value, kv, "k8", 1), "KeyVal_getValue");
  ok(strcmp(value, "${}") == 0, "8g. empty variable name");
  free(value);
  unsigned char getvalue_res = KeyVal_getValue(&value, kv, "k9", 1);
  ok(getvalue_res == 2, "8h. recursive variables detected");
  _check_err(KeyVal_delete(kv), "KeyVal_delete");
}
```