user: Demonstrate the C code that generates the assembly output below:

```asm
<str_to_num>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x38(%rbp)
  movb   $0x1,-0x21(%rbp)
  movq   $0x0,-0x18(%rbp)
  movq   $0x0,-0x10(%rbp)
  movq   $0x0,-0x8(%rbp)
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x2d,%al
  jne    L121
  movb   $0xff,-0x21(%rbp)
  addq   $0x1,-0x38(%rbp)
  jmp    L146
L121:
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x2b,%al
  jne    L146
  addq   $0x1,-0x38(%rbp)
  jmp    L146
L158:
  mov    -0x18(%rbp),%rdx
  mov    %rdx,%rax
  shl    $0x2,%rax
  add    %rdx,%rax
  add    %rax,%rax
  mov    %rax,%rdx
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  sub    $0x30,%eax
  cltq
  add    %rdx,%rax
  mov    %rax,-0x18(%rbp)
  addq   $0x1,-0x38(%rbp)
L146:
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x2f,%al
  jle    L126
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x39,%al
  jle    L158
L126:
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x2e,%al
  jne    L140
  addq   $0x1,-0x38(%rbp)
  movq   $0xa,-0x8(%rbp)
  jmp    L7
L100:
  mov    -0x8(%rbp),%rdx
  mov    %rdx,%rax
  shl    $0x2,%rax
  add    %rdx,%rax
  add    %rax,%rax
  mov    %rax,-0x8(%rbp)
  mov    -0x10(%rbp),%rdx
  mov    %rdx,%rax
  shl    $0x2,%rax
  add    %rdx,%rax
  add    %rax,%rax
  mov    %rax,%rdx
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  sub    $0x30,%eax
  cltq
  add    %rdx,%rax
  mov    %rax,-0x10(%rbp)
  addq   $0x1,-0x38(%rbp)
L7:
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x2f,%al
  jle    L140
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  cmp    $0x39,%al
  jle    L100
L140:
  mov    -0x38(%rbp),%rax
  movzbl (%rax),%eax
  test   %al,%al
  je     L46
  pxor   %xmm0,%xmm0
  jmp    L67
L46:
  mov    -0x18(%rbp),%rax
  test   %rax,%rax
  js     L44
  pxor   %xmm0,%xmm0
  cvtsi2sd %rax,%xmm0
  jmp    L72
L44:
  mov    %rax,%rdx
  shr    %rdx
  and    $0x1,%eax
  or     %rax,%rdx
  pxor   %xmm0,%xmm0
  cvtsi2sd %rdx,%xmm0
  addsd  %xmm0,%xmm0
L72:
  movsd  %xmm0,-0x20(%rbp)
  cmpq   $0x0,-0x8(%rbp)
  je     L132
  mov    -0x10(%rbp),%rax
  mov    $0x0,%edx
  divq   -0x8(%rbp)
  test   %rax,%rax
  js     L134
  pxor   %xmm0,%xmm0
  cvtsi2sd %rax,%xmm0
  jmp    L12
L134:
  mov    %rax,%rdx
  shr    %rdx
  and    $0x1,%eax
  or     %rax,%rdx
  pxor   %xmm0,%xmm0
  cvtsi2sd %rdx,%xmm0
  addsd  %xmm0,%xmm0
L12:
  movsd  -0x20(%rbp),%xmm1
  addsd  %xmm1,%xmm0
  movsd  %xmm0,-0x20(%rbp)
L132:
  movsbl -0x21(%rbp),%eax
  pxor   %xmm0,%xmm0
  cvtsi2sd %eax,%xmm0
  movsd  -0x20(%rbp),%xmm1
  mulsd  %xmm1,%xmm0
  movsd  %xmm0,-0x20(%rbp)
  movsd  -0x20(%rbp),%xmm0
L67:
  movq   %xmm0,%rax
  movq   %rax,%xmm0
  pop    %rbp
  ret
```

assistant: ```c
double str_to_num(char *s) {
  double res;
  signed char sign = 1;
  unsigned long int_part = 0;
  unsigned long frc_part = 0;
  unsigned long frc_exp = 0;
  if (*s == '-') {
    sign = -1;
    s++;
  } else if (*s == '+')
    s++;
  for (; *s >= '0' && *s <= '9'; s++)
    int_part = int_part * 10 + (*s - '0');
  if (*s == '.') {
    s++;
    frc_exp = 10;
    for (; *s >= '0' && *s <= '9'; s++) {
      frc_exp *= 10;
      frc_part = frc_part * 10 + (*s - '0');
    }
  }
  if (*s != '\0')
    return 0;
  res = int_part;
  if (frc_exp > 0)
    res += frc_part / frc_exp;
  res *= sign;
  return res;
}
```