day 19 part 2

This commit is contained in:
Lucia Ceionia 2023-12-20 01:40:44 -06:00
parent d59671e54c
commit 2598b444f8

407
19/main.s Normal file
View File

@ -0,0 +1,407 @@
%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
proc_next_input:
; go through the rules
mov ebx, [in_idx]
push 1 ; x min
push 4001 ; x max (exclusive)
push 1 ; m min
push 4001 ; m max (exclusive)
push 1 ; a min
push 4001 ; a max (exclusive)
push 1 ; s min
push 4001 ; s max (exclusive)
call check_rule
jmp game_over
; rule idx in EBX, xmas ranges on stack (args)
; ebp+36 x min
; ebp+32 x max (exclusive)
; ebp+28 m min
; ebp+24 m max (exclusive)
; ebp+20 a min
; ebp+16 a max (exclusive)
; ebp+12 s min
; ebp+ 8 s max (exclusive)
; ebp+ 4 return loc
; ebp+ 0 ebp
; ebp- 4 rule ptr
check_rule:
push ebp
mov ebp, esp ; a proper C-like stackframe!? egads!
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
shr esi, 16 ; bound
mov ebx, eax
and bl, 0b1110 ; dir & var
cmp bl, 0b0110
je .xl
cmp bl, 0b0010
je .ml
cmp bl, 0b0000
je .al
cmp bl, 0b0100
je .sl
cmp bl, 0b1110
je .xg
cmp bl, 0b1010
je .mg
cmp bl, 0b1000
je .ag
cmp bl, 0b1100
je .sg
mov eax, [0] ; something is horribly wrong
.xl: ; matched x range is x min to bound, inverse is bound to x max
xchg esi, [ebp+32] ; bound -> our max, our old max -> esi
call .internal_thing
xchg esi, [ebp+32] ; restore old max
mov [ebp+36], esi ; bound -> our min
jmp .next_rule
.ml: ; matched m range is m min to bound, inverse is bound to m max
xchg esi, [ebp+24] ; bound -> our max, our old max -> esi
call .internal_thing
xchg esi, [ebp+24] ; restore old max
mov [ebp+28], esi ; bound -> our min
jmp .next_rule
.al: ; matched a range is a min to bound, inverse is bound to a max
xchg esi, [ebp+16] ; bound -> our max, our old max -> esi
call .internal_thing
xchg esi, [ebp+16] ; restore old max
mov [ebp+20], esi ; bound -> our min
jmp .next_rule
.sl: ; matched s range is s min to bound, inverse is bound to s max
xchg esi, [ebp+ 8] ; bound -> our max, our old max -> esi
call .internal_thing
xchg esi, [ebp+ 8] ; restore old max
mov [ebp+12], esi ; bound -> our min
jmp .next_rule
.xg: ; matched x range is bound+1 to x max, inverse is x min to bound+1
inc esi
xchg esi, [ebp+36] ; bound+1 -> our min, our old min -> esi
call .internal_thing
xchg esi, [ebp+36] ; restore old min
mov [ebp+32], esi ; bound+1 -> our max
jmp .next_rule
.mg: ; matched m range is bound+1 to m max, inverse is m min to bound+1
inc esi
xchg esi, [ebp+28] ; bound+1 -> our min, our old min -> esi
call .internal_thing
xchg esi, [ebp+28] ; restore old min
mov [ebp+24], esi ; bound+1 -> our max
jmp .next_rule
.ag: ; matched a range is bound+1 to a max, inverse is a min to bound+1
inc esi
xchg esi, [ebp+20] ; bound+1 -> our min, our old min -> esi
call .internal_thing
xchg esi, [ebp+20] ; restore old min
mov [ebp+16], esi ; bound+1 -> our max
jmp .next_rule
.sg: ; matched a range is bound+1 to s max, inverse is s min to bound+1
inc esi
xchg esi, [ebp+12] ; bound+1 -> our min, our old min -> esi
call .internal_thing
xchg esi, [ebp+12] ; restore old min
mov [ebp+ 8], esi ; bound+1 -> our max
jmp .next_rule
.always:
shr ax, 4 ; rule.res
test ax, ax
jz .return_res_A
cmp ax, 0x0FFF
je .return_res_R
; nested rule
movzx ebx, ax
jmp .inner
.return_res_A:
call .A
.return_res_R:
add esp, 4 ; stackframe gone :c
pop ebp
ret
.internal_thing:
mov ebx, eax
shr ax, 4 ; rule.res
test ax, ax
jz .A
cmp ax, 0x0FFF
je .R
; we need to make a recursive call, set up args
push esi
movzx ebx, ax
push dword [ebp+36] ; x min
push dword [ebp+32] ; x max
push dword [ebp+28] ; m min
push dword [ebp+24] ; m max
push dword [ebp+20] ; a min
push dword [ebp+16] ; a max
push dword [ebp+12] ; s min
push dword [ebp+ 8] ; s max
call check_rule
add esp, 4*8
pop esi
jmp .R
.A:
pushad
sub esp, 8 ; scratch memory
; final_value += (xMax-xMin)*
; (mMax-mMin)*
; (aMax-aMin)*
; (sMax-sMin);
mov eax, [ebp+32]
sub eax, [ebp+36]
js .no_add
xor edx, edx
mov ecx, [ebp+24]
sub ecx, [ebp+28]
js .no_add
imul edx, ecx
mov [esp], edx
mul ecx
mov ecx, edx
mov edx, [esp]
add ecx, edx
mov edx, [ebp+16]
sub edx, [ebp+20]
js .no_add
imul ecx, edx
mul edx
add edx, ecx
mov ecx, [ebp+ 8]
sub ecx, [ebp+12]
js .no_add
imul edx, ecx
mov [esp+4], edx
mul ecx
mov esi, eax
mov eax, [esp+4]
add edx, eax
add [final_value], esi
adc [final_value+4], edx
.no_add:
add esp,8
popad
.R: ; done, return to place to inverse range
ret
game_over:
mov eax, [final_value]
call print_dec
call space
mov eax, [final_value+4]
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
in_idx: dd 0
final_value: dd 0, 0
file: incbin FILENAME
.over:
[section .bss]
rules: resd 1024*4
rule_idx_to_id: resd 1024
[section .rodata]
wtf: db "WTF"
.over: