section .data               
;Cambiar Nombre y Apellido por vuestros datos.
developer db "_Enrique_ _García_",0

;Constantes que también están definidas en C.
DimMatrix    equ 3
SizeMatrix   equ DimMatrix*DimMatrix ;=9 


section .text            

;Variables definidas en Ensamblador.
global developer                        

;Subrutinas de ensamblador que se llaman desde C.
global copyMatrixP1, updateBoardP1, getSpacePosP1, posCurScreenP1,
global moveCursorP1, moveTileP1, checkEndP1, playP1

;Variables definidas en C.
extern spacePos, cursorPos, state, moves, rowScreen, colScreen, charac
extern tilesIni, tiles, tilesEnd

;Funciones de C que se llaman desde ensamblador.
extern clearScreen_C, printBoardP1_C, gotoxyP1_C, printchP1_C, getchP1_C
extern printMessageP1_C


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ATENCIÓN: Recordad que en ensamblador las variables y los parámetros 
;;   de tipo 'char' se tienen que asignar a registros de tipo
;;   BYTE (1 byte): al, ah, bl, bh, cl, ch, dl, dh, sil, dil, ..., r15b
;;   las de tipo 'short' se tiene que asignar a registros de tipo 
;;   WORD (2 bytes): ax, bx, cx, dx, si, di, ...., r15w
;;   las de tipo 'int' se tiene que asignar a registros de tipo  
;;   DWORD (4 bytes): eax, ebx, ecx, edx, esi, edi, ...., r15d
;;   las de tipo 'long' se tiene que asignar a registros de tipo 
;;   QWORD (8 bytes): rax, rbx, rcx, rdx, rsi, rdi, ...., r15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Les subrutinas en ensamblador que hay que implementar son:
;;   copyMatrixP1, updateBoardP1, getSpacePosP1, posCurScreenP1 
;;   moveCursorP1, moveTileP1, checkEndP1
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Situar el cursor en una fila indicada por la variable (rowScreen) y en 
; una columna indicada por la variable (colScreen) de pantalla 
; llamando a la función gotoxyP1_C.
; 
; Variables globales utilizadas:	
; (rowScreen): Fila de la pantalla donde posicionamos el cursor.
; (colScreen): Columna de la pantalla donde posicionamos el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gotoxyP1:
   push rbp
   mov  rbp, rsp
   ;guardamos el estado de los registros del procesador porque
   ;las funciones de C no mantienen el estado de los registros.
   push rax
   push rbx
   push rcx
   push rdx
   push rsi
   push rdi
   push r8
   push r9
   push r10
   push r11
   push r12
   push r13
   push r14
   push r15

   call gotoxyP1_C
 
   pop r15
   pop r14
   pop r13
   pop r12
   pop r11
   pop r10
   pop r9
   pop r8
   pop rdi
   pop rsi
   pop rdx
   pop rcx
   pop rbx
   pop rax

   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Mostrar un carácter guaardado en la varaile (charac) en pantalla, en
; la posición donde está el cursor llamando a la función printchP1_C.
; 
; Variables globales utilizadas:	
; (charac): Caracter que queremos mostrar.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printchP1:
   push rbp
   mov  rbp, rsp
   ;guardamos el estado de los registros del procesador porque
   ;las funciones de C no mantienen el estado de los registros.
   push rax
   push rbx
   push rcx
   push rdx
   push rsi
   push rdi
   push r8
   push r9
   push r10
   push r11
   push r12
   push r13
   push r14
   push r15

   call printchP1_C
 
   pop r15
   pop r14
   pop r13
   pop r12
   pop r11
   pop r10
   pop r9
   pop r8
   pop rdi
   pop rsi
   pop rdx
   pop rcx
   pop rbx
   pop rax

   mov rsp, rbp
   pop rbp
   ret
   

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Leer una tecla y guardar el carácter asociado en la varaible (charac) 
; sin mostrarlo en pantalla, llamando a la función getchP1_C
; 
; Variables globales utilizadas:	
; (charac): Carácter que queremos mostrar.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
getchP1:
   push rbp
   mov  rbp, rsp
   ;guardamos el estado de los registros del procesador porque
   ;las funciones de C no mantienen el estado de los registros.
   push rax
   push rbx
   push rcx
   push rdx
   push rsi
   push rdi
   push r8
   push r9
   push r10
   push r11
   push r12
   push r13
   push r14
   push r15

   call getchP1_C
 
   pop r15
   pop r14
   pop r13
   pop r12
   pop r11
   pop r10
   pop r9
   pop r8
   pop rdi
   pop rsi
   pop rdx
   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copiar la matriz (tilesIni), sobre la matriz (tiles).
; Recorrer toda la matriz por filas de izquierda a derecha y de arriba a abajo.
; Para recorrer la matriz en ensamblador el índice va de 0 (posición [0][0])
; a 8 (posición [2][2]) con incrementos de 1 porque los datos son de 
; tipo char(BYTE) 1 byte.
;
; Variables globales utilizadas:   
; (tilesIni): Matriz con las fichas iniciales del juego
; (tiles)   : Matriz donde guardamos la fichas del juego.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
copyMatrixP1:
   push rbp
   mov  rbp, rsp
   ;Empieza
   mov dword [rbp-4], 0
   jmp .L2
.L3:
   mov dword [rbp-8],0
   jmp .L4
.L5:
   mov eax, [rbp-4]
   sal eax, 2
   add eax, [rbp-8]
   mov ecx, eax
   mov edx, eax
   mov  dl, BYTE[tilesIni+edx] ;al = tilesIni[i][j]  
   mov BYTE [tiles+ecx],dl;t[i][j] = al
  
   
   
   add dword[rbp-8], 1
.L4:
   cmp dword [rbp-8], DimMatrix
   jl .L5
   add dword [rbp-4], 1
.L2:
   cmp dword [rbp-4], DimMatrix
   jl .L3
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mostrar los valores de la matriz (tiles), en pantalla, 
; dentro del tablero en las posiciones correspondientes.
; Recorrer toda la matriz por filas de izquierda a derecha y de arriba a abajo.
; Para recorrer la matriz en ensamblador el índice va de 0 (posición [0][0])
; a 9 (posiciones [2][2]) con incrementos de 1 porquè los datos son de
; tipo char(BYTE) 1 byte, y para cada elemento de la matriz:
; Posicionar el cursor en el tablero llamando a la subrutina gotoxyP1.
; La posición inicial del cursor es la fila 12 de la pantalla (fila 0 
; de la matriz), columna 8 de la pantalla (columna 0 de la matriz).
; Mostrar los caracteres de cada posición de la matriz (tiles) 
; llamando a la subrutina printchP1.
; Actualizar la columna (colScreen) de 4 en 4 y al cambiar de fila
; (rowScreen) de 2 en 2.
; Mostrar los movimientos que quedan por hacer (moves) dentro del tablero 
; en la fila 8, columna 20 de la pantalla.
; 
; Variables globales utilizadas:   
; (tiles)    : Matriz donde guardamos las fichas del juego.
; (moves)    : Movimientos que quedan para ordenar las fichas.
; (rowScreen): Fila de la pantalla donde posicionamos el cursor.
; (colScreen): Columna de la pantalla donde posicionamos el cursor.
; (charac)   : Carácter a escribir en pantalla.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
updateBoardP1:
   push rbp
   mov  rbp, rsp
   ;Empieza
   mov dword [rowScreen], 12
   mov dword [rbp-4], 0
   jmp .L2
.L3:
   mov dword [colScreen], 8
   mov dword [rbp-8], 0
   jmp .L4
.L5:
   call gotoxyP1
   mov eax, [rbp-4]
   sal eax, 2
   add eax, [rbp-8]
   movzx eax, byte [tiles+eax]
   mov byte [charac], al
   call printchP1
   add dword[colScreen], 4
   add dword[rbp-8], 1
