adventofcode2023/19/main_part1.s

305 lines
5.2 KiB
ArmAsm
Raw Normal View History

2023-12-19 21:20:26 -06:00
%include "utils.s"
global _start
[bits 32]
[section .text]
%define FILENAME "input"
;%define FILENAME "input_test"
_start:
mov esi, file
load_rule:
xor ebx, ebx ; id
.get_id:
lodsb
cmp al, '{'
je .got_id
shl ebx, 8
mov bl, al ; add new byte
jmp .get_id
.got_id:
call id_to_idx ; idx in EDX
shl edx, 4 ; *16
lea edi, [rules+edx] ; rule ptr
.get_rules:
; --- rule format ---
; [ 16 ]
; [ 4 ][ 4 ][ 4 ][ 4 ]
; [ 2 ] [ 2 ][ 2 ] [ 2 ][ 2 ] [ 2 ][ 2 ] [ 2 ]
; [bound] [ vdr ][bound] [ vdr ][bound] [ vdr ][bound] [ vdr ]
; var, dir, & res
; FEDCBA9876543210
; --- var --- 76543210
; ...............1 -> Always
; .............00. -> a (ASCII .1100...)
; .............01. -> m (ASCII .1101...)
; .............10. -> s (ASCII .1110...)
; .............11. -> x (ASCII .1111...)
; --- dir ---
; ............0... -> < (ASCII .0....0.)
; ............1... -> > (ASCII .0....1.)
; --- res ---
; 111111111111.... -> R (ASCII .10....0 bit 0 - 1 -> ..111)
; 000000000000.... -> A (ASCII .10....1 bit 0 - 1 -> ..000)
; NNNNNNNNNNNN.... -> eval
xor ecx, ecx ; output vdr & bound
xor eax, eax ; input byte
lodsb ; lowercase alpha or RA
bt ax, 5 ; low for RA, high for alpha
jc .alpha
; immediately finish with R or A
or cx, 1 ; Always
and ax, 1 ; bit 0 of ASCII
dec ax ; R -> -1, A -> 0
shl ax, 4 ; correct position
or cx, ax
jmp .done
.alpha: ; either [xmas][><] or a multi-char ID
mov ebx, eax ; save last input
lodsb ; next byte
bt ax, 6 ; bit 6 low for ><
jnc .is_check
; immediately finish by evaluating ID
.imm_got_id_byte:
shl ebx, 8
mov bl, al
.imm_get_full_id:
lodsb
cmp al, ',' ; ends , or }
je .imm_got_id
cmp al, '}'
jne .imm_got_id_byte
.imm_got_id:
call id_to_idx ; idx in EDX
or cx, 1 ; out.var <- Always
shl edx, 4 ; correct position
or cx, dx ; out.res <- idx
jmp .done
.is_check:
and bx, 3<<3
shr bx, 2
or cx, bx ; out.var <- bits 3&4 of last
and ax, 1<<1
shl ax, 2
or cx, ax ; out.dir <- bit 1 of ASCII
call dec_parse
mov bx, cx
mov cx, ax
shl ecx, 16
mov cx, bx ; out.bound <- parse_dec
; parse_dec skips the : so get the res
lodsb
bt ax, 5
jc .chk_id
; res is R or A
and ax, 1
dec ax
shl ax, 4
or cx, ax ; out.res <- bit 0 of ASCII - 1
jmp .done
.chk_id: ; res is ID
xor ebx, ebx
jmp .chk_got_id_byte
.chk_next_byte:
lodsb
cmp al, ',' ; ends ,
je .chk_got_id
.chk_got_id_byte:
shl ebx, 8
mov bl, al
jmp .chk_next_byte
.chk_got_id:
call id_to_idx ; idx in EDX
shl edx, 4
or cx, dx ; out.res <- idx
.done:
mov eax, ecx
stosd
cmp byte [esi-1], ','
je .get_rules
cmp byte [esi], ','
je .next_rule
cmp byte [esi-1], '}'
je .next_line
cmp byte [esi], '}'
je .next_line
cmp byte [esi-1], 10
je .check_rules_over
call newline
.wtf: p_string wtf
jmp .wtf
.next_rule:
inc esi
jmp .get_rules
.next_line:
lodsb
cmp al, 10 ; \n
jne .next_line
.check_rules_over:
cmp byte [esi], 10
jne load_rule
rules_over:
mov eax, [next_rule_idx]
dec eax
call print_dec
call newline
; find rule 'in'
mov ebx, 'ni'
call id_to_idx
mov [in_idx], edx
mov eax, edx
call print_dec
call space
shl edx, 4
movzx eax, word [rules+edx]
call print_dec
call space
movzx eax, word [rules+edx+2]
call print_dec
call newline
; we're now reading in the inputs to test
; find the next {
proc_next_input:
mov ecx, 32
mov al, '{'
xchg edi, esi
repne scasb
xchg edi, esi
cmp esi, file.over
jae game_over
; get 4 nums, x m a s (ecx edx edi ebp)
.get_x:
call dec_parse
jc .get_x
mov ecx, eax
.get_m:
call dec_parse
jc .get_m
mov edx, eax
.get_a:
call dec_parse
jc .get_a
mov edi, eax
.get_s:
call dec_parse
jc .get_s
mov ebp, eax
; go through the rules
push esi
mov ebx, [in_idx]
call check_rule
add ecx, edx
add ecx, edi
add ecx, ebp
not eax
movzx eax, al
test eax, eax
cmovnz eax, ecx
add [final_value], eax
pop esi
jmp proc_next_input
; rule idx in EBX, xmas in ecx edx edi ebp
; return in EAX
check_rule:
sub esp, 4
.inner:
shl ebx, 4
lea esi, [rules+ebx] ; rule ptr
mov [esp], esi
.next_rule:
mov esi, [esp]
lodsd ; rule
mov [esp], esi
bt ax, 0 ; always
jc .always
; .............00. -> a
; .............01. -> m
; .............10. -> s
; .............11. -> x
; ............0... -> <
; ............1... -> >
mov esi, eax
mov ebx, eax
and bl, 0b110 ; var
cmp bl, 0b000
cmove eax, edi
cmp bl, 0b010
cmove eax, edx
cmp bl, 0b100
cmove eax, ebp
cmp bl, 0b110
cmove eax, ecx
mov ebx, esi
shr ebx, 16 ; rule.bound
bt esi, 3 ; rule.dir
jnc .less
cmp eax, ebx
jg .match
jmp .next_rule
.less:
cmp eax, ebx
jge .next_rule
.match:
mov eax, esi
.always:
shr ax, 4 ; rule.res
test ax, ax
jz .return_res
cmp ax, 0x0FFF
je .return_res
; nested rule
movzx ebx, ax
jmp .inner
.return_res:
movzx eax, ax
add esp, 4
ret
game_over:
mov eax, [final_value]
call print_dec
call newline
jmp exit
; ID in EBX, IDX return in EDX
id_to_idx:
xor edx, edx
.test:
cmp [rule_idx_to_id+edx*4], ebx
je .found
inc edx
cmp edx, [next_rule_idx]
jb .test
; new ID
mov [rule_idx_to_id+edx*4], ebx
inc dword [next_rule_idx]
.found:
ret
[section .data]
next_rule_idx: dd 1
final_value: dd 0
in_idx: dd 0
file: incbin FILENAME
.over:
[section .bss]
rule_idx_to_id: resd 1024
rules: resd 1024*4
[section .rodata]
wtf: db "WTF"
.over: