Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .section .maze, "aw"
- .align 3
- .global laberinto
- .section .data
- estado: .dword 0x4e45204f4745554a, 0x21214f5352554320
- _stack_ptr: .dword _stack_end
- // ------------- Modificar para agregar datos constantes --------------
- // --------------------------------------------------------------------
- .section .text
- .global _start
- _start:
- ldr x1, =_stack_ptr
- ldr x1, [x1]
- mov sp, x1
- mov x0, xzr
- mov x4, xzr
- ldr x0, =laberinto
- /* w11 es flag para indicar si se puede avanzar o no.
- * x19 es flag para indicar la direccion actual:
- * 0 = arriba, 1 = derecha, 2 = abajo, 3 = izquierda.
- * x1 es el contador de pasos.
- * x3 es la fila, x4 es la columna. (x3, x4) es una coodernada
- *
- */
- main:
- // ------------- El código principal debe ir aqui abajo ---------------
- // Iniciamos el contador de pasos en 0
- mov x1, xzr
- // Buscamos la posicion inicial de X en el laberinto
- // x9 tendra la dirección de memoria de X
- bl seeking_x
- // Orientación inicial mirando hacia abajo DIR_DOWN = 2
- // x19 mira para abajo
- mov x19, #DIR_DOWN
- // Hand-on-wall rule
- // https://en.wikipedia.org/wiki/Maze-solving_algorithm
- resolve_loop:
- // Intentamos ir a la izquierda relativa (relativa a x19)
- bl turn_left
- // Chequeamos si podemos avanzar a la izquierda relativa a x19
- bl peek_forward
- // si w11=0, entonces es transitable,
- // si w11=1 entonces es pared, seguimos intentando
- cbz w11, do_move
- // Como no pudimos ir a la izquierda,
- // deshacemos el giro
- bl turn_right
- // Intentamos ir al frente (relativo a x19)
- bl peek_forward
- // si w11=0, entonces es transitable,
- // si w11=1 entonces es pared, seguimos intentando
- cbz w11, do_move
- // No pudimos ir al frente, entonces
- // Intentamos ir a la derecha (relativa a x19)
- bl turn_right
- bl peek_forward
- // si w11=0, entonces es transitable,
- // si w11=1 entonces es pared, seguimos intentando
- cbz w11, do_move
- // No pudimos ir a la derecha, entonces
- // Intentamos ir para atrás (relativo a x19)
- // Como ya estabamos mirando a la derecha de x19,
- // girar a la derecha otra vez nos deja mirando para atrás de x19,
- bl turn_right
- // intentar avanzar para atrás
- bl peek_forward
- cbz w11, do_move
- // callejon sin salida, no deberia suceder en un laberinto valido
- b resolve_loop
- do_move:
- // Luz verde para avanzar,
- // x19 es la dirección a la que estamos mirando,
- // Calculamos coordenadas destino (x12, x13)
- mov x12, x3
- mov x13, x4
- // Si estamos mirando para arriba, la fila destino es fila-1
- cmp x19, #DIR_UP
- b.eq do_move_up
- // Si estamos mirando para la derecha, la columna destino es col+1
- cmp x19, #DIR_RIGHT
- b.eq do_move_right
- // Si estamos mirando para abajo, la fila destino es fila+1
- cmp x19, #DIR_DOWN
- b.eq do_move_down
- // Si estamos mirando para la izquierda, la columna destino es col-1
- sub x13, x13, #1
- b do_move_map
- do_move_up:
- // fila destino es fila-1
- sub x12, x12, #1
- b do_move_map
- do_move_right:
- add x13, x13, #1
- b do_move_map
- do_move_down:
- add x12, x12, #1
- do_move_map:
- // calculamos direccion destino
- // x14 = base + fila*16 + col
- mov x14, x0
- mov x15, #16
- madd x14, x15, x12, x14
- add x14, x14, x13
- // en este punto x14 es la direccion destino
- // leemos el byte destino
- ldrb w5, [x14]
- // verificamos si es la salida
- cmp w5, #SALIDA
- b.eq reached_exit
- // Como no era salida, entonces es un espacio transitable, avanzamos,
- // escribimos espacio en la posición vieja (x9 = dirección actual de X)
- mov w8, #ESPACIO
- strb w8, [x9]
- // escribimos X en la posición nueva (x14 = dirección destino)
- mov w8, #PERSONA
- strb w8, [x14]
- // seteamos coordenadas actuales a las coordenadas destino
- // es decir, donde ahora se encuentra el personaje X
- mov x3, x12
- mov x4, x13
- mov x9, x14
- // incrementar contador de pasos
- add x1, x1, #1
- // seguimos intentando
- b resolve_loop
- // --------------------------------------------------------------------
- /*
- * La funcion reached_exit se llama cuando el personaje
- * llega a la salida del laberinto. Escribe "Juego finalizado"
- * en el estado, y luego entra en un loop infinito.
- */
- reached_exit:
- ldr x20, =estado
- mov x21, #0x754A
- movk x21, #0x6765, lsl #16
- movk x21, #0x206F, lsl #32
- movk x21, #0x6966, lsl #48
- str x21, [x20]
- mov x22, #0x616E
- movk x22, #0x6C69, lsl #16
- movk x22, #0x617A, lsl #32
- movk x22, #0x6F64, lsl #48
- str x22, [x20, #8]
- add x1, x1, #1
- infloop: b infloop
- /*
- * peek_forward chequea si la celda del frente es transitable
- *
- * Como X puede estar mirando en cualquier direccion (segun x19),
- * calculamos cual es la celda al frente y leemos su contenido.
- *
- * La direccion de memoria del destino se calcula con la formula del paper:
- * dir = base + fila*16 + columna
- * Luego leemos el byte y lo comparamos con 0x20 y 0x23, espacio y salida resp.
- *
- * @param x0 = dir base
- * @param x3 = fila
- * @param x4 = columna
- * @param x19 = orientacion actual
- *
- * @return
- * w11 = 0 si la celda del frente es transitable
- * w11 = 1 si es pared o directamente no se puede transitar
- *
- * Temporales: x12 para fila destino,
- * x13 para columna destino,
- * x14 para direccion destino,
- * x15 para multiplicar fila por 16
- *
- * No modifica: x0, x3, x4, x9, x19
- */
- peek_forward:
- mov x12, x3
- mov x13, x4
- // si estamos mirando arriba, la fila destino es fila-1
- cmp x19, #DIR_UP
- b.eq peek_forward_up
- // si estamos mirando a la derecha, la columna destino es col+1
- cmp x19, #DIR_RIGHT
- b.eq peek_forward_right
- // si estamos mirando abajo, la fila destino es fila+1
- cmp x19, #DIR_DOWN
- b.eq peek_forward_down
- // si estamos mirando a la izquierda, la columna destino es col-1
- sub x13, x13, #1
- b peek_forward_map
- peek_forward_up:
- sub x12, x12, #1
- b peek_forward_map
- peek_forward_right:
- add x13, x13, #1
- b peek_forward_map
- peek_forward_down:
- add x12, x12, #1
- peek_forward_map:
- // Calculamos la dirección destino
- // dirección = base + fila*16 + col
- mov x14, x0
- mov x15, #16
- madd x14, x15, x12, x14
- add x14, x14, x13
- // Leemos el byte destino
- ldrb w5, [x14]
- // Comparamos con espacio y salida
- cmp w5, #ESPACIO
- b.eq peek_forward_go
- cmp w5, #SALIDA
- b.eq peek_forward_go
- // no es ni espacio ni salida, entonces no es transitable
- // seteamos la flag w11 a 1 para indicar que no se puede avanzar
- mov w11, #1
- b peek_forward_end
- peek_forward_go:
- // es transitable,
- // seteamos la flag w11 a 0 para indicar que se puede avanzar
- mov w11, #0
- peek_forward_end:
- // retornamos
- br x30
Advertisement