;
;---------------------------------------------------------------------------
; Observe el siguiente programa del ATmega328p;
; 	.cseg
;	.org 0
;	call InicializarAyB
;	call ProcesarAyB
;	call ProcesarC
;fin: 	rjmp fin
;
;	  .dseg
;	  .org 500
;TablaA: .byte 100
;TablaB: .byte 100
;TablaC: .byte 200
;
;Complételo escribiendo la subrutina ProcesarAyB, que cuando sea llamada debe 
;procesar las tablas  TablaA y TablaB, que contienen números de 8 bits con 
;signo, para obtener la tabla TablaC, de la siguiente forma: El elemento i-ésimo
;de TablaC se obtiene como el opuesto del valor absoluto del producto del 
;elemento i-ésimo de la TablaA por el i-ésimo de la TablaB. Dicho de otro modo,
; tenemos que:
;
; TablaC[ i ] = - | TablaA[i] x TablaB[i] |
;
;
;Con respecto a si la subrutina ProcesarAyB debe preservar los valores de los 
;registros que usa, debe explicar si es necesario hacerlo o no y actuar
;en consecuencia.
;------------------------------------------------------------------------------
;
;
;
; Varios aspectos a tener en cuenta:
; - Los elementos de la tabla C son de tamaño word. Ésto se deduce por los 
;   tamaños de las TablaX que se dan en el código del enunciado. TablaA y 
;   TablaB tienen 100 bytes cada una, mientras que TablaC el doble. Se sabe
;   que la multiplicación de byte x byte es word y, en este caso, debemos 
;   considerar la totalidad del resultado.
; - Se deberá usar la instrucción MULS para obtener el resultado correcto
;   ya que cada operando es tamaño byte con signo.
; - El resultado siempre debe ser negativo. Por tanto si la multiplicación
;   es negativa no se realizará ningún proceso más pero, en caso contrario,
;   habrá que cambiar el signo del número.
; - Para cambiar el signo de un número de 16 bits podemos usar varias estrate-
;   gias. La primera sería calcular el Ca1 (COM aplicado a parte baja y alta
;   del número) y después sumarle 1 al resultado, la segunda
;   realizar el cálculo de 0 - número y una tercera usando las instrucciones
;   COM y NEG. Si la parte baja es 0, éste se queda como está y aplicamos NEG
;   a la parte alta, en caso contrario, aplicamos NEG a la baja y COM a la alta.
; - Hay que guardar en la pila los registros que esta subrutina use y restaurar-
;   los cuando acabe. Primero escribimos el código, vemos los recursos usados,
;   y añadimos las sentencias PUSH POP al inicio y final de la subrutina.  
;
;   Pseudocódigo:
;
;   Subrutina ProcesarAyB
;	STACK<- RegistrosUsados
;	X <- TablaA   ;Inicializamos X con la dirección de comienzo de TablaA
;	Y <- TablaB   ;Inicializamos Y con la dirección de comienzo de TablaB
;	Z <- TablaC   ;Inicializamos Z con la dirección de comienzo de TablaC
;		      ;X,Y se incrementan de uno en uno, Z de dos en dos	  
;	Cont <- 100   ;Número de elementos de las Tablas A y B
;	hacer	
;		R0 <- (X);
;		X<- X+1;
;		R1 <- (Y);
;		Y <- Y+1;
;		R1:R0 <- R0 X R1;
;		si ( R1[7] == 0)
;			R1:R0 <- -R1:R0
;		finsi
;		(Z) <- R0;
;		Z<-Z+1;
;		(Z) <- R1;
;		Z<-Z+1;
;		Cont <- Cont-1;
;	mientras(Cont!=0);
;	RegistrosUsados<-STACK 
;   Fin ProcesarAyB
;
;  En el pseudocódigo anterior se han usado los registros R1:R0 para depositar
;  los datos de las tablas A y B para su multiplicación. MULS trabaja sólo
;  con registros y el resultado se deposita en R1:R0. De esta forma sólo se
;  necesitan dos registros y no cuatro.
;
;  Note que el cálculo del negativo del número es bastante general y no aporta
;  mucha información de cómo lo vamos a llevar a cabo. A continuación se hace
;  una mejora del pseudocódigo que se aproxime más a la programación en bajo 
;  nivel. 
;
;
;	
;   Subrutina ProcesarAyB
;	STACK<- RegistrosUsados
;	X <- TablaA   ;Inicializamos X con la dirección de comienzo de TablaA
;	Y <- TablaB   ;Inicializamos Y con la dirección de comienzo de TablaB
;	Z <- TablaC   ;Inicializamos Z con la dirección de comienzo de TablaC
;		      ;X,Y se incrementan de uno en uno, Z de dos en dos	  
;	Cont <- 100   ;Número de elementos de las Tablas A y B
;	hacer	
;		R0 <- (X);
;		X<- X+1;
;		R1 <- (Y);
;		Y <- Y+1;
;		R1:R0 <- R0 X R1;
;		si ( R1[7] == 0)
;			si ( R0 == 0)
;				R1 <- Ca2(R1)
;			sino
;				R0 <- Ca2(R0)
;				R1 <- Ca1(R1)
;			fsi
;		finsi
;		(Z) <- R0;	;Importante guardarlo en este orden.Little-endian
;		Z<-Z+1;
;		(Z) <- R1;
;		Z<-Z+1;
;		Cont <- Cont-1;
;	mientras(Cont!=0);
;	RegistrosUsados<-STACK 
;   Fin ProcesarAyB
;
;  
; Posiblemente a la hora de codificar necesitaremos algunos registros adicionales
;
; Código

	.def Cont=r16
	.def Zero=R17

