user: 请显示与下面列出的汇编代码相匹配的C语言实现：

```asm
<CheckX509IpAddress>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %rdi,0x10(%rsp)
  mov    %rsi,0x8(%rsp)
  mov    %edx,(%rsp)
  test   %rdi,%rdi
  je     L118
  mov    %rcx,%r14
  mov    %r8d,%r12d
  test   %r8d,%r8d
  jle    L6
  test   %rcx,%rcx
  je     L91
L6:
  test   %r12d,%r12d
  js     L197
  mov    (%rsp),%eax
  test   %eax,%eax
  js     L95
  cmpq   $0x0,0x8(%rsp)
  je     L43
  mov    D26(%rip),%rax
  mov    0x10(%rsp),%rdi
  xor    %edx,%edx
  mov    (%rax),%ecx
  mov    D14(%rip),%rax
  mov    (%rax),%ebp
  mov    D11(%rip),%rax
  mov    %ecx,0x4(%rsp)
  xor    %ecx,%ecx
  mov    (%rax),%esi
  call   <X509_get_ext_d2i@plt>
  mov    %rax,%r13
  test   %rax,%rax
  je     L151
  mov    %rax,%rdi
  call   <sk_GENERAL_NAME_num@plt>
  mov    %eax,%ebx
  test   %eax,%eax
  jle    L129
  movslq (%rsp),%rax
  xor    %r15d,%r15d
  mov    %rax,0x18(%rsp)
  jmp    L123
  nopl   0x0(%rax)
L144:
  add    $0x1,%r15d
  cmp    %r15d,%ebx
  je     L129
L123:
  mov    %r15d,%esi
  mov    %r13,%rdi
  call   <sk_GENERAL_NAME_value@plt>
  cmp    %ebp,(%rax)
  jne    L144
  mov    0x8(%rax),%rax
  test   %rax,%rax
  je     L144
  mov    0x4(%rax),%esi
  test   %esi,%esi
  je     L144
  mov    (%rsp),%ecx
  cmp    %ecx,(%rax)
  jne    L144
  mov    0x18(%rsp),%rdx
  mov    0x8(%rsp),%rdi
  call   <memcmp@plt>
  test   %eax,%eax
  jne    L144
  mov    %r13,%rdi
  call   <GENERAL_NAMES_free@plt>
L35:
  add    $0x28,%rsp
  mov    $0x1,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  cs nopw 0x0(%rax,%rax,1)
L129:
  mov    %r13,%rdi
  call   <GENERAL_NAMES_free@plt>
L151:
  mov    0x10(%rsp),%rdi
  mov    $0xffffffff,%r13d
  call   <X509_get_subject_name@plt>
  mov    %rax,%rbx
  test   %rax,%rax
  jne    L7
L186:
  xor    %eax,%eax
L204:
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L189:
  mov    %r13d,%esi
  mov    %rbx,%rdi
  call   <X509_NAME_get_entry@plt>
  mov    %rax,%rdi
  call   <X509_NAME_ENTRY_get_data@plt>
  xor    %ecx,%ecx
  mov    %r12d,%edx
  mov    %r14,%rsi
  mov    %rax,%rdi
  call   <CheckX509HostnameMatch@plt>
  test   %rax,%rax
  jne    L35
L7:
  mov    0x4(%rsp),%esi
  mov    %r13d,%edx
  mov    %rbx,%rdi
  call   <X509_NAME_get_index_by_NID@plt>
  mov    %eax,%r13d
  test   %eax,%eax
  jns    L189
  jmp    L186
L91:
  mov    $0xfffffffd,%eax
  jmp    L204
L43:
  mov    $0xfffffffa,%eax
  jmp    L204
L197:
  mov    $0xfffffffc,%eax
  jmp    L204
L95:
  mov    $0xfffffffb,%eax
  jmp    L204
L118:
  mov    $0xfffffffe,%eax
  jmp    L204
```

assistant: ```c
int CheckX509IpAddress(X509 *x509, const unsigned char *addressBytes, int addressBytesLen, const char *hostname, int cchHostname) {
  if (!x509)
    return -2;
  if (cchHostname > 0 && !hostname)
    return -3;
  if (cchHostname < 0)
    return -4;
  if (addressBytesLen < 0)
    return -5;
  if (!addressBytes)
    return -6;
  int subjectNid = NID_commonName;
  int sanGenType = GEN_IPADD;
  GENERAL_NAMES *san = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
  int success = 0;
  if (san) {
    int i;
    int count = sk_GENERAL_NAME_num(san);
    for (i = 0; i < count; ++i) {
      GENERAL_NAME *sanEntry = sk_GENERAL_NAME_value(san, i);
      ASN1_OCTET_STRING *ipAddr;
      if (sanEntry->type != sanGenType) {
        continue;
      }
      ipAddr = sanEntry->d.iPAddress;
      if (!ipAddr || !ipAddr->data || ipAddr->length != addressBytesLen) {
        continue;
      }
      if (!memcmp(addressBytes, ipAddr->data, (size_t)addressBytesLen)) {
        success = 1;
        break;
      }
    }
    GENERAL_NAMES_free(san);
  }
  if (!success) {
    X509_NAME *subject = X509_get_subject_name(x509);
    if (subject) {
      int i = -1;
      while ((i = X509_NAME_get_index_by_NID(subject, subjectNid, i)) >= 0) {
        X509_NAME_ENTRY *nameEnt = X509_NAME_get_entry(subject, i);
        ASN1_STRING *cn = X509_NAME_ENTRY_get_data(nameEnt);
        if (CheckX509HostnameMatch(cn, hostname, cchHostname, 0)) {
          success = 1;
          break;
        }
      }
    }
  }
  return success;
}
```