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

```asm
<MD4_Final>:
  endbr64
  push   %r13
  push   %r12
  mov    %rdi,%r12
  push   %rbp
  push   %rbx
  mov    %rsi,%rbx
  sub    $0x8,%rsp
  mov    0x30(%rsi),%r13
  mov    (%rsi),%rax
  mov    D2(%rip),%rbp
  movb   $0x80,0x0(%r13,%rax,1)
  add    $0x1,%rax
  mov    0x0(%rbp),%edx
  lea    0x0(%r13,%rax,1),%rdi
  mov    %eax,%esi
  lea    -0x8(%rdx),%ecx
  movslq %ecx,%rcx
  cmp    %rax,%rcx
  jb     L0
L19:
  sub    %esi,%edx
  xor    %esi,%esi
  sub    $0x8,%edx
  call   <memset@plt>
  movslq 0x0(%rbp),%rax
  mov    0x8(%rbx),%edx
  mov    %rbx,%rdi
  lea    -0x8(%r13,%rax,1),%rax
  mov    %dl,(%rax)
  mov    0x8(%rbx),%edx
  lea    0x8(%rax),%r13
  mov    %dh,0x1(%rax)
  movswl 0xa(%rbx),%edx
  mov    %dl,0x2(%rax)
  movsbl 0xb(%rbx),%edx
  mov    %dl,0x3(%rax)
  mov    0xc(%rbx),%edx
  mov    %dl,0x4(%rax)
  mov    0xc(%rbx),%edx
  mov    %dh,0x5(%rax)
  movswl 0xe(%rbx),%edx
  mov    %dl,0x6(%rax)
  movsbl 0xf(%rbx),%edx
  mov    %dl,0x7(%rax)
  movslq 0x0(%rbp),%rax
  mov    $0x1,%edx
  sub    %rax,%r13
  mov    %r13,%rsi
  call   <md4_block_data_order@plt>
  movq   $0x0,(%rbx)
  mov    0x0(%rbp),%esi
  mov    %r13,%rdi
  call   <OPENSSL_cleanse@plt>
  mov    0x10(%rbx),%eax
  mov    %eax,(%r12)
  mov    0x18(%rbx),%eax
  mov    %eax,0x4(%r12)
  mov    0x20(%rbx),%eax
  mov    %eax,0x8(%r12)
  mov    0x28(%rbx),%eax
  mov    %eax,0xc(%r12)
  add    $0x8,%rsp
  mov    $0x1,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  ret
  nopl   0x0(%rax)
L0:
  sub    %eax,%edx
  xor    %esi,%esi
  call   <memset@plt>
  mov    $0x1,%edx
  mov    %r13,%rsi
  mov    %rbx,%rdi
  call   <md4_block_data_order@plt>
  mov    0x0(%rbp),%edx
  mov    %r13,%rdi
  xor    %esi,%esi
  jmp    L19
```

assistant: ```c
int MD4_Final(unsigned char *md, MD4_CTX *c) {
  unsigned char *p = (unsigned char *)c->data;
  size_t n = c->num;
  p[n] = 0x80;
  n++;
  if (n > (MD4_CBLOCK - 8)) {
    memset(p + n, 0, MD4_CBLOCK - n);
    n = 0;
    md4_block_data_order(c, p, 1);
  }
  memset(p + n, 0, MD4_CBLOCK - 8 - n);
  p += MD4_CBLOCK - 8;
  (void)(*((p)++) = (unsigned char)(((c->Nl)) & 0xff), *((p)++) = (unsigned char)(((c->Nl) >> 8) & 0xff), *((p)++) = (unsigned char)(((c->Nl) >> 16) & 0xff), *((p)++) = (unsigned char)(((c->Nl) >> 24) & 0xff), c->Nl);
  (void)(*((p)++) = (unsigned char)(((c->Nh)) & 0xff), *((p)++) = (unsigned char)(((c->Nh) >> 8) & 0xff), *((p)++) = (unsigned char)(((c->Nh) >> 16) & 0xff), *((p)++) = (unsigned char)(((c->Nh) >> 24) & 0xff), c->Nh);
  p -= MD4_CBLOCK;
  md4_block_data_order(c, p, 1);
  c->num = 0;
  OPENSSL_cleanse(p, MD4_CBLOCK);
  do {
    unsigned long ll;
    ll = (c)->A;
    (void)(*(((md))++) = (unsigned char)(((ll)) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 8) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 16) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 24) & 0xff), ll);
    ll = (c)->B;
    (void)(*(((md))++) = (unsigned char)(((ll)) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 8) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 16) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 24) & 0xff), ll);
    ll = (c)->C;
    (void)(*(((md))++) = (unsigned char)(((ll)) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 8) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 16) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 24) & 0xff), ll);
    ll = (c)->D;
    (void)(*(((md))++) = (unsigned char)(((ll)) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 8) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 16) & 0xff), *(((md))++) = (unsigned char)(((ll) >> 24) & 0xff), ll);
  } while (0);
  return 1;
}
```