user: 请从给定的汇编指令推导出C源代码：

```asm
<sporkel_bspatch>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  mov    %rdx,%rbx
  sub    $0x48,%rsp
  test   %rdi,%rdi
  sete   %al
  test   %rdx,%rdx
  mov    %r8,0x20(%rsp)
  sete   %dl
  or     %dl,%al
  jne    L68
  test   %r8,%r8
  je     L68
  mov    %rcx,%rax
  mov    %rsi,%r13
  mov    %r9,%rbp
  mov    %rcx,%rsi
  or     %r9,%rax
  or     %r13,%rax
  js     L68
  mov    %rdi,%r15
  mov    %rbx,%rdi
  call   <sporkel_bspatch_valid_header@plt>
  test   %eax,%eax
  je     L51
  lea    0x40(%rbx),%rdi
  call   <offtin@plt>
  lea    0x80(%rbx),%rdi
  mov    %rax,%r12
  call   <offtin@plt>
  lea    0xc0(%rbx),%rdi
  mov    %rax,%r14
  call   <offtin@plt>
  mov    %rax,0x18(%rsp)
  mov    %rax,%rsi
  cmp    %rax,%rbp
  jl     L68
  lea    0x100(%rbx,%r12,8),%rax
  lea    0x100(%rbx),%rbp
  movq   $0x0,0x28(%rsp)
  mov    %rax,0x8(%rsp)
  lea    0x20(%r12,%r14,1),%rax
  xor    %r12d,%r12d
  lea    (%rbx,%rax,8),%rax
  mov    %r12,%r14
  mov    %rax,0x10(%rsp)
  test   %rsi,%rsi
  jle    L80
  nopl   0x0(%rax)
L126:
  mov    %rbp,%rdi
  call   <offtin@plt>
  lea    0x40(%rbp),%rdi
  mov    %rax,%r12
  call   <offtin@plt>
  lea    0x80(%rbp),%rdi
  add    $0xc0,%rbp
  mov    %rax,%rbx
  call   <offtin@plt>
  lea    (%r12,%r14,1),%r9
  mov    %rax,0x30(%rsp)
  cmp    0x18(%rsp),%r9
  jg     L132
  mov    0x20(%rsp),%rax
  mov    0x8(%rsp),%rsi
  mov    %r12,%rdx
  mov    %r9,0x38(%rsp)
  lea    (%rax,%r14,8),%r14
  mov    %r14,%rdi
  call   <memcpy@plt>
  mov    0x8(%rsp),%rax
  test   %r12,%r12
  mov    0x38(%rsp),%r9
  lea    (%rax,%r12,8),%rax
  mov    %rax,0x8(%rsp)
  mov    0x28(%rsp),%rax
  lea    (%r12,%rax,1),%r10
  jle    L149
  mov    %r14,%rdx
  lea    (%r12,%rax,1),%r10
  nopl   0x0(%rax)
L84:
  cmp    %rax,%r13
  jle    L105
  test   %rax,%rax
  js     L105
  mov    (%r15,%rax,8),%rcx
  add    %rcx,(%rdx)
L105:
  add    $0x1,%rax
  add    $0x8,%rdx
  cmp    %r10,%rax
  jne    L84
L149:
  mov    0x18(%rsp),%r12
  lea    (%rbx,%r9,1),%r14
  mov    %r10,0x28(%rsp)
  cmp    %r12,%r14
  jg     L132
  mov    0x20(%rsp),%rax
  mov    0x10(%rsp),%rsi
  mov    %rbx,%rdx
  lea    (%rax,%r9,8),%rdi
  call   <memcpy@plt>
  mov    0x10(%rsp),%rax
  mov    0x28(%rsp),%r10
  add    0x30(%rsp),%r10
  lea    (%rax,%rbx,8),%rax
  mov    %r10,0x28(%rsp)
  mov    %rax,0x10(%rsp)
  cmp    %r12,%r14
  jl     L126
L80:
  add    $0x48,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L132:
  mov    $0xfffffffd,%eax
L14:
  add    $0x48,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L68:
  mov    $0xffffffff,%eax
  jmp    L14
L51:
  mov    $0xfffffffe,%eax
  jmp    L14
```

assistant: ```c
int sporkel_bspatch(u_char *oldp, ssize_t oldsz, u_char *patch, ssize_t patchsz, u_char *newp, ssize_t newsz) {
  ssize_t newsize, ctrllen, datalen;
  u_char *ctrlblock, *diffblock, *extrablock;
  off_t oldpos, newpos;
  off_t ctrl[3];
  off_t i;
  if (oldp == NULL || patch == NULL || newp == NULL)
    return -1;
  if (oldsz < 0 || patchsz < 0 || newsz < 0)
    return -1;
  if (!sporkel_bspatch_valid_header(patch, patchsz))
    return -2;
  ctrllen = offtin(patch + 8);
  datalen = offtin(patch + 16);
  newsize = offtin(patch + 24);
  if (newsize > newsz)
    return -1;
  ctrlblock = patch + 32;
  diffblock = patch + 32 + ctrllen;
  extrablock = patch + 32 + ctrllen + datalen;
  oldpos = 0;
  newpos = 0;
  while (newpos < newsize) {
    ctrl[0] = offtin(ctrlblock);
    ctrl[1] = offtin(ctrlblock + 8);
    ctrl[2] = offtin(ctrlblock + 16);
    ctrlblock += 24;
    if (newpos + ctrl[0] > newsize)
      return -3;
    memcpy(newp + newpos, diffblock, ctrl[0]);
    diffblock += ctrl[0];
    for (i = 0; i < ctrl[0]; i++)
      if ((oldpos + i >= 0) && (oldpos + i < oldsz))
        newp[newpos + i] += oldp[oldpos + i];
    newpos += ctrl[0];
    oldpos += ctrl[0];
    if (newpos + ctrl[1] > newsize)
      return -3;
    memcpy(newp + newpos, extrablock, ctrl[1]);
    extrablock += ctrl[1];
    newpos += ctrl[1];
    oldpos += ctrl[2];
  };
  return 0;
}
```