section .data               
;Cambiar Nombre y Apellido por vuestros datos.
developer db "_Cristina_ _Vinuesa_",0

;Constante que también está definida en C.
ARRAYDIM equ 5		

section .text            

;Variables definidas en Ensamblador.
global developer  

;Variables globales definidas en C.
extern charac, row, col
extern aSecret, aPlay, pos, state, tries, hX

;Subrutinas de ensamblador que se llaman desde C.
global posCurBoardP1, updatePosP1, updateArrayP1, checkSecretP1
global checkPlayP1, printHitsP1, printSecretPlayP1, playP1

;Funciones de C que es llaman desde ensamblador.
extern clearScreen_C,  gotoxyP1_C, printchP1_C, getchP1_C
extern printBoardP1_C, 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 assignar a registros de tipo 
;;   WORD (2 bytes): ax, bx, cx, dx, si, di, ...., r15w
;;   las de tipo 'int' se tiene que assignar a registros de tipo  
;;   DWORD (4 bytes): eax, ebx, ecx, edx, esi, edi, ...., r15d
;;   las de tipo 'long' se tiene que assignar a registros de tipo 
;;   QWORD (8 bytes): rax, rbx, rcx, rdx, rsi, rdi, ...., r15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Les subrutinas en ensamblador se teneis que implementar son:
;;   posCurBoardP1, updatePosP1, updateArrayP1, 
;;   checkSecretP1, printSecretPlayP1, checkPlayP1, printHitsP1.  
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Esta subrutina se da hecha. NO LA PODÉIS MODIFICAR.
; Situar el cursor en una posición de la pantalla
; llamando a la función gotoxyP1_C.
; 
; Variables globales utilizadas:	
; (row) : Fila de la pantalla donde se situa el cursor.
; (col) : Columna de la pantalla donde se situa 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.
; Leer un carácter desde el teclado sin mostrarlo en la pantalla
; y almacenarlo en la variable (charac) llamando a la función printchP1_C.
; 
; Variables globales utilizadas:	
; (charac) : Carácter que leemos desde el teclado.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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 variable (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
   push rbp

   call getchP1_C
 
   pop rbp
   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 
   

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Posiciona el cursor dentro del tablero según la posición del cursor 
; (pos) de los intentos que quedan (tries). 
; Si estamos entrando la combinación secreta (state==0) nos pondremos en
; la fila 3 (row=3), si estamos entrando una jugada (state!=0) la fila  
; se calcula con la fórmula: (row=9+(ARRAYDIM-tries)*2).
; La columna es calcula con la fórmula (col= 8+(pos*2)).
; Para posicionar el cursor se llama a la subrutina gotoxyP1.
; 
; Variables globales utilizadas:	
; (state) : Estado del juego.
; (tries) : Intentos que quedan.
; (row)   : Fila de la pantalla donde se situa el cursor.
; (col)   : Columna de la pantalla donde se situa el cursor.
; (pos)   : Posición donde está el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
posCurBoardP1:
   push rbp
   mov  rbp, rsp
   
   push rax						;state;
   push rbx						;cálculos fila;
   push rcx						;cálculos columna;

   mov ax, WORD[state]
   pcb_if:				        ;if (state==0) {
   cmp ax, 0					;state == 0;
   jne pcb_if_else
       mov ebx, 3				;row = 3;
       jmp pcb_if_end
   pcb_if_else:					;row = 9+(ARRAYDIM-tries)*2;
       mov ebx, ARRAYDIM		;ARRAYDIM;
       sub ebx, DWORD[tries]	;-tries;
       imul ebx, 2			    ;*2;
       add ebx, 9			    ;9+;
   pcb_if_end:
   
   mov DWORD[row], ebx			;row;
   
   mov ecx, DWORD[pos]			;pos;
   shl ecx, 1				    ;*2;
   add ecx, 8				    ;8+;
   mov DWORD[col], ecx			;col = 8+(pos*2);

   call gotoxyP1

   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Si se ha leído (charac=='j') izquierda o (charac=='k') derecha 
; actualizar la posición del cursor (posición dentro del array de la
; combinación) controlando que no salga de las posiciones del array 
; [0..4] y actualizar el índice del array (pos +/-1) según corresponda. 
; No se puede salir de la zona donde estamos escribiendo (5 posiciones).
;  
; Variables globales utilizadas:	
; (charac) : Carácter leído desde el teclado.
; (pos)    : Posición donde está el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
updatePosP1:
   push rbp
   mov  rbp, rsp

   push rcx							;charac;
   
   mov cl, BYTE[charac]
   up_if1:				        	;if ((charac=='j') && (pos>0)) {
   cmp cl, 'j'						;charac=='j';
   jne up_if1_end
   cmp DWORD[pos], 0				;pos>0;
   jle up_if1_end
       dec DWORD[pos]			    ;pos--;
   up_if1_end:

   up_if2:				        	;if ((charac=='k') && (pos<ARRAYDIM-1) {
   cmp cl, 'k'						;charac=='k';
   jne up_if2_end
   cmp DWORD[pos], (ARRAYDIM-1)    	;pos<ARRAYDIM-1;
   jge up_if2_end
       inc DWORD[pos]			   	;pos++;
   up_if2_end:
   
   pop rcx
   
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Guardar el valor del carácter leído ['0'-'9'] en un array y
; mostrarlo en pantalla.
; Obtenemos el valor  (val) restando 48 (ASCII de '0') a (charac).
; Si (state==0) guardamos el valor (val) en la posición (pos) del array
; (aSecret) y cambiaremos el carácter leído por un '*' (charac='*') 
; para que no se vea la combinación secreta que escribimos.
; Si (state!=0) guardamos el valor (val) en la posició (pos) del array 
; (aPlay).
; Finalmente mostramos el carácter (charac) en pantalla en la posición
; donde está el cursor llamando a la función printchP1_C.
; 
; Variables globales utilizadas:	
; (charac)  : Carácter a mostrar.
; (state)   : Estado del juego.
; (aSecret) : Array con la combinación secreta.
; (aPlay)   : Array con la jugada.
; (pos)     : Posición del array donde guardamos el valor leído [0..4].
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
updateArrayP1:
   push rbp
   mov  rbp, rsp

   push rax								;charac;
   push rbx								;pos;
   push rcx								;val;							
   
   mov al, BYTE[charac]					;charac;
   sub eax, '0'							;-'0';
   mov ecx, eax							;val = (int)(charac-'0');    
   mov ebx, DWORD[pos]
   ua_if:				                ;if (state==0) {
   cmp WORD[state], 0			        ;state == 0;
   jne ua_if_else						
       mov DWORD[aSecret+ebx], ecx		;aSecret[pos]=val;
       mov BYTE[charac], '*'		    ;charac = '*';
       jmp ua_if_end
   ua_if_else:
       mov DWORD[aPlay+ebx], ecx		;aPlay[pos]=val;
   ua_if_end:
   
   call printchP1

   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Verificar que la combinación secreta (aSecret) no tenga el valor -3, 
; (valor inicial), ni números repetidos.
; Para cada elemento del array (aSecret) mirar que no haya un -3
; y que no esté repetido en el resto del array (de la posición 
; siguiente a la actual hasta el final). Para indicar que la combinación
; secreta no es correcta ponemos (secretError=1).
; Si la combinación secreta es correcta, poner (state=1) y vamos 
; a leer jugadas.
; Si la combinación secreta es incorrecta, poner (state=2) para 
; volverla a pedir.
; 
; Variables globales utilizadas:
; (aSecret) : Array con la combinación secreta.
; (state)   : Estado del juego.	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
checkSecretP1:
   push rbp
   mov  rbp, rsp

   push rax							;i;
   push rbx							;aSecret[j];
   push rcx							;secretError;
   push rdx							;j;
   
   mov ecx, 0							;secretError = 0;
   mov eax, 0							;i = 0;
   cs_for1:						    	;for (i=0;i<ARRAYDIM;i++) {
   cmp eax, ARRAYDIM					;i < ARRAYDIM
   jge cs_for1_end
      cs_if1:							;if (aSecret[i]==-3) {
      cmp DWORD[aSecret+eax], -3		;aSecret[i] == -3;
      jne cs_if1_end
          mov ecx, 1					;secretError = 1;
      cs_if1_end:
      mov edx, eax
      inc edx
      cs_for2:							;for (j=i+1;j<ARRAYDIM;j++) {
      cmp edx, ARRAYDIM					;j < ARRAYDIM;
      jge cs_for2_end
          cs_if2:				    	;if (aSecret[i]==aSecret[j]) {
		  mov ebx, [aSecret+edx]		;aSecret[j];
		  cmp [aSecret+eax], ebx		;aSecret[i]==aSecret[j];
          jne cs_if2_end
		      mov ecx, 1				;secretError = 1;
          cs_if2_end
          inc edx						;j++;
          jmp cs_for2
      cs_for2_end:
      inc eax							;i++;
      jmp cs_for1
   cs_for1_end:
   
   cs_if3:						    	;if (secretError==1) {
   cmp ecx, 1
   jne cs_if_else
       mov WORD[state], 2				;state=2;
       jmp cs_if3_end
   cs_if_else:
       mov WORD[state], 1				;state=1;
   cs_if3_end:

   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mostrar una combinación del juego.
; Si (state!=1) mostrar la combinación secreta (aSecret) en la fila 3 (row=3),
; si no, mostrar la jugada (aPlay) en la fila (row = 9+(ARRAYDIM-tr)*2),
; a partir de la columna 8 (col=8).
; Para cada posición del array:
; Posicionar el cursor llamando a la subrutina gotoxyP1
; Si (state!=1) coger valor de la combinación secreta (aSecret),
; si no, coger valor de la jugada (aPlay),
; sumar '0' al valor cogido de l'array para convertirlo a carácter y
; llamar a la subrutina printchP1 para mostrarlo.
; Incrementar la columna de 2 en 2. 
; 
; Variables globales utilizadas:	
; (state)   : Estado del juego.
; (row)     : Fila de la pantalla donde se situa el cursor.
; (col)     : Columna de la pantalla donde se situa el cursor.
; (tries)   : Intentos que quedan.
; (aSecret) : Array con la combinación secreta.
; (aPlay)   : Array con la jugada.
; (charac)  : Carácter a mostrar.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
printSecretPlayP1:
   push rbp
   mov  rbp, rsp
	
   push rax									;i;
   push rbx									;cálculos fila;
   push rcx									;state;	
   push rdx									;aSecret[i];
   push rsi									;aPlay[i];

   mov eax, 0					      		;i = 0;
   mov cx, WORD[state]
   psp_if1:					                ;if (state!=1) {
   cmp cx, 1				            	;state != 1;
   je psp_if1_else
       mov ebx, 3			            	;row = 3;
       jmp psp_if1_end
   psp_if1_else:							;row = 9+(ARRAYDIM-tries)*2;
       mov ebx, ARRAYDIM			        ;ARRAYDIM;
       sub ebx, DWORD[tries]			 	;-tries;
       imul ebx, 2				            ;*2;
       add ebx, 9			                ;9+;
   psp_if1_end:
   mov [row], ebx		            		;row;
   mov DWORD[col], 8				        ;col = 8;
   psp_for:					                ;for (i=0; i<ARRAYDIM; i++) {
   cmp eax, ARRAYDIM			          	;i<ARRAYDIM;
   jge psp_for_end
       call gotoxyP1
       psp_if2:					            ;if (state != 1) {
       cmp cx, 1		           			;state != 1;
       je psp_if2_else
	       mov edx, DWORD[aSecret+eax]
	       add dl, '0'						;+'0';
	       mov BYTE[charac], dl						
	       jmp psp_if2_end
       psp_if2_else:						;charac = aPlay[i]+'0';
           mov esi, DWORD[aPlay+eax]
           add sil, '0'						;+'0';
           mov BYTE[charac], sil
       psp_if2_end:	
       call printchP1
       add DWORD[col], 2			        ;col = col + 2;
       inc eax								;i++;
       jmp psp_for
   psp_for_end:
   
   pop rdx
   pop rcx
   pop rbx
   pop rax

   mov rsp, rbp
   pop rbp
   ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cuenta los aciertos en el sitio de la jugada (aPlay) 
; respecto de la combinación secreta (aSecret).
; Comparar cada elemento de la combinación secreta (aSecret) con
; el elemento que hay en la misma posición de la jugada (aPlay).
; Si un elemento de la combinación secreta (aSecret[i]) es igual 
; al elemento de la misma posición de la jugada (aPlay[i]): será un 
; acierto en el sitio 'X' y se tiene que incrementar los aciertos en el
; sitio (hX++).
; Si todas las posiciones de la combinación secreta (aSecret) y de la jugada
; (aPlay) son iguales (hX=ARRAYDIM) hemos ganado y se tiene que modificar 
; el estado del juego para indicarlo (state=3).
; Mostrar los aciertos en el sitio en el tablero de juego llamando 
; a la subrutina printHitsP1.
; 
; Variables globales utilizadas:	
; (aSecret) : Array con la combinación secreta.
; (aPlay)   : Array con la jugada.
; (state)   : Estado del juego.
; (tries)   : Intentos que quedan.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
checkPlayP1:
   push rbp
   mov  rbp, rsp
   
   push rax								;i;
   push rbx								;hX;
   push rcx								;aPlay[i]		
   
   mov eax, 0				        	;i = 0;
   mov bx, 0				        	;hX = 0;
   cp_for:				            	;for (i=0;i<ARRAYDIM;i++) {
   cmp eax, ARRAYDIM			    	;i<ARRAYDIM;
   jge cp_for_end
       cp_if1:				        	;if (aSecret[i]==aPlay[i]) {
       mov ecx, DWORD[aPlay+eax]
       cmp DWORD[aSecret+eax], ecx		;aSecret[i]==aPlay[i];
       jne cp_if1_end
           inc bx			       		;hX++;
       cp_if1_end:
       inc eax				        	;i++;
       jmp cp_for
   cp_for_end:
   cp_if2:				            	;if (hX==ARRAYDIM) {
   cmp bx, ARRAYDIM			    		;hX == ARRRAYDIM
   jne cp_if2_end
       mov WORD[state], 3		    	;state = 3;
   cp_if2_end:
   
   call printHitsP1
  
   pop rdx
   pop rcx
   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Mostrar los aciertos en el sitio.
; Situar el cursor en la fila (9+(ARRAYDIM-tries)*2) y la columna 
; (col = 22) (parte derecha del tablero) para mostrar los aciertos.
; De muestran tantas 'X' como aciertos en el sitio haya (hX).
; Para mostrar los aciertos se tiene que llamar a la subrutina gotoxyP1 
; para posicionar el cursor y printchP1 para mostrar los caracteres. 
; Cada vez que se muestra un acierto se tiene que incrementar en 2 la 
; columna.
; NOTA: (hX tiene que ser siempre menor o igual a ARRAYDIM).
; 
; Variables globales utilizadas:	
; (row)     : Fila de la pantalla donde posicionamos el cursor.
; (col)     : Columna de la pantalla donde posicionamos el cursor.
; (tries)   : Intentos que quedan.
; (charac)  : Carácter a mostrar.
; (hX)      : Aciertos en el sitio.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printHitsP1:
   push rbp
   mov  rbp, rsp
   
   push rax						;cálculos fila;
   push rbx						;i;
   
   mov bx, [hX]					;i=hX;
   mov eax, ARRAYDIM			;ARRAYDIM;
   sub eax, DWORD[tries]		;-tries;
   shl eax, 1				    ;*2;
   add eax, 9				    ;9+;
   mov [row], eax				;row = 9+(ARRAYDIM-tries)*2;
   mov DWORD[col], 22			;col = 22;
   mov BYTE[charac], 'X'		;charac = 'X';
   ph_for:				        ;for (i=hX;i>0;i++) {
   cmp bx, 0				    ;i>0;
   jle ph_for_end
       call gotoxyP1_C
       call printchP1_C
       add DWORD[col], 2		;col = col + 2;
       dec bx				    ;i--;
       jmp ph_for
   ph_for_end:

   pop rbx
   pop rax
   
   mov rsp, rbp
   pop rbp
   ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Aquesta subrutina es dóna feta. NO LA PODEU MODIFICAR.
; Mostrar un mensaje en la parte inferior derecha del tablero según el 
; valor de la variable (state).
; (state) : 0: Estamos entrando la combinación secreta, 
;           1: Estamos entrando la jugada.
;           2: La combinación secreta tiene los valores iniciales o valores repetidos.
;           3: Se ha ganado, jugada = combinación secreta.
;           4: Se han agotado las jugadas.
;           5: Se ha pulsado ESC para salir.
; Se espera que se pulse una tecla para continuar. 
; Mostrar un mensaje debajo del tablero para indicarlo 
; y al pulsar una tecla lo borra.
; 
; Variables globales utilizadas:	
; (row)   : Fila de la pantalla donde se situa el cursor.
; (col)   : Columna de la pantalla donde se situa el cursor.
; (state) : Estado del juego.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printMessageP1:
   push rbp
   mov  rbp, rsp
   ;guardem l'estat dels registres del processador perquè
   ;les funcions de C no mantenen l'estat dels registres.
   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
   push rbp

   call printMessageP1_C
 
   pop rbp
   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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Aquesta subrutina es dóna feta. NO LA PODEU MODIFICAR.
; Subrutina principal del juego
; Leer la combinación secreta y verificar que sea correcta.
; A continuación se lee una jugada, compara la jugada con la
; combinación secreta para determinar si son iguales.
; Repetir el proceso mientras no se acierte la combinación secreta y 
; mientras queden intentos. Si se pulsa la tecla 'ESC' durante la 
; lectura de la combinación secreta o de una jugada salir.
; 
; Pseudo código:
; El jugador dispone de 5 intentos para acertar la combinación secreta,
; el estado inicial del juego es 0 y el cursor ese pone en la posición 0.
; Mostrar el tablero de juego llamando la función printBoardP1_C.
; Mostrar un mensaje indicando que se tiene que entrar la combinación
; secreta llamando a la subrutina printMessageP1.
; Mientras (state==0) leer la combinación secreta o (state==2) leer 
; la combinación secreta porque no era correcta:
; - Poner el estado inicial del juego a 0 (state=0).
;   Mientras no se pulse (ESC) o (ENTER):
;   - Posicionar el cursor en el tablero llamando a la subrutina posCurBoardP1.
;   - Leer una tecla llamando a la subrutina getchP1.
;   - Si se ha leído una 'j'(izquierda) o una 'k' (derecha) mover el 
;     cursor por las 5 posiciones de la combinación, actualizando 
;     el índice del array (pos +/-1) llamando a la subrutina updatePosP1.
;     (no se puede salir de la zona donde estamos escribiendo (5 posiciones))
;   - Si se ha leído un carácter válido ['0'-'9'] lo guardamos en el array
;     (aSecret), si (status==0) cambiaremos el carácter leído por un 
;     '*' para que no se vea la combinación secreta que escribimos y
;     mostramos el carácter en pantalla en la posición donde está el
;     cursor llamando a la función updateArrayP1_C.
;   - Si se ha leído un ESC(27) poner (state=5) para salir.
; 
;   Si no se ha pulsado la tecla (ESC) (state!=5) llamar a la subrutina
;   checkSecretP1 para verificar si la combinación secreta tiene un -3
;   o números repetidos y mostrar un mensaje llamando a la subrutina
;   printMessageP1 indicando que ya se pueden entrar jugadas (state=1) 
;   si la combinación secreta es correcta o que la combinación secreta 
;   no es correcta (state=2).
; 
;  Mientras (state==1) estamos introduciendo jugadas:
;  - Inicializar la posición del cursor a 0 (pos=0).
;  - Mostrar los intentos que quedan (tries) para acertar la combinación 
;    secreta, situar el cursor a la fila 21, columna 5 llamando a la subrutina
;    gotoxyP1 y mostrar el carácter asociado al valor de la variable
;    (tries) sumando '0' y llamando a la subrutina printchP1.
;  - Mostrar la jugada que tenemos en el array (aPlay), inicialmente 
;    será ("00000") y se podrá modificar.
;    Mientras no se pulse (ESC) o (ENTER):
;     - Posicionar el cursor en el tablero llamando a la subrutina posCurBoardP1.
;     - Leer una tecla llamando a la subrutina getchP2.
;     - Si se ha leído una 'j'(izquierda) o una 'k' (derecha) actualizar
;       la posiciób del cursor, índice del array, (pos +/-1) llamando a 
;       la subrutina updatePosP1.
;       (no se puede salir de la zona donde estamos escribiendo (5 posiciones)).
;     - Si se ha leído un carácter válido ['0'-'9'] lo guardamos en el
;       array (aPlay) y mostramos el carácter en pantalla en la posición 
;       donde está el cursor llamando a la funció updateArrayP1_C.
;     - Si se ha leído un ESC(27) poner (state=5) para sortir.
; 
;    Si no se ha pulsado (ESC)(state!=5) llamar a la subrutina chekPlaysP1 
;    para contar los aciertos en el lugar de la jugada (aPlay)
;    respecto de la combinación secreta (aSecret), si la jugada es igual,
;    posición a posición, en la combinación secreta, hemos ganado (state=3).
;    Decrementamos los intentos (tries), y si no quedan intentos (tries==0) y
;    no hemos acertado la combinación secreta (state==1), hemos perdido (state=4).
; 
; Para acabar, mostrar la combinación secreta llamando a la subrutina
; printSecretPlayP1. Mostrar los intentos que quedan (tries) para 
; acertar la combinación secreta, situar el cursor en la fila 21, 
; columna 5 llamando a la subrutina gotoxyP1 y mostrar el carácter asociado 
; al valor de la variable (tries) sumando '0' y llamando a la subrutina
; printchP1, finalmente mostrar el mensaje indicando cual ha sido  
; el motivo llamando a la subrutina printMessageP1.
; Se acaba el juego.
; 
; Variables globales utilizadas:	
; (state)  : Estado del juego.
; (tries)  : Intentos que quedan.
; (pos)    : Posición donde está el cursor.
; (charac) : Carácter leído desde el teclado y a mostrar.
; (row)    : Fila de la pantalla donde se situa el cursor.
; (col)    : Columna de la pantalla donde se situa el cursor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
playP1:
   push rbp
   mov  rbp, rsp 
   
   push rcx
   
   mov  WORD[state], 0
   mov  DWORD[tries], 5
   mov  DWORD[pos], 0
   
   call printBoardP1_C        ;printBoardP1_C();
   call printMessageP1        ;printMessageP1_C();

   P1_while1:
   cmp WORD[state], 0         ;while (state == 0 
   je  P1_while1ok
   cmp WORD[state], 2         ;|| state==2) {
   jne P1_endwhile1
     P1_while1ok:
     mov WORD[state], 0       ;state=0;
     P1_do1:                  ;do {
       call posCurBoardP1     ;posCurBoardP1_C();
       call getchP1           ;charac = getchP1_C();
       mov  cl, BYTE[charac]
   
       cmp cl, 'j'            ;if ((charac=='j') 
       je  P1_if11
       cmp cl, 'k'            ;|| (charac=='k')){
       jne P1_endif11        
       P1_if11:
         call updatePosP1     ;pos = updatePosP1_C();
       P1_endif11:            ;}
       
       cmp cl, '0'            ;if (charac>='0' 
       jl P1_endif12
       cmp cl, '9'            ;&& charac<='9'){  
       jg P1_endif12
         call updateArrayP1   ;updateArrayP1_C();
       P1_endif12:            ;}
       
       cmp cl, 27             ;if (charac== 27) {
       jne P1_endif13
         mov WORD[state], 5   ;state = 5;    
       P1_endif13:            ;}
       
     cmp cl,10                ;} while ((c!=10) 
     je  P1_enddo1
     cmp cl, 27               ;&& (charac!=27)); 
     jne P1_do1
     P1_enddo1:              
     
     cmp WORD[state], 5       ;if (state!=5) {
     je  P1_endif14
       call checkSecretP1     ;checkSecretP1_C();
       call printMessageP1    ;printMessageP1_C();
     P1_endif14:              ;}
     
   jmp P1_while1 
   P1_endwhile1:              ;}
     
   P1_while2:                 ;while (state == 1)
   cmp WORD[state], 1                
   jne  P1_endwhile2
     mov  DWORD[pos], 0       ;pos=0;
     mov  DWORD[row], 21
     mov  DWORD[col], 5
     call gotoxyP1            ;gotoxyP1_C();
     mov  edi, DWORD[tries]
     add  dil, '0'
     mov  BYTE[charac], dil   ;charac=tries + '0';
     call printchP1           ;printchP1_C();
     call printSecretPlayP1   ;printSecretPlayP1_C();

     P1_do2:                  ;do {
       call posCurBoardP1     ;posCurBoardP1_C();
       call getchP1           ;getchP1_C();
	   mov  cl, BYTE[charac]
	   
       cmp cl, 'j'            ;if ((charac=='j') 
       je  P1_if21
       cmp cl, 'k'            ;|| (charac=='k')){
       jne P1_endif21        
       P1_if21:
         call updatePosP1     ;pos = updatePosP1_C();     
       P1_endif21:            ;}
       
       cmp cl, '0'            ;if (charac>='0' 
       jl P1_endif22
       cmp cl, '9'            ;&& charac<='9'){  
       jg P1_endif22
         call updateArrayP1   ;updateArrayP1_C();
       P1_endif22:            ;}
       
       cmp cl, 27             ;if (charac == 27) {
       jne P1_endif23
         mov WORD[state], 5   ;state = 5;    
       P1_endif23:            ;}
       
     cmp cl,10                ;} while ((charac!=10) 
     je  P1_enddo2
     cmp cl, 27               ;&& (charac!=27)); 
     jne P1_do2
     P1_enddo2:              
     
     cmp WORD[state], 5              ;if (state!=5) {
     je  P1_endif24
       call checkPlayP1       ;checkPlayP1_C();
	   dec DWORD[tries]       ;tries--;
	   cmp DWORD[tries], 0    ;if (tries == 0 
	   jne P1_endif25
	   cmp WORD[state], 1     ;&& state == 1) {
	   jne P1_endif25
         mov WORD[state], 4   ;state = 4;   
       P1_endif25:            ;}
     P1_endif24:              ;}
     
   jmp P1_while2
   P1_endwhile2:              ;} 
   
   mov  DWORD[row], 21
   mov  DWORD[col], 5
   call gotoxyP1              ;gotoxyP1_C();
   mov  edi, DWORD[tries]
   add  dil, '0'
   mov  BYTE[charac], dil     ;charac=tries + '0';
   call printchP1             ;printchP1_C();
   call printSecretPlayP1     ;printSecretPlayP1_C();
   call printMessageP1        ;printMessage_C();
   P1_end:
   
   pop rcx
   
   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