364 lines
6.3 KiB
ArmAsm
364 lines
6.3 KiB
ArmAsm
|
%include "utils.s"
|
||
|
|
||
|
global _start
|
||
|
[bits 32]
|
||
|
[section .text]
|
||
|
|
||
|
; len +2 for padding
|
||
|
%define LINE_LEN (141+2)
|
||
|
%define FILENAME "input"
|
||
|
;%define LINE_LEN (13+2)
|
||
|
;%define FILENAME "input_test"
|
||
|
|
||
|
;%define DBG_PRINT
|
||
|
|
||
|
_start:
|
||
|
|
||
|
; convert input file to useful data
|
||
|
mov esi, file
|
||
|
mov edi, cost
|
||
|
convert_input:
|
||
|
lodsb
|
||
|
cmp al, 10 ; \n
|
||
|
je .cont
|
||
|
cmp al, '$'
|
||
|
jne .num
|
||
|
mov al, 0xFF
|
||
|
stosb
|
||
|
jmp .cont
|
||
|
.num:
|
||
|
sub al, '0'
|
||
|
stosb
|
||
|
.cont:
|
||
|
cmp esi, file.over
|
||
|
jb convert_input
|
||
|
|
||
|
; im lazy so doing dijkstra
|
||
|
; thanks wikipedia
|
||
|
|
||
|
; for each vertex v in Graph.Vertices:
|
||
|
; dist[v] ← INFINITY
|
||
|
; prev[v] ← UNDEFINED
|
||
|
; add v to Q
|
||
|
mov ecx, LINE_LEN*LINE_LEN*16
|
||
|
mov eax, 0xffffffff
|
||
|
mov edi, dist
|
||
|
rep stosd
|
||
|
mov ecx, LINE_LEN*LINE_LEN*16
|
||
|
mov eax, 0xffffffff
|
||
|
mov edi, prev
|
||
|
rep stosd
|
||
|
mov ecx, LINE_LEN*LINE_LEN*16
|
||
|
mov eax, 1
|
||
|
mov edi, q
|
||
|
rep stosb
|
||
|
|
||
|
; for all real dir:
|
||
|
; dist[source@dir] ← 0
|
||
|
mov dword [dist+((((LINE_LEN*16)+16))|0b0000)*4], 0
|
||
|
mov dword [dist+((((LINE_LEN*16)+16))|0b1000)*4], 0
|
||
|
|
||
|
|
||
|
|
||
|
; while Q is not empty and any dist[u] in Q < inf:
|
||
|
; u ← vertex in Q with min dist[u]
|
||
|
while_q:
|
||
|
xor ebp, ebp ; test node
|
||
|
mov ecx, 0xffffffff ; best dist
|
||
|
mov edx, 0xffffffff ; best node
|
||
|
.find_min:
|
||
|
cmp byte [q+ebp], 1
|
||
|
jne .cont
|
||
|
cmp [dist+ebp*4], ecx
|
||
|
cmovb ecx, [dist+ebp*4]
|
||
|
cmovb edx, ebp
|
||
|
.cont:
|
||
|
inc ebp
|
||
|
cmp ebp, LINE_LEN*LINE_LEN*16
|
||
|
jb .find_min
|
||
|
cmp ecx, 0xffffffff
|
||
|
je while_q_done
|
||
|
|
||
|
%ifdef DBG_PRINT
|
||
|
pushad
|
||
|
call newline
|
||
|
mov ebp, edx
|
||
|
mov eax, edx
|
||
|
xor edx, edx
|
||
|
shr eax, 4
|
||
|
mov ebx, LINE_LEN
|
||
|
div ebx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, ebp
|
||
|
and eax, 0b1111
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, ecx
|
||
|
call print_dec
|
||
|
call newline
|
||
|
popad
|
||
|
%endif
|
||
|
|
||
|
; remove u from Q
|
||
|
mov byte [q+edx], 0
|
||
|
|
||
|
; for each neighbor v of u still in Q:
|
||
|
; alt ← dist[u] + Graph.Edges(u, v)
|
||
|
; if alt < dist[v]:
|
||
|
; dist[v] ← alt
|
||
|
; prev[v] ← u
|
||
|
mov ebp, LINE_LEN*16 ; whatever
|
||
|
for_neighbor:
|
||
|
; turning neighbor 0
|
||
|
neighbor_0:
|
||
|
; neighbors += v@dir(u, ~u.dir & 0b1000)
|
||
|
mov ebx, edx
|
||
|
not ebx
|
||
|
and ebx, 0b1000
|
||
|
; tmp := 16
|
||
|
mov edi, 16
|
||
|
; bt dir, 3
|
||
|
bt ebx, 3
|
||
|
; if CF tmp := LINE_LEN
|
||
|
cmovc edi, ebp
|
||
|
; bt dir, 2
|
||
|
; if CF tmp := -tmp
|
||
|
mov esi, edi
|
||
|
neg esi
|
||
|
bt ebx, 2
|
||
|
cmovc edi, esi
|
||
|
; v := u + tmp
|
||
|
mov esi, edx
|
||
|
and esi, 0xFFFFFFF0
|
||
|
add edi, esi
|
||
|
; v.dir := dir
|
||
|
or edi, ebx
|
||
|
; alt ← dist[u] + cost(v)
|
||
|
; if alt < dist[v]:
|
||
|
; dist[v] ← alt
|
||
|
; prev[v] ← u
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
movzx eax, byte [cost+eax]
|
||
|
cmp al, 0xff
|
||
|
je neighbor_1 ; off graph
|
||
|
add eax, ecx
|
||
|
%ifdef DBG_PRINT
|
||
|
pushad
|
||
|
call space
|
||
|
mov esi, eax
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
mov ecx, LINE_LEN
|
||
|
xor edx, edx
|
||
|
div ecx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edi
|
||
|
and eax, 0xf
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, esi
|
||
|
call print_dec
|
||
|
call newline
|
||
|
popad
|
||
|
%endif
|
||
|
cmp eax, [dist+edi*4]
|
||
|
jae neighbor_1 ; not better
|
||
|
mov [dist+edi*4], eax
|
||
|
mov [prev+edi*4], edx
|
||
|
; turning neighbor 1
|
||
|
neighbor_1:
|
||
|
; neighbors += v@dir(u, (~u.dir & 0b1000) | 0b0100)
|
||
|
mov ebx, edx
|
||
|
not ebx
|
||
|
and ebx, 0b1000
|
||
|
or ebx, 0b0100
|
||
|
; tmp := 16
|
||
|
mov edi, 16
|
||
|
; bt dir, 3
|
||
|
bt ebx, 3
|
||
|
; if CF tmp := LINE_LEN
|
||
|
cmovc edi, ebp
|
||
|
; bt dir, 2
|
||
|
; if CF tmp := -tmp
|
||
|
mov esi, edi
|
||
|
neg esi
|
||
|
bt ebx, 2
|
||
|
cmovc edi, esi
|
||
|
; v := u + tmp
|
||
|
mov esi, edx
|
||
|
and esi, 0xFFFFFFF0
|
||
|
add edi, esi
|
||
|
; v.dir := dir
|
||
|
or edi, ebx
|
||
|
; alt ← dist[u] + cost(v)
|
||
|
; if alt < dist[v]:
|
||
|
; dist[v] ← alt
|
||
|
; prev[v] ← u
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
movzx eax, byte [cost+eax]
|
||
|
cmp al, 0xff
|
||
|
je neighbor_2 ; off graph
|
||
|
add eax, ecx
|
||
|
%ifdef DBG_PRINT
|
||
|
pushad
|
||
|
call space
|
||
|
mov esi, eax
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
mov ecx, LINE_LEN
|
||
|
xor edx, edx
|
||
|
div ecx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edi
|
||
|
and eax, 0xf
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, esi
|
||
|
call print_dec
|
||
|
call newline
|
||
|
popad
|
||
|
%endif
|
||
|
cmp eax, [dist+edi*4]
|
||
|
jae neighbor_2 ; not better
|
||
|
mov [dist+edi*4], eax
|
||
|
mov [prev+edi*4], edx
|
||
|
; straight - neighbor 2
|
||
|
neighbor_2:
|
||
|
; if u.dir & 0b0011 < 2
|
||
|
; neighbors += v@dir(u, u.dir + 1)
|
||
|
mov ebx, edx
|
||
|
and ebx, 0b0011
|
||
|
cmp ebx, 2
|
||
|
jae while_q_cont ; neighbors done
|
||
|
mov ebx, edx
|
||
|
and ebx, 0b1111
|
||
|
inc ebx
|
||
|
; tmp := 16
|
||
|
mov edi, 16
|
||
|
; bt dir, 3
|
||
|
bt ebx, 3
|
||
|
; if CF tmp := LINE_LEN
|
||
|
cmovc edi, ebp
|
||
|
; bt dir, 2
|
||
|
; if CF tmp := -tmp
|
||
|
mov esi, edi
|
||
|
neg esi
|
||
|
bt ebx, 2
|
||
|
cmovc edi, esi
|
||
|
; v := u + tmp
|
||
|
mov esi, edx
|
||
|
and esi, 0xFFFFFFF0
|
||
|
add edi, esi
|
||
|
; v.dir := dir
|
||
|
or edi, ebx
|
||
|
; alt ← dist[u] + cost(v)
|
||
|
; if alt < dist[v]:
|
||
|
; dist[v] ← alt
|
||
|
; prev[v] ← u
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
movzx eax, byte [cost+eax]
|
||
|
cmp al, 0xff
|
||
|
je while_q_cont ; off graph
|
||
|
add eax, ecx
|
||
|
%ifdef DBG_PRINT
|
||
|
pushad
|
||
|
call space
|
||
|
mov esi, eax
|
||
|
mov eax, edi
|
||
|
shr eax, 4
|
||
|
mov ecx, LINE_LEN
|
||
|
xor edx, edx
|
||
|
div ecx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edx
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, edi
|
||
|
and eax, 0xf
|
||
|
call print_dec
|
||
|
call space
|
||
|
mov eax, esi
|
||
|
call print_dec
|
||
|
call newline
|
||
|
popad
|
||
|
%endif
|
||
|
cmp eax, [dist+edi*4]
|
||
|
jae while_q_cont ; not better
|
||
|
mov [dist+edi*4], eax
|
||
|
mov [prev+edi*4], edx
|
||
|
|
||
|
while_q_cont:
|
||
|
jmp while_q
|
||
|
|
||
|
while_q_done:
|
||
|
|
||
|
call newline
|
||
|
|
||
|
; last dist values
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0000)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0001)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0010)*4]
|
||
|
call print_sign_dec
|
||
|
call newline
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0100)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0101)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b0110)*4]
|
||
|
call print_sign_dec
|
||
|
call newline
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1000)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1001)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1010)*4]
|
||
|
call print_sign_dec
|
||
|
call newline
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1100)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1101)*4]
|
||
|
call print_sign_dec
|
||
|
call space
|
||
|
mov eax, [dist+((((LINE_LEN-2)*(LINE_LEN*16))+((LINE_LEN-2)*16))+0b1110)*4]
|
||
|
call print_sign_dec
|
||
|
call newline
|
||
|
|
||
|
game_over:
|
||
|
jmp exit
|
||
|
|
||
|
[section .data]
|
||
|
file: incbin FILENAME
|
||
|
.over:
|
||
|
|
||
|
[section .bss]
|
||
|
dist: resd LINE_LEN*LINE_LEN*16
|
||
|
prev: resd LINE_LEN*LINE_LEN*16
|
||
|
q: resb LINE_LEN*LINE_LEN*16
|
||
|
cost: resb LINE_LEN*LINE_LEN
|
||
|
new_file: resb len(file)
|