ProcesarAyB: 	push	R31
		push 	R30	;Guardamos Z
		push	R29
		push 	R28	;Guardamos Y
		push 	R27
		push	R26	;Guardamos Z
		push	R1
		push	R0	;Registros usados para la multiplicación
		push	Cont	;Registro que actuará como contador
		push 	Zero	

		ldi	xlow,low(TablaA)	;X <- TablaA  
		ldi	xhigh,high(TablaA)
		ldi	ylow,low(TablaB)	;Y <- TablaB  
		ldi     yhigh,high(TablaB)
		ldi	zlow,low(TablaC)	;Z <- TablaC  
		ldi     zhigh,high(TablaC)

		clr	Zero			;Zero<-0
		ldi 	Cont,100		;Cont <- 100   
	bucle:					;hacer	bucl
		ld	R0,X+			;R0 <- (X);
						;X<- X+1;
		ld 	R1,Y+			;R1 <- (Y);
						;Y <- Y+1;
		muls	R1,R0			;R1:R0 <- R0 X R1;
	si1:	sbrc	R1,7			;si ( R1[7] == 0)
		rjmp	fsi1
	si2:	cp	R0,Zero			;si ( R0 == 0)
		brne	fsi2			;se necesita un registro con ceros
						;porque no se puede usar cpi R0,0
			
		neg	R1			;	R1 <- Ca2(R1)
		rjmp	fsi1
	fsi2:					;fsi2
		neg	r0			;	R0 <- Ca2(R0)
		com	r1			;	R1 <- Ca1(R1)

						;fsi1		
	fsi1:	
		st	Z+,r0			;(Z) <- R0;
						;Z<-Z+1;
		st	Z+,r1			;(Z) <- R1;
						;Z<-Z+1;
		dec	Cont			;Cont <- Cont-1;

		brne	bucle			;mientras(Cont!=0);
						

		pop	Zero
		pop	Cont	;RegistrosUsados<-STACK 
		pop	R0	;Importante extraerlos en orden inverso a su
		pop	R1	;introducción en la pila
		pop	R26
		pop	R27
		pop	R28
		pop	R29
		pop	R30
		pop	R31
		ret		;Fin ProcesarAyB
