day 12 part 1&2

This commit is contained in:
Lucia Ceionia 2023-12-12 09:36:26 -06:00
parent dd65bf8a56
commit 400b90c50e
7 changed files with 2564 additions and 0 deletions

3
12/Makefile Normal file
View File

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

1000
12/input Normal file

File diff suppressed because it is too large Load Diff

1001
12/input5 Normal file

File diff suppressed because it is too large Load Diff

7
12/input_test Normal file
View File

@ -0,0 +1,7 @@
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1

171
12/main.s Normal file
View File

@ -0,0 +1,171 @@
global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
mov esi, file
parse_line:
; find first num
mov ebp, esi ; line start
.first_num:
mov edi, esi ; save before loc
call dec_parse
jc .first_num
; edi has pointer to just before numbers
mov ecx, edi
sub ecx, ebp
dec ecx ; space
xchg esi, ebp
mov [line_len], ecx
mov edi, line
rep movsb
xchg esi, ebp
mov dword [contiguous_broken+ 0], 0
mov dword [contiguous_broken+ 4], 0
mov dword [contiguous_broken+ 8], 0
mov dword [contiguous_broken+12], 0
mov dword [contiguous_broken+16], 0
mov dword [contiguous_broken+20], 0
mov dword [contiguous_broken+24], 0
mov dword [contiguous_broken+28], 0
mov dword [contiguous_broken+32], 0
mov dword [contiguous_broken+36], 0
mov dword [contiguous_broken+40], 0
mov dword [contiguous_broken+44], 0
mov dword [contiguous_broken+48], 0
mov dword [contiguous_broken+52], 0
mov dword [contiguous_broken+56], 0
mov dword [contiguous_broken+60], 0
mov edi, contiguous_broken
stosb
.next_num:
cmp byte [esi-1], 10 ; \n
je .newline
call dec_parse
jc .next_num
.got_num:
stosb
jmp .next_num
.newline:
push esi ; save input line
; clear cache
mov edi, cache
mov ecx, (cache.end - cache)/4
mov eax, -1
rep stosd
; setup do_stream vars
xor esi, esi ; line idx
mov ebp, [line_len]
xor edi, edi ; contiguous_broken idx
xor edx, edx ; poss_counter high
xor ebx, ebx ; poss_counter low
call do_stream ; call into recursive routine
add [final_value+0], ebx ; poss_counter low
adc [final_value+4], edx ; poss_counter high
mov eax, edx
call print_dec
call space
mov eax, ebx
call print_dec
call newline
jmp parse_line_cont
do_stream:
cmp byte [line+esi], '.'
je .cont
cmp byte [line+esi], '#'
jne .branch
.broke:
cmp byte [contiguous_broken+edi], 0
je .ret ; branch impossible
movzx ecx, byte [contiguous_broken+edi]
inc edi
.consume_things:
mov al, byte [line+esi]
inc esi
cmp esi, ebp
ja .ret ; branch impossible
cmp al, '.'
je .ret ; branch impossible
loop .consume_things
cmp esi, ebp
je .cont
cmp byte [line+esi], '#'
je .ret ; branch impossible
; .cont consumes . or ? (must be .)
jmp .cont
.branch: ; recursive branch
mov eax, esi
shl eax, 8 ; *256
cmp dword [eax+edi*8+cache], -1
je .not_cached
add ebx, [eax+edi*8+(cache+0)]
adc edx, [eax+edi*8+(cache+4)]
jmp .cont
.not_cached:
push edx
push ebx
push esi
push edi
xor ebx, ebx
xor edx, edx
call do_stream.broke ; assume #
pop edi
pop esi
mov eax, esi
shl eax, 8
mov [eax+edi*8+(cache+0)], ebx
mov [eax+edi*8+(cache+4)], edx
pop eax
add ebx, eax
pop eax
adc edx, eax
; assume .
.cont:
inc esi
cmp esi, ebp
jb do_stream
; iff we are at the end of stream
; and contiguous_broken is exhausted
; we add a possibility
cmp byte [contiguous_broken+edi], 0
jne .ret
add ebx, 1 ; poss counter
adc edx, 0
.ret:
ret
parse_line_cont:
pop esi
cmp esi, file.over-1
jb parse_line
call newline
game_over:
mov eax, [final_value+4]
call print_dec
call space
mov eax, [final_value+0]
call print_dec
call newline
jmp exit
[section .data]
line_len: dd 0
final_value: dd 0, 0
final_setting: dd 0, 0
curr_setting: dd 0, 0
file: incbin "input5"
.over:
nl_str: db "new line!"
.over:
[section .bss]
contiguous_broken: resb 64
line: resb 512
cache: resd 256*64*2
cache.end:

124
12/main_part1.s Normal file
View File

@ -0,0 +1,124 @@
global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
mov esi, file
parse_line:
; find first num
mov ebp, esi ; line start
.first_num:
mov edi, esi ; save before loc
call dec_parse
jc .first_num
; edi has pointer to just before numbers
mov ecx, edi
sub ecx, ebp
dec ecx ; space
xchg esi, ebp
mov [line_len], ecx
mov edi, line
rep movsb
xchg esi, ebp
mov dword [contiguous_broken+ 0], 0
mov dword [contiguous_broken+ 4], 0
mov dword [contiguous_broken+ 8], 0
mov dword [contiguous_broken+12], 0
mov edi, contiguous_broken
stosb
.next_num:
cmp byte [esi-1], 10 ; \n
je .newline
call dec_parse
jc .next_num
.got_num:
stosb
jmp .next_num
.newline:
push esi ; save input line
mov esi, line
mov ecx, [line_len]
xor ebx, ebx
count_qs:
lodsb
cmp al, '?'
jne .cont
stc
rcl ebx, 1
.cont:
loop count_qs
push ebx ; ? final setting
test_possibilities:
xor ebp, ebp ; ? settings
xor ebx, ebx ; poss counter
.next_poss:
mov edx, ebp
mov esi, line
mov ecx, [line_len]
xor eax, eax ; ah - curr broke run, al - lodsb
mov edi, contiguous_broken
.next_poss_loop:
lodsb
cmp al, '.'
je .working
cmp al, '#'
je .broke
; else ? - select based on edx
rcr edx, 1
jc .broke
.working:
cmp ah, 0
je .cont ; no broke
cmp [edi], ah
jne .fail_poss
inc edi
mov ah, 0
jmp .cont
.broke:
inc ah
.cont:
loop .next_poss_loop
cmp [edi], ah
jne .fail_poss
cmp byte [edi+1], 0
jne .fail_poss
inc ebx ; poss counter
mov eax, ebp
;call print_dec
;call space
.fail_poss:
.next_poss_cont:
inc ebp ; ? settings
cmp ebp, [esp] ; cmp to final
jbe .next_poss
;call newline
mov eax, ebx
call print_dec
call newline
add [final_value], ebx
add esp, 4
pop esi
cmp esi, file.over-1
jb parse_line
call newline
game_over:
mov eax, [final_value]
call print_dec
call newline
jmp exit
[section .data]
final_value: dd 0
line_len: dd 0
file: incbin "input"
.over:
nl_str: db "new line!"
.over:
[section .bss]
contiguous_broken: resb 16
line: resb 256

258
12/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