day 15 part1&2

This commit is contained in:
Lucia Ceionia 2023-12-15 01:58:12 -06:00
parent 5b6a60a62a
commit 9ecb520b5c
6 changed files with 467 additions and 0 deletions

3
15/Makefile Normal file
View File

@ -0,0 +1,3 @@
all:
nasm -g -felf32 main.s && ld -melf_i386 -g main.o

1
15/input Normal file

File diff suppressed because one or more lines are too long

1
15/input_test Normal file
View File

@ -0,0 +1 @@
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7

160
15/main.s Normal file
View File

@ -0,0 +1,160 @@
global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
; HASH
mov esi, file
xor ebx, ebx ; current value
xor edi, edi ; current label high
xor ecx, ecx ; current label low
mov ebp, 17 ; mul value
hash:
movzx eax, byte [esi]
inc esi
cmp al, 10
je next_seq
cmp al, '-'
je minus
cmp al, '='
je equals
; save label
cmp ecx, 0x00ffffff
ja .needs_high
shl ecx, 8
mov cl, al
jmp .do_hash
.needs_high:
xchg eax, edi
shl eax, 8
mov al, cl
xchg eax, edi
mov cl, al
.do_hash:
; do HASH
; current += new
add eax, ebx
; current *= 17
mul ebp
; current %= 256
movzx ebx, al
jmp hash
; i'm not using a linked list whatever
minus:
; box *box = boxes+current*1024
shl ebx, 10
lea ebp, [ebx+boxes]
lea ebx, [ebx+boxes+4]
; box->max
mov eax, [ebp]
.find_eq:
test eax, eax
jz .done
dec eax
cmp [ebx], ecx
jne .cont
cmp [ebx+4], edi
jne .cont
xchg esi, edx
; remove match, move others down
mov edi, ebx
lea esi, [ebx+12]
; len = eax*8 + eax*4
mov ecx, eax
shl ecx, 3
shl eax, 2
add ecx, eax
rep movsd
xchg esi, edx
; decrease max
dec dword [ebp]
jmp .done
.cont:
add ebx, 12
jmp .find_eq
.done:
inc esi
jmp next_seq
equals:
; box *box = boxes+current*1024
shl ebx, 10
lea ebp, [ebx+boxes]
lea ebx, [ebx+boxes+4]
; box->max
mov eax, [ebp]
.find_eq:
test eax, eax
jz .no_match
dec eax
cmp [ebx], ecx
jne .cont
cmp [ebx+4], edi
jne .cont
; update match
mov al, [esi] ; ascii num
sub al, '0' ; to binary
mov [ebx+8], al
jmp .done
.cont:
add ebx, 12
jmp .find_eq
.no_match:
; new entry
mov [ebx], ecx
mov [ebx+4], edi
mov al, [esi]
sub al, '0'
mov [ebx+8], al
; inc max
inc dword [ebp]
.done:
add esi, 2
next_seq:
xor ebx, ebx ; current value
xor edi, edi ; current label high
xor ecx, ecx ; current label low
mov ebp, 17 ; mul value
cmp esi, file.over
jb hash
mov esi, boxes
calc_shit:
cmp dword [esi], 0
je .cont
mov edi, esi
sub edi, boxes
shr edi, 10 ; box idx
inc edi ; box num
mov ecx, 1 ; slot num
lea ebx, [esi+4] ; lenses
.inner:
mov eax, edi ; box num
mul ecx ; slot num
mul dword [ebx+8] ; focal length
add [final_value], eax
add ebx, 12
inc ecx
cmp ecx, [esi]
jbe .inner
.cont:
add esi, 1024
cmp esi, boxes.end
jb calc_shit
game_over:
mov eax, [final_value]
call print_dec
call newline
jmp exit
[section .data]
final_value: dd 0
file: incbin "input"
.over:
[section .bss]
boxes: resb 256*1024
.end:

44
15/main_part1.s Normal file
View File

@ -0,0 +1,44 @@
global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
; HASH
mov esi, file
xor ebx, ebx ; current value
mov ebp, 17 ; mul value
hash:
movzx eax, byte [esi]
inc esi
cmp al, ','
jle .next_seq
; do HASH
; current += new
add eax, ebx
; current *= 17
mul ebp
; current %= 256
movzx ebx, al
jmp hash
.next_seq:
add [final_value], ebx
xor ebx, ebx
cmp esi, file.over
jb hash
game_over:
mov eax, [final_value]
call print_dec
call newline
jmp exit
[section .data]
final_value: dd 0
file: incbin "input"
.over:
[section .bss]

258
15/utils.s Normal file
View File

@ -0,0 +1,258 @@
; 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