%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: