415 lines
7.3 KiB
ArmAsm
415 lines
7.3 KiB
ArmAsm
|
%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
|