%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)