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

```asm
<string_decode_base16>:
  endbr64
  test   %rdi,%rdi
  je     L139
  push   %rbp
  xor    %eax,%eax
  mov    %rsi,%rbp
  push   %rbx
  sub    $0x8,%rsp
  test   %rsi,%rsi
  je     L219
  mov    %rdi,%rbx
  call   <strlen@plt>
  movb   $0x0,0x0(%rbp)
  mov    %eax,%edi
  shr    $0x1f,%eax
  add    %edi,%eax
  sar    %eax
  cmp    $0x1,%edi
  jle    L234
  mov    %eax,%edx
  lea    (%rbx,%rdx,2),%rcx
  cmp    %rcx,%rbp
  setae  %cl
  add    %rbp,%rdx
  cmp    %rdx,%rbx
  setae  %dl
  or     %dl,%cl
  je     L3
  cmp    $0x1f,%edi
  jle    L3
  mov    %eax,%ecx
  xor    %edx,%edx
  pxor   %xmm4,%xmm4
  movdqa D81(%rip),%xmm14
  movdqa D53(%rip),%xmm13
  shr    $0x4,%ecx
  movdqa D70(%rip),%xmm12
  movdqa D8(%rip),%xmm11
  shl    $0x4,%rcx
  movdqa D59(%rip),%xmm10
  movdqa D37(%rip),%xmm8
  nopw   0x0(%rax,%rax,1)
L176:
  movdqu (%rbx,%rdx,2),%xmm0
  movdqu 0x10(%rbx,%rdx,2),%xmm1
  movdqu 0x10(%rbx,%rdx,2),%xmm2
  movdqa D32(%rip),%xmm3
  pand   %xmm14,%xmm1
  pand   %xmm14,%xmm0
  packuswb %xmm1,%xmm0
  movdqu (%rbx,%rdx,2),%xmm1
  psrlw  $0x8,%xmm2
  movdqa %xmm0,%xmm6
  paddb  %xmm0,%xmm3
  movdqa %xmm0,%xmm5
  psrlw  $0x8,%xmm1
  paddb  %xmm13,%xmm6
  paddb  %xmm11,%xmm5
  packuswb %xmm2,%xmm1
  movdqa %xmm0,%xmm2
  movdqa %xmm6,%xmm9
  paddb  %xmm12,%xmm2
  psubusb %xmm10,%xmm9
  movdqa %xmm2,%xmm7
  pcmpeqb %xmm4,%xmm9
  paddb  %xmm5,%xmm5
  pminub %xmm8,%xmm7
  paddb  %xmm6,%xmm6
  pcmpeqb %xmm2,%xmm7
  paddb  %xmm5,%xmm5
  psubusb %xmm8,%xmm2
  pcmpeqb %xmm4,%xmm2
  movdqa %xmm9,%xmm15
  paddb  %xmm6,%xmm6
  pcmpeqb %xmm4,%xmm15
  paddb  %xmm5,%xmm5
  paddb  %xmm6,%xmm6
  paddb  %xmm5,%xmm5
  paddb  D27(%rip),%xmm0
  pcmpeqb %xmm4,%xmm2
  paddb  %xmm6,%xmm6
  pand   %xmm15,%xmm7
  pand   %xmm9,%xmm6
  pandn  %xmm5,%xmm9
  por    %xmm6,%xmm9
  paddb  %xmm0,%xmm0
  pand   %xmm7,%xmm5
  pand   %xmm2,%xmm15
  movdqa %xmm3,%xmm2
  pandn  %xmm9,%xmm7
  pminub %xmm8,%xmm2
  paddb  %xmm0,%xmm0
  por    %xmm5,%xmm7
  pcmpeqb %xmm3,%xmm2
  psubusb %xmm8,%xmm3
  paddb  %xmm0,%xmm0
  pcmpeqb %xmm4,%xmm3
  paddb  %xmm0,%xmm0
  movdqa %xmm1,%xmm9
  paddb  %xmm13,%xmm9
  pand   %xmm15,%xmm2
  movdqa %xmm9,%xmm6
  pcmpeqb %xmm4,%xmm3
  pand   %xmm2,%xmm0
  psubusb %xmm10,%xmm6
  pcmpeqb %xmm4,%xmm6
  pand   %xmm15,%xmm3
  pandn  %xmm7,%xmm3
  movdqa %xmm6,%xmm15
  movdqa %xmm1,%xmm7
  pandn  %xmm3,%xmm2
  movdqa %xmm1,%xmm3
  paddb  %xmm11,%xmm7
  paddb  %xmm12,%xmm3
  pcmpeqb %xmm4,%xmm15
  por    %xmm0,%xmm2
  movdqa D32(%rip),%xmm0
  movdqa %xmm3,%xmm5
  por    %xmm2,%xmm7
  por    %xmm2,%xmm9
  pminub %xmm8,%xmm5
  paddb  %xmm1,%xmm0
  pand   %xmm6,%xmm9
  pcmpeqb %xmm3,%xmm5
  psubusb %xmm8,%xmm3
  pandn  %xmm7,%xmm6
  pcmpeqb %xmm4,%xmm3
  por    %xmm9,%xmm6
  paddb  D27(%rip),%xmm1
  pand   %xmm15,%xmm5
  por    %xmm2,%xmm1
  pcmpeqb %xmm4,%xmm3
  pand   %xmm5,%xmm7
  pandn  %xmm6,%xmm5
  por    %xmm7,%xmm5
  pand   %xmm15,%xmm3
  movdqa %xmm0,%xmm15
  pminub %xmm8,%xmm15
  pcmpeqb %xmm0,%xmm15
  psubusb %xmm8,%xmm0
  pcmpeqb %xmm4,%xmm0
  pand   %xmm3,%xmm15
  pcmpeqb %xmm4,%xmm0
  pand   %xmm15,%xmm1
  pand   %xmm3,%xmm0
  pand   %xmm0,%xmm2
  pandn  %xmm5,%xmm0
  por    %xmm2,%xmm0
  pandn  %xmm0,%xmm15
  por    %xmm1,%xmm15
  movups %xmm15,0x0(%rbp,%rdx,1)
  add    $0x10,%rdx
  cmp    %rcx,%rdx
  jne    L176
  mov    %eax,%edx
  and    $0xfffffff0,%edx
  mov    %edx,%r8d
  cmp    %edx,%eax
  je     L196
  movslq %edx,%rdx
  sub    %rdx,%r8
  add    %rbp,%r8
  jmp    L145
  nopl   0x0(%rax,%rax,1)
L92:
  or     %r9d,%ecx
L184:
  mov    %cl,(%r8,%rdx,1)
  add    $0x1,%rdx
  cmp    %edx,%eax
  jle    L196
L145:
  movzbl (%rbx,%rdx,2),%esi
  lea    -0x30(%rsi),%r9d
  mov    %r9d,%ecx
  shl    $0x4,%ecx
  cmp    $0x9,%r9b
  jbe    L6
  lea    -0x61(%rsi),%ecx
  cmp    $0x5,%cl
  ja     L193
  sub    $0x57,%esi
  mov    %esi,%ecx
  shl    $0x4,%ecx
L6:
  movzbl 0x1(%rbx,%rdx,2),%esi
  lea    -0x30(%rsi),%r9d
  cmp    $0x9,%r9b
  jbe    L92
  lea    -0x61(%rsi),%r9d
  cmp    $0x5,%r9b
  ja     L170
  sub    $0x57,%esi
  or     %esi,%ecx
  mov    %cl,(%r8,%rdx,1)
  add    $0x1,%rdx
  cmp    %edx,%eax
  jg     L145
  nopl   (%rax)
L196:
  lea    -0x1(%rax),%edx
  mov    $0x1,%ecx
  add    $0x1,%rdx
  cmp    $0x1,%edi
  cmovle %rcx,%rdx
  add    %rdx,%rbp
  test   %eax,%eax
  mov    $0x1,%edx
  cmovle %edx,%eax
L76:
  movb   $0x0,0x0(%rbp)
L219:
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  ret
  nopl   0x0(%rax,%rax,1)
L193:
  lea    -0x41(%rsi),%r9d
  sub    $0x37,%esi
  xor    %ecx,%ecx
  shl    $0x4,%esi
  cmp    $0x6,%r9b
  cmovb  %esi,%ecx
  jmp    L6
  nopl   (%rax)
L170:
  lea    -0x41(%rsi),%r9d
  sub    $0x37,%esi
  or     %ecx,%esi
  cmp    $0x6,%r9b
  cmovb  %esi,%ecx
  jmp    L184
  nopl   (%rax)
L139:
  xor    %eax,%eax
  ret
  nopl   0x0(%rax,%rax,1)
L3:
  xor    %ecx,%ecx
  jmp    L96
  nopl   0x0(%rax)
L13:
  or     %r8d,%edx
L191:
  mov    %dl,0x0(%rbp,%rcx,1)
  add    $0x1,%rcx
  cmp    %ecx,%eax
  jle    L196
L96:
  movzbl (%rbx,%rcx,2),%esi
  lea    -0x30(%rsi),%edx
  cmp    $0x9,%dl
  jbe    L56
  lea    -0x61(%rsi),%edx
  cmp    $0x5,%dl
  ja     L59
  lea    -0x57(%rsi),%edx
L56:
  shl    $0x4,%edx
L88:
  movzbl 0x1(%rbx,%rcx,2),%esi
  lea    -0x30(%rsi),%r8d
  cmp    $0x9,%r8b
  jbe    L13
  lea    -0x61(%rsi),%r8d
  cmp    $0x5,%r8b
  ja     L31
  sub    $0x57,%esi
  or     %esi,%edx
  jmp    L191
  nopl   0x0(%rax)
L59:
  lea    -0x41(%rsi),%r8d
  sub    $0x37,%esi
  xor    %edx,%edx
  shl    $0x4,%esi
  cmp    $0x6,%r8b
  cmovb  %esi,%edx
  jmp    L88
  nopl   (%rax)
L31:
  lea    -0x41(%rsi),%r8d
  sub    $0x37,%esi
  or     %edx,%esi
  cmp    $0x6,%r8b
  cmovb  %esi,%edx
  jmp    L191
  nopw   0x0(%rax,%rax,1)
L234:
  xor    %eax,%eax
  jmp    L76
```