.L4:
   cmp dword [rbp-8], DimMatrix
   jl .L5
   add dword [rowScreen], 2
   add dword [rbp-4], 1
.L2:
   cmp dword [rbp-4], DimMatrix
   jl .L3
   
   mov dword[rowScreen], 8
   
   call gotoxyP1
   movzx eax, byte [moves]
   add al, '0'
   mov byte [charac], al
   call printchP1
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Buscar donde está el espacio en blanco dentro de la matriz (tiles), 
; y actualizar la posición (spacePos) del espacio dentro de la matriz.
; Recorrer toda la matriz por filas de izquierda a derecha y de arriba a bajo.
; Si el número de espacios no es 1 (spacePos = sizeMatrix).
; Para recorrer la matriz en ensamblador el índice va de 0 (posición [0][0])
; a 9 (posiciones [2][2]) con incrementos de 1 porquè los datos son de
; tipo char(BYTE) 1 byte.
; 
; Variables globales utilizadas:   
; (tiles)   : Matriz donde guardamos las fichas del juego.
; (spacePos): Posición del espacio dentro de la matriz.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
getSpacePosP1:
   push rbp
   mov  rbp, rsp
   ;Empieza               
   mov dword [rbp-4], 0
   mov dword [rbp-8], 0
   mov dword [rbp-12], 0
   mov dword [rbp-16], 0
   jmp .L2
.L3:
   mov dword [rbp-20], 0
   jmp .L4
.L5:
   mov eax, [rbp-16]
   sal eax, 2
   add eax, [rbp-20]
   cmp byte [tiles+eax], ' '
   jne .L6
   add dword [rbp-8], 1
   mov eax, [rbp-12]
   mov dword [spacePos], eax
.L6:
   add dword [rbp-12], 1
   add dword [rbp-20], 1
.L4:
   cmp dword [rbp-20], DimMatrix
   jl .L5
   add dword [rbp-16], 1
.L2:
   cmp dword [rbp-16], DimMatrix
   jl .L3
   
   cmp dword [rbp-8], 1
   je .L7
   
   mov eax, SizeMatrix
   mov dword [spacePos], eax
.L7:
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Posicionar el cursor en la pantalla, dentro del panel, en función de
; la variable (cursorPos).
; Para calcular la posición del cursor a pantalla (rowScreen) y
; (colScreen) utilizar estas fórmulas:
; rowScreen=12+(cursorPos/DimMatrix)*2
; colScreen= 8+(cursorPos%DimMatrix)*4
; Para posicionar el cursor llamar a la subrutina gotoxyP1.
; 
; Variables globales utilizadas:   
; (cursorPos): Posición del cursor en la matriu (tiles).
; (rowScreen): Fila de la pantalla donde posicionamos el cursor.
; (colScreen): Columna de la pantalla donde posicionamos el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
posCurScreenP1:
   push rbp
   mov  rbp, rsp
   ;Empieza
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   imul eax, 2
   add eax, 12
   mov dword [rowScreen], eax
   
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   mov eax, edx
   imul eax, 4
   add eax, 8
   mov dword [colScreen], eax
   
   call gotoxyP1
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mover el cursor en la dirección indicada por la variable (charac),
; ('i':arriba, 'k':bajo, 'j':izquierda o 'l':derecha).
; Actualizar la variable (cursorPos) controlando que
; no salga del tablero.
;
; No se debe posicionar el cursor en la pantalla.
;
; Variables globales utilizadas:
; (charac)   : Carácter leído de teclado.
; (cursorPos): Posición del cursor en la matriz (tiles).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
moveCursorP1:
   push rbp
   mov  rbp, rsp 
   ;Empieza
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-4], eax
   
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-8], eax
   
   cmp byte [charac], 'i'
   jne .L2
   cmp dword [rbp-4], 0
   jle .L7
   sub dword [cursorPos], DimMatrix
   jmp .L7
   
