day 19 part 2
This commit is contained in:
parent
d59671e54c
commit
2598b444f8
407
19/main.s
Normal file
407
19/main.s
Normal 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:
|
Loading…
Reference in New Issue
Block a user