offset: MACRO ; I want to keep myself sane if _NARG > 1 ld a, \2 endc add a, LOW(\1) ld LOW(\1), a jr nc, .no_carry_\@ inc HIGH(\1) .no_carry_\@ ENDM CalculateSHA1: ; in: hl: pointer to data, a: length (bytes) ; out: hl = hl + 64 pointing to hash, all other regs clobbered, initial data buffer clobbered ; returns carry iif a > 55 (since this would require implementing proper blocking) ; prereq's: a <= 55, hl points to an 84-byte buffer initialized with the data cp 55 ccf ret c push hl ; pad the block ld c, a offset hl ld a, $80 ld [hli], a ld a, c sub 62 ld b, a xor a jr .padding_loop_check .padding_loop ld [hli], a .padding_loop_check inc b jr nz, .padding_loop ld a, c add a, a add a, a add a, a ld b, a sbc a and 1 ld [hli], a ld a, b ld [hli], a ; initialize the registers ld b, 20 ld de, .initialization_data .initialization_loop ld a, [de] inc de ld [hli], a dec b jr nz, .initialization_loop pop hl ; 80 iterations of operations xor a .iteration_loop call .combine_states_and_constant push hl push af and $f add a, a add a, a offset hl call .add_word pop af pop hl push af call .update_states pop af cp $40 call c, .update_buffer_word inc a cp $50 jr c, .iteration_loop ; add the results to the initialization data offset hl, $40 push hl xor a .final_addition_loop push af call .load_word dec hl dec hl dec hl dec hl pop af push af push hl ld hl, .initialization_data add a, a add a, a offset hl call .add_word pop hl call .store_word pop af inc a cp 5 jr c, .final_addition_loop ; and we're done! pop hl and a ret .load_word ld a, [hli] ld b, a ld a, [hli] ld c, a ld a, [hli] ld d, a ld a, [hli] ld e, a ret .store_word ld a, b ld [hli], a ld a, c ld [hli], a ld a, d ld [hli], a ld a, e ld [hli], a ret .and_word ld a, [hli] and b ld b, a ld a, [hli] and c ld c, a ld a, [hli] and d ld d, a ld a, [hli] and e ld e, a ret .or_word ld a, [hli] or b ld b, a ld a, [hli] or c ld c, a ld a, [hli] or d ld d, a ld a, [hli] or e ld e, a ret .rotate_word_left sla e rl d rl c rl b ret nc inc e ret .rotate_word_right srl b rr c rr d rr e ret nc set 7, b ret .combine_states_and_constant ; must preserve a, hl push af push hl ld c, a offset hl, $44 ld a, c call .initial_states_combination pop hl push hl offset hl, $50 call .add_word pop hl push hl offset hl, $40 add sp, -4 push hl ld hl, sp + 2 call .store_word pop hl call .load_word ld l, 5 .rotation_loop call .rotate_word_left dec l jr nz, .rotation_loop ld hl, sp + 0 call .add_word add sp, 4 pop hl pop af push af push hl call .add_iteration_constant pop hl pop af ret .initial_states_combination cp 20 jr c, .selection_function cp 40 jr c, .xor_function cp 60 jr c, .majority_function .xor_function call .load_word call .xor_word .xor_word ld a, [hli] xor b ld b, a ld a, [hli] xor c ld c, a ld a, [hli] xor d ld d, a ld a, [hli] xor e ld e, a ret .majority_function add sp, -4 call .load_word push hl push de push bc call .and_word push hl ld hl, sp + 8 call .store_word pop hl pop bc pop de call .and_word ld hl, sp + 2 call .or_word ld hl, sp + 2 ;faster than push/pop, and same size call .store_word pop hl call .load_word call .and_word ld hl, sp + 0 call .or_word add sp, 4 ret .selection_function add sp, -4 call .load_word push de push bc call .and_word push hl ld hl, sp + 6 call .store_word pop hl pop bc ld a, b cpl ld b, a ld a, c cpl ld c, a pop de ld a, d cpl ld d, a ld a, e cpl ld e, a call .and_word ld hl, sp + 0 call .or_word add sp, 4 ret .add_iteration_constant ld l, -1 .iteration_constant_loop inc l sub 20 jr nc, .iteration_constant_loop ld a, l add a, a add a, a ld hl, .iteration_constants offset hl .add_word inc hl inc hl inc hl ld a, [hld] add a, e ld e, a ld a, [hld] adc d ld d, a ld a, [hld] adc c ld c, a ld a, [hl] adc b ld b, a ret .update_buffer_word ; must preserve a, hl push af push hl sub 3 and $f add a, a add a, a offset hl call .load_word pop hl pop af push af sub 8 call .xor_word_by_offset pop af push af sub 14 call .xor_word_by_offset pop af push af push hl and $f add a, a add a, a offset hl push hl call .xor_word call .rotate_word_left pop hl call .store_word pop hl pop af ret .xor_word_by_offset push hl and $f add a, a add a, a offset hl call .xor_word pop hl ret .update_states ; must preserve hl push bc push de ld a, $4c call .shift_word_position ld a, $48 call .shift_word_position push hl offset hl, $44 call .load_word call .rotate_word_right call .rotate_word_right call .store_word pop hl ld a, $40 call .shift_word_position pop de pop bc push hl offset hl, $40 call .store_word pop hl ret .shift_word_position push hl offset hl call .load_word call .store_word pop hl ret .initialization_data db $67, $45, $23, $01 db $ef, $cd, $ab, $89 db $98, $ba, $dc, $fe db $10, $32, $54, $76 db $c3, $d2, $e1, $f0 .iteration_constants db $5a, $82, $79, $99 db $6e, $d9, $eb, $a1 db $8f, $1b, $bc, $dc db $ca, $62, $c1, $d6