%include "utils.s" global _start [bits 32] [section .text] %define FILENAME "input" ;%define FILENAME "input_test" ;%define FILENAME "input_test2" ;%define DBG _start: ; read in modules ; module data (16 bytes): ; 0 ; bit 1: type (0: flipflop, 1: conj) bit 0: state (0: low, 1: high) ; 1 2 3 4 5 6 ; destination IDX list ; 7 8 9 A B C D E F ; input states (for conj modules) ; bit 0 is remembered state, higher is index mov esi, file read_modules: lodsb cmp al, '%' je .flipflop cmp al, '&' je .conjunc ; broadcaster %ifdef DBG mov al, 'B' call print_char mov al, 'R' call print_char call space %endif mov ch, 1<<1 mov al, 1 %ifdef DBG call print_hex_byte call space %endif mov cl, -1 ; broadcaster is special add esi, 14 mov edi, modules+16 ; module 1 is broadcast jmp .get_dests .flipflop: mov cl, 0b00 ; low, flipflop jmp .get_idx .conjunc: mov cl, 0b10 ; low, conj jmp .get_idx .get_idx: ; get ID lodsb %ifdef DBG call print_char %endif mov bh, al lodsb %ifdef DBG call print_char call space %endif mov bl, al call id_to_idx ; idx in edx mov ch, dl %ifdef DBG mov al, dl call print_hex_byte call space %endif shl ch, 1 shl edx, 4 ; * 16 lea edi, [modules+edx] add esi, 4 .get_dests: ; type/state in CL mov [edi], cl inc edi .next_dest: ; get dest ID lodsb %ifdef DBG call print_char %endif mov bh, al lodsb %ifdef DBG call print_char call space %endif mov bl, al call id_to_idx cmp bx, 'fm' jne .not_rx mov [mf_idx], dx .not_rx: mov al, dl %ifdef DBG call print_hex_byte call space %endif stosb ; store our idx<<1 in dest inputs shl edx, 4 ; * 16 lea edx, [modules+edx+7] .store_input: cmp byte [edx], 0 jnz .check_next_input mov byte [edx], ch jmp .input_stored .check_next_input: inc edx jmp .store_input .input_stored: ; check if more lodsb cmp al, ',' jne .cont ; no more inc esi ; space jmp .next_dest .cont: %ifdef DBG call newline %endif cmp esi, file.over jb read_modules main: ; start an iteration, broadcaster (1) sends low to everything mov dword [queue_head], 0 mov dword [queue_tail], 2 mov word [queue], 0b10 ; low to index 1 call do_iters inc dword [final_value] jmp main do_iters: ; get head of queue mov eax, [queue_head] mov ax, [eax+queue] %ifdef DBG call print_hex_word call newline %endif mov cl, ah ; sender movzx eax, al shr eax, 1 ; get pulse setc bl jnc .not_high cmp al, [mf_idx] jne .not_high push eax mov al, cl call print_hex_byte call space mov eax, [final_value] call print_dec call newline pop eax .not_high: ; get module mov bh, al ; idx shl eax, 4 ; * 16 lea edi, [modules+eax] mov al, [edi] cmp al, -1 je .broadcast bt ax, 1 jc .conj .flipflop: ; if high, do nothing test bl, bl jnz .cont ; if low, flip and send result xor al, 1 bt ax, 0 setc bl mov [edi], al jmp add_cmds .conj: mov dl, 1 mov esi, 7 .check_mem: mov al, [edi+esi] test al, al jz .mem_done shr al, 1 setc dh cmp al, cl jne .mem_cont shr bl, 1 setc dh rcl al, 1 mov [edi+esi], al .mem_cont: and dl, dh inc esi cmp esi, 0xF jbe .check_mem .mem_done: ; send high if not all were high xor dl, 1 mov bl, dl jmp add_cmds .broadcast: jmp add_cmds ; just add commands with same pulse .cont: mov eax, [queue_head] add eax, 2 and eax, 511 mov [queue_head], eax cmp eax, [queue_tail] jne do_iters ret ; BH: module IDX, BL: pulse, EDI: *module add_cmds: mov dx, bx ; save mov ecx, 1 .loop: mov al, [edi+ecx] test al, al jz .done mov bx, dx shl al, 1 or bl, al %ifdef DBG call space mov ax, bx call print_hex_word call newline %endif ; add to queue mov eax, [queue_tail] mov [eax+queue], bx add eax, 2 and eax, 511 mov [queue_tail], eax inc ecx cmp ecx, 6 jbe .loop .done: jmp do_iters.cont ; ID in BX, IDX return in EDX id_to_idx: xor edx, edx .test: cmp [module_idx_to_id+edx*2], bx je .found inc dx cmp dx, [next_module_idx] jb .test ; new ID mov [module_idx_to_id+edx*2], bx inc word [next_module_idx] .found: ret [section .data] final_value: dd 1 next_module_idx: dw 2 ; 1 reserved for broadcaster mf_idx: dw 0 queue_head: dd queue queue_tail: dd queue file: incbin FILENAME .over: db 0 ; EOF [section .bss] modules: resb 64*16 module_idx_to_id: resw 64 queue: resw 64*8 [section .rodata]