adventofcode2023/05/main.s

415 lines
7.3 KiB
ArmAsm
Raw Normal View History

2023-12-05 07:49:20 -06:00
%define BUFF_LIM 32768
global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
mov ebx, filename
call open_file
mov ecx, read_buff
mov edx, BUFF_LIM
call read_file
add eax, read_buff
mov [file_lim], eax
; skip until :
; loop until :
; get next number
; save in seeds@seedcnt
; increment seedcnt
; end
;
; get the map tables
; current_map := 0
; do 7 times
; loop until :
; get next number
; save in tmp
; get next number
; save in ((maps@current_map)@current_line)+4 SRC
; get next number
; save in ((maps@current_map)@current_line)+8 RNG
; tmp := tmp - SRC
; changes DEST to represent *change* in location
; save in ((maps@current_map)@current_line)+0 DEST
; end
; end
;
; for (seed,srng) in seeds
; list_bs@0 := (seed,srng,0)
; listcnt := 1
; for m in maps
; for (d,s,r) in m
; listi := 0
; maxs := s + r - 1
; while listi < listcnt
; (is, ir, mod) := list_bs@listi
; if mod is map .cont
; maxi := is + ir - 1
; if maxi < s .cont
; if is > maxs .cont
; fr := greater(is, s)
; lr := less(maxi, maxs)
; rr := lr - fr + 1
; .chk_AE:
; if is < fr
; (list_bs@listi).r := fr - is
; NEWENT(fr + d, rr, map)
; else
; (list_bs@listi).s := fr + d
; (list_bs@listi).r := rr
; (list_bs@listi).mod := map
; end
; .chk_AF:
; if imax > lr
; NEWENT(lr + 1, imax - lr, mod)
; end
; .cont: inc listi
; end
; end
; end
; find smallest
; tmp := final_value
; for (is, _, _) in list_bs
; if is < tmp then tmp := is
; end
; final_value := tmp
; end
; output final_value
; skip until :
mov esi, read_buff
skip_to_nums:
lodsb
cmp al, ':'
jne skip_to_nums
; loop until :
; get next number
; save in seeds@seedcnt
; increment seedcnt
; end
inc esi
xor ebx, ebx ; seedcnt
get_seeds:
cmp byte [esi-1], ':'
je .got_seeds
call dec_parse
jc get_seeds
; save number
mov [seeds+ebx*4], eax
inc ebx
jmp get_seeds
.got_seeds:
mov [seedcnt], ebx
inc esi ; don't retrigger : check
; get the map tables
; current_map := 0
mov dword [current_map], 0
; do 7 times
; ...
; end
mov ecx, 7
process_maps:
push ecx
; loop until :
; ...
; end
mov edi, [current_map]
mov edi, [maps+edi*4]
push ebx
push ecx
push edx
map_chk:
; get next number
; save in tmp
; get next number
; save in ((maps@current_map)@current_line)+4 SRC
; get next number
; save in ((maps@current_map)@current_line)+8 RNG
; tmp := tmp - SRC
; changes DEST to represent *change* in location
; save in ((maps@current_map)@current_line)+0 DEST
.get_dest:
cmp byte [esi-1], ':' ; make sure we aren't passing into new map
je .map_done
call dec_parse
jc .get_dest
; save in tmp
mov ebx, eax
.get_src:
call dec_parse
jc .get_src
; save in ((maps@current_map)@current_line)+4 SRC
mov ecx, eax
.get_rng:
call dec_parse
jc .get_rng
; save in ((maps@current_map)@current_line)+8 RNG
mov edx, eax
; tmp := tmp - SRC
; changes DEST to represent *change* in location
; save in ((maps@current_map)@current_line)+0 DEST
sub ebx, ecx
mov eax, ebx
stosd
mov eax, ecx
stosd
mov eax, edx
stosd
jmp map_chk
.map_done:
inc dword [current_map]
pop edx
pop ecx
pop ebx
; process_maps loop
inc esi ; skip ':'
pop ecx
dec ecx
test ecx, ecx
jnz process_maps
; debug print maps
;mov ecx, 0
;dbg_maps:
;push ecx
;mov esi, [maps+ecx*4]
;.lines:
;xor ebx, ebx
;lodsd
;add ebx, eax
;call print_dec
;call space
;lodsd
;add ebx, eax
;call print_dec
;call space
;lodsd
;add ebx, eax
;call print_dec
;call newline
;test ebx, ebx
;jnz .lines
;call newline
;inc ecx
;cmp ecx, 7
;jb dbg_maps
; for (seed,srng) in seeds
mov eax, [seedcnt]
shr eax, 1
mov esi, seeds
for_seeds:
push eax ; seed count
; list_bs@0 := (seed,srng,0)
; listcnt := 1
mov edi, list_bs
movsd ; seed
movsd ; srng
push esi ; seed ptr
xor eax, eax
stosd ; mod
mov dword [listcnt], 1
; for m in maps
mov ecx, 0
for_maps:
mov ebp, [maps+ecx*4] ; map
push ecx ; map idx
; for line in m
mov esi, ebp ; line := map@0
sub esp, 32 ; space for 0 ?, 4 ?, 8 map, 12 mod, 16 d, 20 r, 24 lineptr, 28 list counter
for_lines:
lodsd
mov [esp+16], eax ; d
lodsd
mov edx, eax ; s
lodsd
mov [esp+20], eax ; r
test eax, eax
jz for_lines_end ; null entry - we're done
mov [esp+24], esi ; lineptr
; maxs := s + r - 1
mov edi, [esp+20]
add edi, edx
dec edi
; for i in listcnt
mov eax, [listcnt]
mov [esp+28], eax
mov esi, list_bs
for_in_list:
lodsd
mov ecx, eax ; is
lodsd
mov ebx, eax ; ir
lodsd ; mod
; if mod is map continue
cmp eax, ebp
je for_in_list_cont
; maxi := is + ir - 1
add ebx, ecx ; maxi, ir not needed anymore
dec ebx
; if maxi < s .cont
; if is > maxs .cont
cmp ebx, edx
jb for_in_list_cont
cmp ecx, edi
ja for_in_list_cont
; make space
mov [esp], edi ; maxs
mov [esp+4], edx ; s
mov [esp+8], ebp ; map
mov [esp+12],eax ; mod
; fr := greater(is, s)
; lr := less(maxi, maxs)
; rr := lr - fr + 1
cmp ecx, edx
cmova edx, ecx ; edx: fr
cmp ebx, edi
cmovb edi, ebx ; edi: lr
.chk_AE:
; if is < fr
cmp ecx, edx
jae .chk_AE_else
; (list_bs@listi).r := fr - is
mov eax, edx
sub eax, ecx
mov [esi-8], eax
; NEWENT(fr + d, rr, map)
mov eax, [listcnt]
shl eax, 1
add eax, [listcnt]
lea eax, [list_bs+eax*4]
mov [eax+8], ebp ; map
mov ebp, edi
sub ebp, edx
inc ebp
mov [eax+4], ebp ; rr
add edx, [esp+16]
mov [eax], edx ; fr + d
inc dword [listcnt]
jmp .chk_AF
.chk_AE_else:
; else
; (list_bs@listi).mod := map
mov [esi-4], ebp
; (list_bs@listi).r := rr
mov eax, edi
sub eax, edx
inc eax
mov [esi-8], eax
; (list_bs@listi).s := fr + d
add edx, [esp+16]
mov [esi-12], edx ; d
.chk_AF:
; if imax > lr
cmp ebx, edi
jbe .chk_AF_not
; NEWENT(lr + 1, maxi - lr, mod)
mov eax, [listcnt]
shl eax, 1
add eax, [listcnt]
lea eax, [list_bs+eax*4]
mov edx, [esp+12]
mov [eax+8], edx ; mod
sub ebx, edi
mov [eax+4], ebx ; maxi - lr
inc edi
mov [eax], edi ; lr + 1
inc dword [listcnt]
.chk_AF_not:
; restore
mov edi, [esp] ; maxs
mov edx, [esp+4] ; s
mov ebp, [esp+8] ; map
mov eax, [esp+12] ; mod
for_in_list_cont:
sub dword [esp+28], 1 ; check if done
jnz for_in_list
; end
for_lines_cont:
mov esi, [esp+24] ; lineptr
jmp for_lines
for_lines_end:
add esp, 32 ; restore stack
; end
for_maps_cont:
pop ecx ; map idx
inc ecx
cmp ecx, 7
jl for_maps
; end
; find smallest
; tmp := final_value
; for (is, _, _) in list_bs
; if is < tmp then tmp := is
; end
; final_value := tmp
mov ebx, [final_value]
mov ecx, [listcnt]
mov esi, list_bs
find_smallest:
lodsd
cmp eax, ebx
cmovb ebx, eax
add esi, 8
loop find_smallest
mov [final_value], ebx
for_seeds_cont:
pop esi ; seed ptr
pop eax ; seed count
sub eax, 1
jnz for_seeds ; loop if not finished
; end
; done processing... at last
;output tmp
mov eax, [final_value]
call print_dec
game_over:
jmp exit
[section .data]
file_lim: dd 0
final_value: dd 0xffffffff
maps: dd seedsoil, soilfert, fertwater, waterlight, lighttemp, temphumid, humidloc
current_map: dd 0
filename: db "input",0
[section .bss]
seedcnt: resd 1
seeds: resd 64
seedsoil: resd 64*3
soilfert: resd 64*3
fertwater: resd 64*3
waterlight: resd 64*3
lighttemp: resd 64*3
temphumid: resd 64*3
humidloc: resd 64*3
read_buff: resb BUFF_LIM
listcnt: resd 1
list_bs: resb 2000000000