adventofcode2023/19/utils.s

286 lines
4.1 KiB
ArmAsm
Raw Permalink Normal View History

2023-12-19 21:20:26 -06:00
[bits 32]
[section .text]
; call # val val2
; int $0x80 eax eax edx -
;
; arg1 arg2 arg3 arg4 arg5 arg6 arg7
; ebx ecx edx esi edi ebp -
exit:
mov eax, 1 ; exit
int 0x80
; filename in EBX
; return handle in EBX
; read only
open_file:
push eax
push ecx
mov eax, 5 ; open
xor ecx, ecx ; read only
int 0x80
mov ebx, eax
pop ecx
pop eax
ret
; file handle in EBX
; buffer in ECX
; count of bytes to read in EDX
; return bytes actually read in EAX
; exits on error
read_file:
mov eax, 3 ; read
int 0x80
test eax, eax
js .err
ret
.err:
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, .err_str
mov edx, 21
int 0x80
jmp exit
.err_str: db `Could not read file.\n`
; string input in ESI
; value in EAX
; CF set if none, clear if some
; ESI set past checked area
dec_parse:
push ebx
push edx
push edi
xor eax, eax
xor edi, edi
mov ebx, 10 ; base
lodsb
sub al, '0'
js .no_input
cmp al, 9
jle .got_char
.no_input:
stc ; set CF
jmp .done
.loop:
xor eax,eax
lodsb
sub al, '0'
js .dec_done
cmp al, 9
jg .dec_done
.got_char:
xchg edi,eax
mul ebx
add edi,eax
jmp .loop
.dec_done:
clc ; clear CF
.done:
mov eax,edi
pop edi
pop edx
pop ebx
ret
; string input in ESI
; value in EAX
; CF set if none, clear if some
; ESI set past checked area
sign_dec_parse:
push ebx
push ecx
push edx
push edi
xor eax, eax
xor edi, edi
xor ecx, ecx ; neg flag
mov ebx, 10 ; base
cmp byte [esi], '-'
jne .no_minus
inc esi
mov cl, 1
.no_minus:
lodsb
sub al, '0'
js .no_input
cmp al, 9
jle .got_char
.no_input:
stc ; set CF
jmp .done
.loop:
xor eax,eax
lodsb
sub al, '0'
js .dec_done
cmp al, 9
jg .dec_done
.got_char:
xchg edi,eax
mul ebx
add edi,eax
jmp .loop
.dec_done:
test ecx, ecx
jz .not_neg
neg edi
.not_neg:
clc ; clear CF
.done:
mov eax,edi
pop edi
pop edx
pop ecx
pop ebx
ret
; modifies no regs
newline:
pushad
push 10
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, esp ; string
mov edx, 1 ; length
int 0x80
add esp, 4
popad
ret
; modifies no regs
space:
pushad
push 9
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, esp ; string
mov edx, 1 ; length
int 0x80
add esp, 4
popad
ret
; input in EAX, all regs unmodified
print_dec:
pushad ; save regs
; max 4294967296 is 10 chars
; round to nearest 32-bit boundary
sub esp, 12
; string in ECX, length in EDX
lea ecx, [esp+11] ; last possible byte
; check for 0
test eax, eax
jz .zero
mov ebx, 10 ; base 10
xor esi, esi ; counter
.div_shit:
xor edx, edx
; divide
div ebx
dec ecx ; next char
inc esi
; store
add dl, '0'
mov byte [ecx], dl
; check if done
test eax, eax
jnz .div_shit ; continue
mov edx, esi ; counter in edx
jmp .write
.zero:
mov byte [ecx], '0'
mov edx, 1 ; length
.write:
mov eax, 4 ; write
mov ebx, 1 ; stdout
int 0x80
add esp, 12 ; restore stack
popad ; restore regs
ret
; input in EAX, all regs unmodified
print_sign_dec:
pushad ; save regs
; range -2147483648 to 2147483647 is 11 chars
; round to nearest 32-bit boundary
sub esp, 12
; string in ECX, length in EDX
lea ecx, [esp+11] ; last possible byte
; check for 0, negative
xor ebp, ebp
test eax, eax
jz .zero
jns .positive
neg eax
mov ebp, 1
.positive:
mov ebx, 10 ; base 10
xor esi, esi ; counter
.div_shit:
xor edx, edx
; divide
div ebx
dec ecx ; next char
inc esi
; store
add dl, '0'
mov byte [ecx], dl
; check if done
test eax, eax
jnz .div_shit ; continue
mov edx, esi ; counter in edx
jmp .write
.zero:
mov byte [ecx], '0'
mov edx, 1 ; length
.write:
test ebp, ebp
jz .no_minus
dec ecx
inc edx
mov byte [ecx], '-'
.no_minus:
mov eax, 4 ; write
mov ebx, 1 ; stdout
int 0x80
add esp, 12 ; restore stack
popad ; restore regs
ret
; input in ESI, len in ECX, all regs unmodified
print_string:
pushad ; save regs
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov edx, ecx ; length
mov ecx, esi ; string
int 0x80
popad ; restore regs
ret
; input in AL, all regs unmodified
print_char:
pushad ; save regs
push eax
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov edx, 1 ; length
mov ecx, esp ; string
int 0x80
add esp, 4
popad ; restore regs
ret
; --- MACROS ---
%define len(x) x %+ .over - x
%macro p_string 1
push esi
push ecx
mov esi, %1
mov ecx, len(%1)
call print_string
pop ecx
pop esi
%endmacro