user: 请将这段汇编代码片段转换成等效的C代码:

```asm
<BN_generate_prime_ex>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  mov    %rdi,%r13
  mov    %esi,%edi
  push   %r12
  xor    %r12d,%r12d
  push   %rbp
  push   %rbx
  mov    %r9,%rbx
  sub    $0x28,%rsp
  mov    %esi,0x14(%rsp)
  mov    %edx,0x10(%rsp)
  mov    %rcx,(%rsp)
  mov    %r8,0x18(%rsp)
  call   <BN_prime_checks_for_size@plt>
  mov    %eax,0x8(%rsp)
  xor    %eax,%eax
  call   <BN_CTX_new@plt>
  test   %rax,%rax
  je     L42
  mov    %rax,%rbp
  mov    %rax,%rdi
  call   <BN_CTX_start@plt>
  mov    %rbp,%rdi
  call   <BN_CTX_get@plt>
  mov    %rax,%r15
  test   %rax,%rax
  je     L184
  movl   $0x1,0xc(%rsp)
  mov    0xc(%rsp),%eax
  cmpq   $0x0,(%rsp)
  lea    -0x1(%rax),%r14d
  je     L88
L74:
  mov    0x10(%rsp),%r9d
  mov    0x18(%rsp),%rcx
  mov    %rbp,%r8
  mov    %r13,%rdi
  mov    (%rsp),%rdx
  mov    0x14(%rsp),%esi
  test   %r9d,%r9d
  je     L149
  call   <probable_prime_dh_safe@plt>
  test   %eax,%eax
  je     L184
  xor    %esi,%esi
  mov    %r14d,%edx
  mov    %rbx,%rdi
  call   <BN_GENCB_call@plt>
  test   %eax,%eax
  je     L184
L164:
  mov    %r13,%rsi
  mov    %r15,%rdi
  call   <BN_rshift1@plt>
  test   %eax,%eax
  je     L184
  mov    0x8(%rsp),%eax
  test   %eax,%eax
  jle    L176
  xor    %r12d,%r12d
  jmp    L36
  nopl   0x0(%rax)
L207:
  test   %eax,%eax
  je     L65
  xor    %ecx,%ecx
  mov    %rbx,%r8
  mov    %rbp,%rdx
  mov    $0x1,%esi
  mov    %r15,%rdi
  call   <BN_is_prime_fasttest_ex@plt>
  cmp    $0xffffffff,%eax
  je     L184
  test   %eax,%eax
  je     L65
  mov    %r14d,%edx
  mov    $0x2,%esi
  mov    %rbx,%rdi
  call   <BN_GENCB_call@plt>
  test   %eax,%eax
  je     L184
  add    $0x1,%r12d
  cmp    %r12d,0x8(%rsp)
  je     L176
L36:
  xor    %ecx,%ecx
  mov    %rbx,%r8
  mov    %rbp,%rdx
  mov    $0x1,%esi
  mov    %r13,%rdi
  call   <BN_is_prime_fasttest_ex@plt>
  cmp    $0xffffffff,%eax
  jne    L207
  nop
L184:
  xor    %r12d,%r12d
L227:
  mov    %rbp,%rdi
  call   <BN_CTX_end@plt>
  mov    %rbp,%rdi
  call   <BN_CTX_free@plt>
L42:
  mov    %r13,%rdi
  call   <bn_check_top@plt>
  add    $0x28,%rsp
  mov    %r12d,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   (%rax)
L149:
  call   <probable_prime_dh@plt>
  test   %eax,%eax
  je     L184
  xor    %esi,%esi
  mov    %r14d,%edx
  mov    %rbx,%rdi
  call   <BN_GENCB_call@plt>
  test   %eax,%eax
  je     L184
L165:
  mov    0x8(%rsp),%esi
  xor    %ecx,%ecx
  mov    %rbx,%r8
  mov    %rbp,%rdx
  mov    %r13,%rdi
  call   <BN_is_prime_fasttest_ex@plt>
  cmp    $0xffffffff,%eax
  je     L184
  test   %eax,%eax
  jne    L176
L65:
  addl   $0x1,0xc(%rsp)
  mov    0xc(%rsp),%eax
  cmpq   $0x0,(%rsp)
  lea    -0x1(%rax),%r14d
  jne    L74
L88:
  mov    0x14(%rsp),%esi
  mov    %r13,%rdi
  call   <probable_prime@plt>
  test   %eax,%eax
  je     L184
  xor    %esi,%esi
  mov    %r14d,%edx
  mov    %rbx,%rdi
  call   <BN_GENCB_call@plt>
  test   %eax,%eax
  je     L184
  mov    0x10(%rsp),%edx
  test   %edx,%edx
  je     L165
  jmp    L164
  nopl   (%rax)
L176:
  mov    $0x1,%r12d
  jmp    L227
```

assistant: ```c
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb) {
  BIGNUM *t;
  int found = 0;
  int i, j, c1 = 0;
  BN_CTX *ctx;
  int checks = BN_prime_checks_for_size(bits);
  ctx = BN_CTX_new();
  if (ctx == NULL)
    goto err;
  BN_CTX_start(ctx);
  t = BN_CTX_get(ctx);
  if (!t)
    goto err;
loop:
  if (add == NULL) {
    if (!probable_prime(ret, bits))
      goto err;
  } else {
    if (safe) {
      if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
        goto err;
    } else {
      if (!probable_prime_dh(ret, bits, add, rem, ctx))
        goto err;
    }
  }
  if (!BN_GENCB_call(cb, 0, c1++))
    goto err;
  if (!safe) {
    i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
    if (i == -1)
      goto err;
    if (i == 0)
      goto loop;
  } else {
    if (!BN_rshift1(t, ret))
      goto err;
    for (i = 0; i < checks; i++) {
      j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb);
      if (j == -1)
        goto err;
      if (j == 0)
        goto loop;
      j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb);
      if (j == -1)
        goto err;
      if (j == 0)
        goto loop;
      if (!BN_GENCB_call(cb, 2, c1 - 1))
        goto err;
    }
  }
  found = 1;
err:
  if (ctx != NULL) {
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
  }
  bn_check_top(ret);
  return found;
}
```