adventofcode2023/01/main.s

223 lines
3.7 KiB
ArmAsm
Raw Normal View History

2023-12-02 01:38:16 -06:00
%define BUFF_LIM 32768
; call # val val2
; int $0x80 eax eax edx -
;
; arg1 arg2 arg3 arg4 arg5 arg6 arg7
; ebx ecx edx esi edi ebp -
global _start
[bits 32]
[section .text]
_start:
push 0 ; eof
mov eax, 5 ; open
mov ebx, filename
xor ecx, ecx ; read only
int 0x80
mov ebx, eax
mov eax, 3 ; read
mov ecx, read_buff
mov edx, BUFF_LIM
int 0x80
cmp eax, -1 ; err
je exit
cmp eax, BUFF_LIM
je .no_eof
; we hit eof
inc dword [esp]
.no_eof:
; parse section
lea edi, [read_buff+eax]
mov esi, read_buff
.cont_read:
xor ecx, ecx ; set if first is found
; last digit in ebx
xor ebx, ebx
; counting loop
xor eax, eax
push eax ; first digit
jmp .count_loop_cont
.count_loop:
lodsb
cmp al, 10 ; newline
je .next_line
cmp al, '0'
jl .count_loop_cont
cmp al, '9'
jg .check_str
sub al, '0'
; reset string parsing when we got a numeral
call reset_string_wheels
.matched:
test ecx, ecx
jnz .have_first
mov [esp], eax ; first digit
inc ecx
.have_first:
mov ebx, eax ; set last to current
.count_loop_cont:
cmp esi, edi
jl .count_loop
.next_line:
test ecx, ecx
jz .check_end ; no digits (huh?)
pop eax ; first digit
mov dl, 10
mul dl
add eax, ebx
; add to total
add [final_value], eax
.check_end:
; reset string parsing when we got a newline
call reset_string_wheels
; check for more data
cmp esi, edi
jl .cont_read
; TODO handle files over BUFF_LIM bytes
; check for EOF
cmp dword [esp], 1
jne .cont_read
; we're at EOF, print result
mov eax, [final_value]
call print_dec
jmp exit
.check_str:
call weird_string_parser
; check result
mov al, [matched_value]
test al, al
jnz .match_found
; nothing matched yet
; check if we got a word char
cmp byte [matched_any_char], 1
je .count_loop_cont
; not a word char, reset wheels
call reset_string_wheels
jmp .count_loop_cont
.match_found:
; we have a match
; reset the matched value
; and go back to loop
mov byte [matched_value], 0
jmp .matched
reset_string_wheels:
push edi
push ecx
push eax
mov edi, number_wheels
mov ecx, number_lens - number_wheels
xor eax, eax
rep stosb
pop eax
pop ecx
pop edi
ret
exit:
mov eax, 1
int 0x80 ; exit
; i hate this
print_dec:
sub esp, 12
lea ecx, [esp+11]
test eax, eax
jz .zero
mov esi, 0
mov ebx, 10
.div_shit:
xor edx, edx
div ebx
dec ecx
inc esi
add dl, '0'
mov byte [ecx], dl
test eax, eax
jnz .div_shit
mov edx, esi
jmp .write
.zero:
mov byte [esp+10], 0
lea ecx, [esp+10]
mov edx, 1 ; count
.write:
mov eax, 4 ; write
mov ebx, 1 ; stdout
int 0x80
add esp, 12
ret
; i'm in hell
weird_string_parser:
pushad
; reset matched any char
mov byte [matched_any_char], 0
mov edi, number_wheels
mov esi, number_lens
mov ebp, numbers
mov ecx, 0
.test_loop:
mov edx, ebp
; add current wheel value
movzx ebx, byte [edi]
add edx, ebx
; compare to input
cmp byte [edx], al
jne .next_test_fail
; match - increment counter
inc bl
; test against length
cmp byte [esi], bl
je .full_match
.partial_match:
; partial match - save value
mov [edi], bl
; we matched any char
mov byte [matched_any_char], 1
jmp .next_test_match
.next_test_fail:
; reset the current wheel
mov byte [edi], 0
; check if it's the start of the word
cmp byte [ebp], al
jne .next_test_match ; nope
; yep! save
mov bl, 1
jmp .partial_match
.next_test_match:
inc ecx
; check if we're done testing
cmp ecx, 9
jge .done
; add current value length to string
movzx ebx, byte [esi]
add ebp, ebx
inc edi
inc esi
; loop
jmp .test_loop
.done:
popad
ret
.full_match:
; save matched byte
inc ecx ; zero -> one
mov byte [matched_value], cl
; reset this wheel
mov byte [edi], 0
; next check
jmp .next_test_match
[section .data]
final_value: dd 0
matched_value: db 0
matched_any_char: db 0
number_wheels: db 0,0,0,0,0,0,0,0,0
number_lens: db 3,3,5,4,4,3,5,5,4
numbers: db "onetwothreefourfivesixseveneightnine"
filename: db "input",0
[section .bss]
read_buff: resb BUFF_LIM