// File: wangyu-[P]pwdgen/lib/pbkdf2-sha256.cpp
// Function: sha2_finish(sha2_context*, unsigned char*)
void sha2_finish( sha2_context *ctx, unsigned char output[32] )
{
    unsigned long last, padn;
    unsigned long high, low;
    unsigned char msglen[8];

    high = ( ctx->total[0] >> 29 )
         | ( ctx->total[1] <<  3 );
    low  = ( ctx->total[0] <<  3 );

    PUT_ULONG_BE( high, msglen, 0 );
    PUT_ULONG_BE( low,  msglen, 4 );

    last = ctx->total[0] & 0x3F;
    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );

    sha2_update( ctx, (unsigned char *) sha2_padding, padn );
    sha2_update( ctx, msglen, 8 );

    PUT_ULONG_BE( ctx->state[0], output,  0 );
    PUT_ULONG_BE( ctx->state[1], output,  4 );
    PUT_ULONG_BE( ctx->state[2], output,  8 );
    PUT_ULONG_BE( ctx->state[3], output, 12 );
    PUT_ULONG_BE( ctx->state[4], output, 16 );
    PUT_ULONG_BE( ctx->state[5], output, 20 );
    PUT_ULONG_BE( ctx->state[6], output, 24 );

    if( ctx->is224 == 0 )
        PUT_ULONG_BE( ctx->state[7], output, 28 );
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movq 0x40(%rsp), %rax
movq (%rax), %rax
shrq $0x1d, %rax
movq 0x40(%rsp), %rcx
movq 0x8(%rcx), %rcx
shlq $0x3, %rcx
orq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x40(%rsp), %rax
movq (%rax), %rax
shlq $0x3, %rax
movq %rax, 0x18(%rsp)
movq 0x20(%rsp), %rax
shrq $0x18, %rax
movb %al, 0x10(%rsp)
movq 0x20(%rsp), %rax
shrq $0x10, %rax
movb %al, 0x11(%rsp)
movq 0x20(%rsp), %rax
shrq $0x8, %rax
movb %al, 0x12(%rsp)
movq 0x20(%rsp), %rax
movb %al, 0x13(%rsp)
movq 0x18(%rsp), %rax
shrq $0x18, %rax
movb %al, 0x14(%rsp)
movq 0x18(%rsp), %rax
shrq $0x10, %rax
movb %al, 0x15(%rsp)
movq 0x18(%rsp), %rax
shrq $0x8, %rax
movb %al, 0x16(%rsp)
movq 0x18(%rsp), %rax
movb %al, 0x17(%rsp)
movq 0x40(%rsp), %rax
movq (%rax), %rax
andq $0x3f, %rax
movq %rax, 0x30(%rsp)
cmpq $0x38, 0x30(%rsp)
jae 0x410b3a
movl $0x38, %eax
subq 0x30(%rsp), %rax
movq %rax, 0x8(%rsp)
jmp 0x410b49
movl $0x78, %eax
subq 0x30(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x40(%rsp), %rdi
movq 0x28(%rsp), %rdx
leaq 0xcaa8c(%rip), %rsi     # 0x4db5f0
callq 0x408620
movq 0x40(%rsp), %rdi
leaq 0x10(%rsp), %rsi
movl $0x8, %edx
callq 0x408620
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, (%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x2(%rax)
movq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x3(%rax)
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x4(%rax)
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x5(%rax)
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x6(%rax)
movq 0x40(%rsp), %rax
movq 0x18(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x7(%rax)
movq 0x40(%rsp), %rax
movq 0x20(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x8(%rax)
movq 0x40(%rsp), %rax
movq 0x20(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x9(%rax)
movq 0x40(%rsp), %rax
movq 0x20(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xa(%rax)
movq 0x40(%rsp), %rax
movq 0x20(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xb(%rax)
movq 0x40(%rsp), %rax
movq 0x28(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xc(%rax)
movq 0x40(%rsp), %rax
movq 0x28(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xd(%rax)
movq 0x40(%rsp), %rax
movq 0x28(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xe(%rax)
movq 0x40(%rsp), %rax
movq 0x28(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0xf(%rax)
movq 0x40(%rsp), %rax
movq 0x30(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x10(%rax)
movq 0x40(%rsp), %rax
movq 0x30(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x11(%rax)
movq 0x40(%rsp), %rax
movq 0x30(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x12(%rax)
movq 0x40(%rsp), %rax
movq 0x30(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x13(%rax)
movq 0x40(%rsp), %rax
movq 0x38(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x14(%rax)
movq 0x40(%rsp), %rax
movq 0x38(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x15(%rax)
movq 0x40(%rsp), %rax
movq 0x38(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x16(%rax)
movq 0x40(%rsp), %rax
movq 0x38(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x17(%rax)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x18(%rax)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x19(%rax)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1a(%rax)
movq 0x40(%rsp), %rax
movq 0x40(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1b(%rax)
movq 0x40(%rsp), %rax
cmpl $0x0, 0x110(%rax)
jne 0x410e4a
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
shrq $0x18, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1c(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
shrq $0x10, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1d(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
shrq $0x8, %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1e(%rax)
movq 0x40(%rsp), %rax
movq 0x48(%rax), %rax
movb %al, %cl
movq 0x38(%rsp), %rax
movb %cl, 0x1f(%rax)
addq $0x48, %rsp
retq
nop