global _start [bits 32] [section .text] %include "utils.s" _start: mov esi, file parse_line: ; find first num mov ebp, esi ; line start .first_num: mov edi, esi ; save before loc call dec_parse jc .first_num ; edi has pointer to just before numbers mov ecx, edi sub ecx, ebp dec ecx ; space xchg esi, ebp mov [line_len], ecx mov edi, line rep movsb xchg esi, ebp mov dword [contiguous_broken+ 0], 0 mov dword [contiguous_broken+ 4], 0 mov dword [contiguous_broken+ 8], 0 mov dword [contiguous_broken+12], 0 mov dword [contiguous_broken+16], 0 mov dword [contiguous_broken+20], 0 mov dword [contiguous_broken+24], 0 mov dword [contiguous_broken+28], 0 mov dword [contiguous_broken+32], 0 mov dword [contiguous_broken+36], 0 mov dword [contiguous_broken+40], 0 mov dword [contiguous_broken+44], 0 mov dword [contiguous_broken+48], 0 mov dword [contiguous_broken+52], 0 mov dword [contiguous_broken+56], 0 mov dword [contiguous_broken+60], 0 mov edi, contiguous_broken stosb .next_num: cmp byte [esi-1], 10 ; \n je .newline call dec_parse jc .next_num .got_num: stosb jmp .next_num .newline: push esi ; save input line ; clear cache mov edi, cache mov ecx, (cache.end - cache)/4 mov eax, -1 rep stosd ; setup do_stream vars xor esi, esi ; line idx mov ebp, [line_len] xor edi, edi ; contiguous_broken idx xor edx, edx ; poss_counter high xor ebx, ebx ; poss_counter low call do_stream ; call into recursive routine add [final_value+0], ebx ; poss_counter low adc [final_value+4], edx ; poss_counter high mov eax, edx call print_dec call space mov eax, ebx call print_dec call newline jmp parse_line_cont do_stream: cmp byte [line+esi], '.' je .cont cmp byte [line+esi], '#' jne .branch .broke: cmp byte [contiguous_broken+edi], 0 je .ret ; branch impossible movzx ecx, byte [contiguous_broken+edi] inc edi .consume_things: mov al, byte [line+esi] inc esi cmp esi, ebp ja .ret ; branch impossible cmp al, '.' je .ret ; branch impossible loop .consume_things cmp esi, ebp je .cont cmp byte [line+esi], '#' je .ret ; branch impossible ; .cont consumes . or ? (must be .) jmp .cont .branch: ; recursive branch mov eax, esi shl eax, 8 ; *256 cmp dword [eax+edi*8+cache], -1 je .not_cached add ebx, [eax+edi*8+(cache+0)] adc edx, [eax+edi*8+(cache+4)] jmp .cont .not_cached: push edx push ebx push esi push edi xor ebx, ebx xor edx, edx call do_stream.broke ; assume # pop edi pop esi mov eax, esi shl eax, 8 mov [eax+edi*8+(cache+0)], ebx mov [eax+edi*8+(cache+4)], edx pop eax add ebx, eax pop eax adc edx, eax ; assume . .cont: inc esi cmp esi, ebp jb do_stream ; iff we are at the end of stream ; and contiguous_broken is exhausted ; we add a possibility cmp byte [contiguous_broken+edi], 0 jne .ret add ebx, 1 ; poss counter adc edx, 0 .ret: ret parse_line_cont: pop esi cmp esi, file.over-1 jb parse_line call newline game_over: mov eax, [final_value+4] call print_dec call space mov eax, [final_value+0] call print_dec call newline jmp exit [section .data] line_len: dd 0 final_value: dd 0, 0 final_setting: dd 0, 0 curr_setting: dd 0, 0 file: incbin "input5" .over: nl_str: db "new line!" .over: [section .bss] contiguous_broken: resb 64 line: resb 512 cache: resd 256*64*2 cache.end: