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

```asm
<BSbisection>:
  endbr64
  push   %r15
  movapd %xmm5,%xmm7
  movq   %xmm0,%r15
  push   %r14
  push   %rbp
  mov    $0x65,%ebp
  push   %rbx
  mov    %edi,%ebx
  sub    $0x48,%rsp
  mov    D84(%rip),%rax
  mov    %rax,%r14
  mov    D98(%rip),%rax
  movq   %rax,%xmm8
  jmp    L35
  nopl   0x0(%rax)
L65:
  comisd D84(%rip),%xmm5
  jbe    L92
  mov    D84(%rip),%rax
  mov    $0x1,%edi
  movq   %rax,%xmm5
  nop
L24:
  movsd  %xmm7,0x30(%rsp)
  movsd  %xmm4,0x28(%rsp)
  movsd  %xmm3,0x20(%rsp)
  movsd  %xmm2,0x18(%rsp)
  movsd  %xmm1,0x10(%rsp)
  movsd  %xmm5,0x8(%rsp)
  movsd  %xmm8,0x38(%rsp)
  call   <assert@plt>
  movsd  0x8(%rsp),%xmm5
  movq   %r15,%xmm0
  mov    %ebx,%edi
  movsd  0x18(%rsp),%xmm2
  movsd  0x28(%rsp),%xmm4
  movsd  0x20(%rsp),%xmm3
  movsd  0x10(%rsp),%xmm1
  call   <BSAmericanApprox@plt>
  movsd  0x30(%rsp),%xmm7
  movsd  D40(%rip),%xmm2
  movsd  0x8(%rsp),%xmm5
  movapd %xmm7,%xmm6
  subsd  %xmm0,%xmm6
  andpd  D91(%rip),%xmm6
  comisd %xmm6,%xmm2
  jae    L29
  cmpltsd %xmm7,%xmm0
  movsd  0x38(%rsp),%xmm8
  movq   %r14,%xmm6
  sub    $0x1,%ebp
  movsd  0x10(%rsp),%xmm1
  movsd  0x18(%rsp),%xmm2
  movsd  0x20(%rsp),%xmm3
  movsd  0x28(%rsp),%xmm4
  movapd %xmm0,%xmm9
  andpd  %xmm0,%xmm6
  andnpd %xmm5,%xmm9
  andpd  %xmm0,%xmm5
  andnpd %xmm8,%xmm0
  orpd   %xmm6,%xmm9
  orpd   %xmm5,%xmm0
  movq   %xmm9,%r14
  movapd %xmm0,%xmm8
  je     L5
L35:
  movapd %xmm8,%xmm5
  mov    %ebx,%edi
  movq   %r15,%xmm0
  movsd  %xmm7,0x30(%rsp)
  movsd  %xmm8,0x38(%rsp)
  movsd  %xmm4,0x28(%rsp)
  movsd  %xmm3,0x20(%rsp)
  movsd  %xmm2,0x18(%rsp)
  movsd  %xmm1,0x10(%rsp)
  call   <BSAmericanApprox@plt>
  movsd  0x28(%rsp),%xmm4
  movq   %r14,%xmm5
  mov    %ebx,%edi
  movsd  0x20(%rsp),%xmm3
  movsd  0x18(%rsp),%xmm2
  movsd  %xmm0,0x8(%rsp)
  movq   %r15,%xmm0
  movsd  0x10(%rsp),%xmm1
  call   <BSAmericanApprox@plt>
  movsd  0x8(%rsp),%xmm9
  movsd  0x30(%rsp),%xmm7
  comisd %xmm7,%xmm9
  ja     L5
  comisd %xmm0,%xmm7
  ja     L105
  movsd  0x38(%rsp),%xmm8
  movapd %xmm7,%xmm6
  movq   %r14,%xmm5
  subsd  %xmm9,%xmm0
  subsd  %xmm9,%xmm6
  movsd  D98(%rip),%xmm1
  movsd  0x18(%rsp),%xmm2
  subsd  %xmm8,%xmm5
  movsd  0x20(%rsp),%xmm3
  movsd  0x28(%rsp),%xmm4
  mulsd  %xmm6,%xmm5
  divsd  %xmm0,%xmm5
  addsd  %xmm8,%xmm5
  comisd %xmm5,%xmm1
  movsd  0x10(%rsp),%xmm1
  jbe    L65
  mov    D98(%rip),%rax
  mov    $0x1,%edi
  movq   %rax,%xmm5
  jmp    L24
  nopw   0x0(%rax,%rax,1)
L92:
  ucomisd %xmm5,%xmm5
  jnp    L66
L99:
  xor    %edi,%edi
  jmp    L24
  nopl   (%rax)
L66:
  comisd D98(%rip),%xmm5
  jb     L99
  movsd  D84(%rip),%xmm6
  xor    %edi,%edi
  comisd %xmm5,%xmm6
  setae  %dil
  jmp    L24
  nopl   0x0(%rax)
L5:
  pxor   %xmm5,%xmm5
L29:
  add    $0x48,%rsp
  movapd %xmm5,%xmm0
  pop    %rbx
  pop    %rbp
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L105:
  mov    D84(%rip),%rax
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  movq   %rax,%xmm5
  pop    %r14
  pop    %r15
  movapd %xmm5,%xmm0
  ret
```

tool_calls: name: unpack_data
arguments: data_label: D84
type_guessed: f64[2]
name: unpack_data
arguments: data_label: D98
type_guessed: f64[2]
name: unpack_data
arguments: data_label: D40
type_guessed: f64
name: unpack_data
arguments: data_label: D91
type_guessed: qword[2]

tool: {"D84": [100.99999,1e-7]}

tool: {"D98": [1e-7,1e-6]}

tool: D40: 1e-06

tool: {"D91": [0x7fffffffffffffff,0x0000000000000000]}

assistant: ```c
extern double BSbisection(int fCall, double S, double X, double T, double r, double b, double price) {
  double vLow = 0.0000001;
  double vHigh = 100.99999, cLow, cHigh;
  double epsilon = 0.000001;
  double val, diff, vi = 0.0;
  int counter = 0;
  for (;;) {
    cLow = BSAmericanApprox(fCall, S, X, T, r, b, vLow);
    cHigh = BSAmericanApprox(fCall, S, X, T, r, b, vHigh);
    if (price < cLow)
      return 0.0;
    else if (price > cHigh)
      return 100.99999;
    vi = vLow + (price - cLow) * (vHigh - vLow) / (cHigh - cLow);
    if (vi < 0.0000001)
      vi = 0.0000001;
    else if (vi > 100.99999)
      vi = 100.99999;
    assert(((vi) == (vi)) && (vi) >= 0.0000001 && vi <= 100.99999);
    val = BSAmericanApprox(fCall, S, X, T, r, b, vi);
    diff = price - val;
    if (fabs(diff) <= epsilon)
      break;
    else if (val < price)
      vLow = vi;
    else
      vHigh = vi;
    if (counter++ >= 100)
      return 0;
  }
  return vi;
}
```