tool_calls: name: disassemble_data
arguments: tag: D81
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D53
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D70
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D8
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D59
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D37
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D32
type_guessed: byte[16]
name: disassemble_data
arguments: tag: D27
type_guessed: byte[16]

tool: {"D81": [0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00]}

tool: {"D53": [0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0,0xd0]}

tool: {"D70": [0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f,0x9f]}

tool: {"D8": [0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9,0xa9]}

tool: {"D59": [0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09]}

tool: {"D37": [0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05]}

tool: {"D32": [0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf]}

tool: {"D27": [0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9,0xc9]}

assistant: ```c
int string_decode_base16(const char *from, char *to) {
  int length, to_length, i, pos;
  unsigned char *ptr_to, value;
  if (!from || !to)
    return 0;
  length = strlen(from) / 2;
  ptr_to = (unsigned char *)to;
  ptr_to[0] = '\0';
  to_length = 0;
  for (i = 0; i < length; i++) {
    pos = i * 2;
    value = 0;
    if ((from[pos] >= '0') && (from[pos] <= '9'))
      value |= (from[pos] - '0') << 4;
    else if ((from[pos] >= 'a') && (from[pos] <= 'f'))
      value |= (from[pos] - 'a' + 10) << 4;
    else if ((from[pos] >= 'A') && (from[pos] <= 'F'))
      value |= (from[pos] - 'A' + 10) << 4;
    pos++;
    if ((from[pos] >= '0') && (from[pos] <= '9'))
      value |= from[pos] - '0';
    else if ((from[pos] >= 'a') && (from[pos] <= 'f'))
      value |= from[pos] - 'a' + 10;
    else if ((from[pos] >= 'A') && (from[pos] <= 'F'))
      value |= from[pos] - 'A' + 10;
    ptr_to[0] = value;
    ptr_to++;
    to_length++;
  }
  ptr_to[0] = '\0';
  return to_length;
}
```