.L2:
   cmp byte [charac], 'k'
   jne .L3
   mov eax, dword [rbp-4]
   add eax, 1
   cmp eax, DimMatrix
   jge .L7
   add dword [cursorPos], DimMatrix
   jmp .L7
   
.L3:
   cmp byte [charac], 'j'
   jne .L4
   cmp dword [rbp-8], 0
   jle .L7
   sub dword [cursorPos], 1
   jmp .L7
   
.L4:
   cmp byte [charac], 'l'
   jne .L7
   mov eax, dword [rbp-8]
   add eax, 1
   cmp eax, DimMatrix
   jge .L7
   add dword [cursorPos], 1
   jmp .L7
   
.L7:
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mover la ficha de la casilla donde está el cursor (cursorPos)
; a la casilla donde está el espacio (spacePos) si están
; de lado (arriba, abajo, izquierda o derecha).
;
; Si la casilla donde está el espacio está al lado de la casilla donde
; está el cursor en la matriz (tiles):
; - Mover la ficha donde está el cursor a la casilla donde está el espacio y
; poner el espacio a la casilla donde está el cursor, en la matriz (tiles).
; Si no, no hacer el movimiento y poner (state=2).
;
; No se debe mostrar la matriz con los cambios, se hace en updateBoardP1.
;
; Variables globales utilizadas:
; (tiles)    : Matriz donde guardamos las fichas del juego.
; (cursorPos): Posición del cursor en la matriz (tiles).
; (spacePos) : Posición del espacio en la matriz (tiles).
; (state)    : Estado del juego.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
moveTileP1:
   push rbp
   mov  rbp, rsp
   ;Empieza
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-4], eax
   
   mov eax, dword [cursorPos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-8], edx
   
   mov eax, dword [spacePos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-12], eax
   
   mov eax, dword [spacePos]
   cdq
   idiv dword [DimMatrix]
   mov dword [rbp-16], edx
   
   mov eax, dword [rbp-4]
   cmp eax, dword [rbp-12]
   jne .L1
   
   mov eax, dword [rbp-8]
   cmp eax, dword [rbp-16]
   je .L2
   dec eax
   cmp eax, dword [rbp-16]
   je .L3
   
   add eax, 2
   cmp eax, dword [rbp-16]
   je .L3
   
.L1:
   mov eax, dword [rbp-8]
   cmp eax, dword [rbp-16]
   jne .L2
   
   mov eax, dword [rbp-4]
   dec eax
   cmp eax, dword [rbp-12]
   je .L3
   
   add eax, 2
   cmp eax, dword [rbp-12]
   
.L3:
   mov eax, dword [rbp-12]
   imul eax, dword [DimMatrix]
   add eax, dword [rbp-16]
   movzx ecx, byte [tiles + rax]
   mov edx, dword [rbp-4]
   imul edx, dword [DimMatrix]
   add edx, dword [rbp-8]
   mov byte [tiles + rdx], cl
   
   mov byte [tiles + rdx], ' '
   jmp .L4

.L2:
   mov dword [state], 2

.L4:
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Verificar si se han agotado los movimentos.
; Si (moves == 0) poner (state=3).
; 
; Variables globales utilizadas:   
; (moves): Movimientos que quedan para ordenar les fichas
; (state): Estado del juego.
;          3: Pierdes, no quedan movimientos.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
checkEndP1:
   push rbp
   mov  rbp, rsp
   ;Empieza
   cmp dword  [moves], 0
   jne .L1
   
   mov dword  [state], 3
  
.L1:
   ;Acaba
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Mostrar un mensaje debajo del tablero según el valor de la variable 
; (state) llamando a la función printMessageP1_C().
; 
; Variables globales utilizadas:   
; (status)   : Estado del juego.
; (rowScreen): Fila de la pantalla donde posicionamos el cursor.
; (colScreen): Columna de la pantalla donde posicionamos el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printMessageP1:
   push rbp
   mov  rbp, rsp
   ;guardamos el estado de los registros del procesador porque
   ;las funciones de C no mantienen el estado de los registros.
   
   push rax
   push rbx
   push rcx
   push rdx
   push rsi
   push rdi
   push r8
   push r9
   push r10
   push r11
   push r12
   push r13
   push r14
   push r15
   
   call printMessageP1_C
 
   pop r15
   pop r14
   pop r13
   pop r12
   pop r11
   pop r10
   pop r9
   pop r8
   pop rdi
   pop rsi
   pop rdx
   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret
   
   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Juego del 8-PUZZLE.
