day 20 part 2 im tired

This commit is contained in:
Lucia Ceionia 2023-12-23 03:29:03 -06:00
parent 9f5df0a65c
commit 7a9bd95804

278
20/main.s Normal file
View File

@ -0,0 +1,278 @@
%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]