305 lines
5.2 KiB
ArmAsm
305 lines
5.2 KiB
ArmAsm
|
%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:
|