; Función principal del juego.
; Permite jugar al juego del 8-PUZZLE llamando todas las funcionalidades.
; 
; Pseudo-código:
; Mostrar el tablero de juego llamando a la función printBoardP1_C.
; Inicializar el estado del juego, (state=1).
; Inicializar los movimientos que se pueden realizar (moves = 9).
; Inicializar la matriz (tiles) con los valores de la matriz (tilesIni)
; llamando la subrutina copyMatrixP1.
; Actualizar el tablero de juego llamando a la subrutina updateBoardP1.
; Busca dónde está el espacio en blanco dentro de la matriz (tiles) llamando
; la subrutina getSpacePosP1.
; Si sólo hay un espacio (spacePos<sizeMatrix) posicionar el
; cursor en el lugar donde está el espacio (cursorPos = spacePos),
; sino, poner (state=5) y mostrar el mensaje para
; indicarlo llamando la subrutina printMessageP1.
; Mientras (state==1) hacer:
;   Posicionar el cursor dentro del tablero llamando a la subrutina posCurScreenP1
;   Leer una tecla (charac) llamando a la subrutina getchP1.
;   Según la tecla leída haremos lo siguiente:
;   - ['i','j','k' o 'l'] desplazar el cursor según la dirección
;     elegida (llamar a la subrutina moveTileP1).
;   - [' '] Mover la ficha de la casilla donde está el cursor llamando a
;     la subrutina moveTileP1, si se puede hacer el movimiento (state!=2)
;     poner el espacio donde ya está el cursor (spacePos=cursorPos)
;     y decrementar los movimientos que quedan (moves).
;   - '<ESC>' (código ASCII 27) poner (state = 0) para salir.
;   Actualizar el tablero de juego llamando a la subrutina updateBoardP1.
;   Verificar si se ha agotado los movimientos llamando la subrutina checkEndP1.
;   Mostrar un mensaje debajo del tablero según el valor de la
;   variable (state) llamando la subrutina printMessageP1.
;   Si no se ha podido hacer movimiento (state == 2) poner
;   (state = 1) para continuar jugando.
; Fin mientras.
;
; Antes de salir, esperar a que se pulse una tecla llamando la subrutina getchP1 para terminar.
; 
; Variables globales utilizadas:   
; (moves)    : Movimientos que quedan para ordenar les fichas.
; (spacePos) : Posición del espacio dentro de la matriz (tiles(.
; (cursorPos): Posición del cursor en la matriz (tiles).
; (charac)   : Carácter a escribir en pantalla.
; (state)    : Estado del juego.
;              1: Continuamos jugando.
;              2: No se ha podido hacer el movimiento.
;              3: Pierdes, no quedan movimientos.
;              5: Error, no se ha encontrado el espacio.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
playP1:
   push rbp
   mov  rbp, rsp
   
   call printBoardP1_C   ;printBoard2_C();
   
   push rax
   push rbx
   
   mov QWORD[moves], 9        ;moves = 9
   mov WORD[state], 1         ;state = 1;
   
   call copyMatrixP1          ;copyMatrixP1_C();
   call updateBoardP1         ;updateBoardP1_C();
   call getSpacePosP1         ;getSpacePosP1_C();         
   cmp  DWORD[spacePos], SizeMatrix     ;if (spacePos < SizeMatrix) {
   jge  playP1_Else
      mov eax, DWORD[spacePos]            
      mov DWORD[cursorPos], eax         ;cursorPos = spacePos;  
      jmp playP1_While
   playP1_Else:               ;} else {
      mov  WORD[state], 5     ;state = 5;
      call printMessageP1     ;printMessageP1_C();
      
   playP1_While:
   cmp  WORD[state], 1        ;while (state == 1)
   jne  playP1_EndWhile       
      call posCurScreenP1     ;posCurScreenP1_C(); 
            
      call getchP1            ;getchP1_C()
      mov  al, BYTE[charac]
      playP1_ReadKey_ijkl:
      cmp al, 'i'
      jl  playP1_ReadKey_Space;(charac>='i')
      cmp al, 'l'
      jg  playP1_ReadKey_Space;(charac<='l')
         call moveCursorP1    ;moveCursorP1_C();
         jmp playP1_ReadKey_End
      playP1_ReadKey_Space:
      cmp al, ' '
      jne playP1_ReadKey_ESC  ;(charac==' ')
         call moveTileP1      ;moveTileP1_C();
         cmp  WORD[state], 2  ;if (state != 2) {
         je  playP1_ReadKey_ESC
            mov eax, DWORD[cursorPos]            
            mov DWORD[spacePos], eax    ;spacePos = cursorPos; 
            dec QWORD[moves]            ;moves--;
            jmp playP1_ReadKey_End
      playP1_ReadKey_ESC:
      cmp al, 27              ;if (charac==27)
      jne playP1_ReadKey_End
         mov WORD[state], 0   ;state = 0  
      playP1_ReadKey_End:

      call updateBoardP1      ;updateBoardP1_C();
      call checkEndP1         ;checkEndP1_C();
      call printMessageP1     ;printMessageP1_C();
      cmp  WORD[state], 2     ;if (state == 2) 
      jne playP1_While
         mov WORD[state], 1   ;state = 1;
   jmp playP1_While
   playP1_EndWhile:

   call getchP1               ;getchP1_C();

   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret
 

Assembly Online Compiler

Write, Run & Share Assembly code online using OneCompiler's Assembly online compiler for free. It's one of the robust, feature-rich online compilers for Assembly language. Getting started with the OneCompiler's Assembly compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as Assembly and start coding.

About Assembly

Assembly language(asm) is a low-level programming language, where the language instructions will be more similar to machine code instructions.

Every assembler may have it's own assembly language designed for a specific computers or an operating system.

Assembly language requires less execution time and memory. It is more helful for direct hardware manipulation, real-time critical applications. It is used in device drivers, low-level embedded systems etc.

Syntax help

Assembly language usually consists of three sections,

  1. Data section

    To initialize variables and constants, buffer size these values doesn't change at runtime.

  2. bss section

    To declare variables

  3. text section

    _start specifies the starting of this section where the actually code is written.

Variables

There are various define directives to allocate space for variables for both initialized and uninitialized data.

1. To allocate storage space to Initialized data

Syntax

variable-name    define-directive    initial-value 
Define DirectiveDescriptionAllocated Space
DBDefine Byte1 byte
DWDefine Word2 bytes
DDDefine Doubleword4 bytes
DQDefine Quadword8 bytes
DTDefine Ten Bytes10 bytes

2. To allocate storage space to un-initialized data

Define DirectiveDescription
RESBReserve a Byte
RESWReserve a Word
RESDReserve a Doubleword
RESQReserve a Quadword
RESTReserve a Ten Bytes

Constants

Constants can be defined using

1. equ

  • To define numeric constants
CONSTANT_NAME EQU regular-exp or value

2. %assign

  • To define numeric constants.
%assign constant_name value

3. %define

  • To define numeric or string constants.
%define constant_name value

Loops

Loops are used to iterate a set of statements for a specific number of times.

mov ECX,n
L1:
;<loop body>
loop L1

where n specifies the no of times loops should iterate.

Procedures

Procedure is a sub-routine which contains set of statements. Usually procedures are written when multiple calls are required to same set of statements which increases re-usuability and modularity.

procedure_name:
   ;procedure body
   ret