223 lines
3.7 KiB
ArmAsm
223 lines
3.7 KiB
ArmAsm
|
%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
|